Sane (r) Art und Weise Zeichencodierung des CLI in Mac OS X zu bekommen?
-
28-09-2019 - |
Frage
Ich war ein CLI-Tool für Mac OS X (10.5 und höher) zu schreiben, die mit Befehlszeilenargumenten zu tun hat, die sehr wahrscheinlich Nicht-ASCII-Zeichen enthalten.
Für die weitere Verarbeitung konvertiere ich diese Argumente mit + [NSString stringWithCString: Codieren:].
Mein Problem ist, dass ich nicht gut Informationen finden konnte, wie der Charakter kodierenden zu bestimmen, von der Shell verwendet, bei dem der cli-Werkzeug aktiv ist.
Was kam ich mit als Lösung auf die folgenden:
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];
Ich finde, dass ein wenig roh, aber - was ich denken läßt, dass ich verpasst etwas offensichtlich ... aber etwas
Sie haben einen gesünderen / Reiniger Weg im wesentlichen die gleiche erreichen?
Vielen Dank im Voraus
D
Lösung 3
Okay, es stellt sich heraus, da keine zu sein scheint!
Wie Yuji wies darauf hin, die zugrunde liegende Codierung von Dateinamen ist UTF-8, egal was passiert. Daher benötigt man Griff zwei Szenarien :
- Argumente, die in typisiert sind, Zeichen für Zeichen durch den Benutzer.
- Argumente, die Tabula abgeschlossen sind oder die Ausgabe von Befehlen wie
ls
, da sie konvertieren keine Zeichen.
Der zweite Fall einfach durch die Annahme von UTF-8 abgedeckt ist.
Der erste Fall ist jedoch problematisch:
- Unter Mac OS 10.6, $ LANG enthält die IANA-Namen der verwendeten Codierung wie
de_DE.IANA_NAME
. - Vor Snow Leopard, ist dies nicht der Fall für charsets andere als UTF-8!
Ich habe nicht jeden Test und jede charset könnte ich mir vorstellen, aber keiner der europäischen, wurden eingeschlossen. Stattdessen war $ LANG nur die Sprache-locale (de_DE
in meinem Fall)!
Da die Ergebnisse des Aufrufs +[NSString stringWithCString:encoding:]
mit einer falschen Codierung undefinierte , kann man nicht davon ausgehen, dass es nil
in diesem Fall * zurück ( wenn z. B. seine ASCII-nur, es könnte perfekt funktionieren!).
Was zum Gesamt Chaos fügt hinzu, dass $LANG
ist nicht Guarateed um zu sein, jedenfalls: Es gibt eine Checkbox in Terminal.app-Einstellungen, die es einem Benutzer nicht Set $LANG
überhaupt ermöglicht (nicht zu sprechen von X11.app die jeden nicht-ASCII-Eingang zu handhaben scheint nicht ...).
So was übrig bleibt:
- Überprüfen auf das Vorhandensein von
$LANG
. Wenn es nicht gesetzt ist, Goto: 4 - Überprüfen Sie, ob
$LANG
Informationen über die Codierung enthält. Wenn dies nicht der Fall, Goto: 4 !
- Überprüfen Sie, ob die Codierung Sie finden es UTF-8 ist. Wenn es Goto: 6, sonst ...
- Wenn
argc
größer als 2 und[[NSString stringWithCString: argv[0] encoding: NSUTF8StringEncoding] isEqualToString: yourForceUTFArgumentFlag]
ist, drucken Sie, dass Sie zwingen die UTF-8 jetzt und Springen 6. Falls nicht: - Angenommen, Sie wissen nichts, eine Warnung, dass Ihre Benutzer die Terminal-Codierung auf UTF-8 gesetzt sollte und betrachten kann
yourForceUTFArgumentFlag
als erstes Argument übergeben und exit () . - Nehmen wir UTF-8 und tun, was Sie müssen ...
Sounds beschissen? Das ist, weil es ist, aber ich kann es nicht glauben, von jede saner Art und Weise zu tun.
Eine weitere Notiz aber: Wenn Sie mit UTF-8 als Kodierung, stringWithCString: Codieren:. NIL zurück, wenn es trifft nicht-ASCII-Zeichen in einem C-String, ist nicht codiert in UTF-8)
Andere Tipps
Die Antwort hängt davon ab, was der nicht-asciiness herkommt.
- In OS X, die Umgebungsvariable
LANG
hat nicht spiegeln die Wahl der Sprache in der GUI. Nur sehr wenige Menschen werdenLANG
auf der Kommandozeile gesetzt. - Die Wahl des „System-Codierung“ auf der GUI in
~/.CFUserTextEncoding
gespeichert ist, und kann durchCFStringGetSystemEncoding
erhalten werden, finden Sie in diesem Apple-doc . - sagte, dass diese "System-Codierung" ist selten verwendet außer in einer sehr alten, nicht-Unicode bewusst Software. Jeder vernünftige Cocoa-Programm verwendet nur Unicode und nichts anderes.
-
Insbesondere der Dateipfad auf der Ebene der Cocoa wird immer in (eine Variante) UTF-8 codiert. Also, eine
NSString
von einem C-String zu erhalten, verwenden SieNSString*string=[NSString stirngWithCString:cString encoding:NSUTF8Encoding];
und einen C-String für den Dateipfad bekommen von einem
NSString
, Verwendungchar*path=[string fileSystemRepresentation];
Hier ist es empfehlenswert, nicht nur
[string UTF8String]
zu verwenden, aufgrund der Feinheit finden Sie in diesem Apple-doc . -
Also, ich empfehle Ihnen nicht um die Codierung zu kümmern und nur UTF-8 übernehmen.
- sagte, könnte es eine sehr kleine Anzahl von Menschen, die
LANG
auf der Kommandozeile setzt, und man könnte sie kümmern nehmen. Dann, was Sie getan haben, ist das einzige, was ich mit oben kommen kann.
Können Sie sich nicht [[NSProcessInfo processInfo] arguments]
verwenden?