Pertanyaan Sane (r) cara mendapatkan pengkodean karakter CLI di Mac OS X?


Saya sedang menulis CLI-Tool untuk Mac OS X (10.5+) yang harus berurusan dengan argumen baris perintah yang sangat mungkin mengandung karakter non-ASCII.

Untuk pemrosesan lebih lanjut, saya mengubah argumen ini menggunakan + [NSString stringWithCString: encoding:].

Masalah saya adalah, bahwa saya tidak dapat menemukan informasi yang baik tentang cara menentukan pengkodean karakter yang digunakan oleh shell di mana kata cli-tool sedang berjalan.
Apa yang saya temukan sebagai solusi adalah sebagai berikut:

NSDictionary *environment = [[NSProcessInfo processInfo] environment];
NSString *ianaName = [[environment objectForKey:@"LANG"] pathExtension];
NSStringEncoding encoding = CFStringConvertEncodingToNSStringEncoding(
  CFStringConvertIANACharSetNameToEncoding( (CFStringRef)ianaName ) );

NSString *someArgument = [NSString stringWithCString:argv[someIndex] encoding:encoding];

Saya menemukan bahwa sedikit mentah, namun - yang membuat saya berpikir bahwa saya melewatkan sesuatu yang jelas ... tapi apa?

Apakah ada cara yang lebih bersih / bersih untuk mencapai dasarnya sama?

Terima kasih sebelumnya

D


4
2018-06-18 16:20


asal


Jawaban:


Jawabannya tergantung pada apa yang non-asciiness berasal.

  1. Di OS X, variabel lingkungan LANG tidak tidak mencerminkan pilihan bahasa di GUI. Sangat sedikit orang yang akan mengatur LANG di baris perintah.
  2. Pilihan "pengkodean sistem" pada GUI disimpan di dalamnya ~/.CFUserTextEncoding, dan dapat diperoleh dengan CFStringGetSystemEncoding, Lihat ini Dokumen Apple.
  3. Yang mengatakan, "sistem pengkodean" ini jarang digunakan kecuali dalam perangkat lunak yang sangat awet, bukan unicode yang sadar. Setiap program Cocoa yang waras hanya menggunakan Unicode dan tidak ada yang lain.
  4. Secara khusus, path file pada level Cocoa selalu dikodekan dalam (varian) UTF-8. Jadi, untuk mendapatkan NSString dari string C, gunakan

     NSString*string=[NSString stirngWithCString:cString encoding:NSUTF8Encoding];
    

    dan mendapatkan C-string untuk path file dari NSString, gunakan

     char*path=[string fileSystemRepresentation];
    

    Di sini dianjurkan untuk tidak menggunakan saja [string UTF8String], karena kehalusannya, lihat ini Dokumen Apple.

  5. Jadi, saya menyarankan Anda untuk tidak peduli tentang pengkodean dan hanya menganggap UTF-8.

  6. Konon, mungkin ada sejumlah kecil orang yang menetapkan LANG pada baris perintah, dan Anda mungkin ingin merawatnya. Kemudian, apa yang Anda lakukan adalah satu-satunya hal yang dapat saya temukan.

1
2018-06-19 03:34



Tidak bisa kamu gunakan saja [[NSProcessInfo processInfo] arguments]?


1
2017-07-02 05:09



Oke, ternyata sepertinya tidak ada satu pun!

Seperti yang ditunjukkan Yuji, penyandian nama file yang mendasari adalah UTF-8, tidak peduli apa. Karena itu, yang perlu ditangani dua skenario:

  1. Argumen yang diketikkan, karakter untuk karakter, oleh pengguna.
  2. Argumen yang selesai tab atau output dari perintah seperti ls, karena mereka tidak mengonversi karakter apa pun.

Kasus kedua hanya ditutupi oleh asumsi UTF-8.

Kasus pertama, bagaimanapun, bermasalah:

  • Pada Mac OS 10.6, $ LANG berisi nama IANA dari pengkodean yang digunakan seperti de_DE.IANA_NAME.
  • Sebelum Snow Leopard, ini bukan kasusnya untuk charsets selain UTF-8!

Saya tidak menguji masing-masing dan setiap charset yang dapat saya pikirkan, tetapi tidak ada yang termasuk di dalamnya. Sebagai gantinya, $ LANG hanya merupakan bahasa-lokal (de_DE dalam hal ini)!

Karena hasil pemanggilan +[NSString stringWithCString:encoding:] dengan pengkodean yang salah tidak terdefinisi, Anda tidak dapat dengan aman berasumsi bahwa itu akan kembali nildalam hal itu * (jika mis. hanya ASCII saja, mungkin berfungsi dengan baik!).

Apa yang menambah kekacauan secara keseluruhan adalah itu $LANG  tidak guarateed berada di sekitar, bagaimanapun: Ada kotak centang di preferensi Terminal.app, yang memungkinkan pengguna untuk tidak disetel $LANG sama sekali (tidak berbicara tentang X11.app yang tampaknya tidak menangani input non-ASCII ...).

Jadi apa yang tersisa:

  1. Periksa keberadaan $LANG. Jika tidak disetel, Goto: 4!
  2. Periksa apakah $LANG mengandung informasi tentang pengkodean. Jika tidak, Goto: 4!
  3. Periksa apakah pengkodean yang Anda temukan di sana adalah UTF-8. Jika itu Goto: 6, yang lain ...
  4. Jika argc lebih besar dari 2 dan [[NSString stringWithCString: argv[0] encoding: NSUTF8StringEncoding] isEqualToString: yourForceUTFArgumentFlag], cetak bahwa Anda sedang memaksa UTF-8 sekarang dan Goto 6. Jika tidak:
  5. Asumsikan Anda tidak tahu apa-apa, mengeluarkan peringatan bahwa pengguna Anda harus mengatur pengkodean Terminal ke UTF-8 dan dapat mempertimbangkan untuk lewat yourForceUTFArgumentFlag sebagai argumen pertama dan keluar().
  6. Asumsikan UTF-8 dan lakukan apa yang harus Anda ...

Kedengarannya menyebalkan? Itu karena itu, tapi aku tidak bisa memikirkannya saner cara melakukannya.


Satu catatan lebih lanjut meskipun: Jika Anda menggunakan UTF-8 sebagai encoding, stringWithCString: encoding: mengembalikan nil setiap kali bertemu karakter non-ASCII dalam C-String yang tidak dikodekan dalam UTF-8.)


0
2017-07-05 18:39