Objective c 在Mac OS X中获取CLI字符编码的合理(r)方法?
我正在为MacOSX(10.5+)编写一个CLI工具,它必须处理命令行参数,这些参数很可能包含非ASCII字符 为了进一步处理,我使用+[NSString stringWithCString:encoding:]转换这些参数 我的问题是,我找不到关于如何确定运行所述cli工具的shell使用的字符编码的好信息。Objective c 在Mac OS X中获取CLI字符编码的合理(r)方法?,objective-c,command-line,foundation,Objective C,Command Line,Foundation,我正在为MacOSX(10.5+)编写一个CLI工具,它必须处理命令行参数,这些参数很可能包含非ASCII字符 为了进一步处理,我使用+[NSString stringWithCString:encoding:]转换这些参数 我的问题是,我找不到关于如何确定运行所述cli工具的shell使用的字符编码的好信息。 我提出的解决方案如下: NSDictionary *environment = [[NSProcessInfo processInfo] environment]; NSString *
我提出的解决方案如下:
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];
然而,我发现这有点粗糙——这让我觉得我遗漏了一些明显的东西……但是什么呢
是否有一种更明智/更清洁的方法来实现基本相同的目标
提前谢谢
答案取决于非粘性的来源
LANG
并不反映GUI中的语言选择。很少有人会在命令行中设置LANG
李>
~/.cfusertextcodencing
中,可以通过CFStringGetSystemEncoding
获得,请参见此NSString
,请使用
NSString*string=[NSString stirngWithCString:cString encoding:NSUTF8Encoding];
要从NSString
获取文件路径的C字符串,请使用
char*path=[string fileSystemRepresentation];
这里建议不要只使用[string UTF8String]
,由于其微妙之处,请参见此LANG
,而您可能需要照顾他们。那么,你所做的是我唯一能想到的好吧,结果似乎没有 正如Yuji所指出的,文件名的底层编码是UTF-8,不管怎样。因此,需要处理两种情况:
ls
)的输出,因为它们不转换任何字符- 在Mac OS 10.6上,$LANG包含所用编码的IANA名称,如
de_de.IANA_name
- 在使用SnowLeopard之前,字符集的情况并非如此,UTF-8除外强>
de_de
在我的例子中)
由于使用不正确的编码调用+[NSString stringWithCString:encoding://code>的结果,,因此您不能安全地假设在这种情况下它将返回nil
*(例如,如果它仅为ASCII,则可能工作得很好!)
更糟糕的是,$LANG
并没有得到保证,不管怎样:在Terminal.app的首选项中有一个复选框,允许用户根本不设置$LANG
(更不用说X11.app了,它似乎不处理任何非ASCII输入…)
剩下的是:
检查是否存在$LANG
。如果没有设置,转到:4李>
检查$LANG
是否包含编码信息。如果没有,转到:4李>
检查您找到的编码是否为UTF-8。如果是转到:6,否则
如果argc
大于2且[[NSString stringWithCString:argv[0]编码:NSUTF8StringEncoding]IseQualtString:yourForceUTFArgumentFlag]
,则打印您正在强制UTF-8并转到6。如果没有:
假定您不知道任何东西,发出警告,您的用户应该将终端编码设置为UTF-8,并可以考虑传递<代码> UyFuffutfAgMutug标记< /C>作为第一个参数和<强> Ext()<<强> > /LI>。
假设UTF-8,做你必须做的
听起来很糟糕?那是因为它是,但我想不出任何更明智的方法
但还有一点需要注意:
如果您使用UTF-8作为编码,stringWithCString:encoding:每当遇到未在UTF-8中编码的C字符串中的非ASCII字符时,返回nil。)您不能使用[[NSProcessInfo processInfo]参数]
?来澄清一下:我编写的工具不是GUI程序,但是一个命令行工具链接到Foundation.h
;正在进行的字符串转换是从C-string到NSString
。因此,编码取决于命令行环境的设置。它可以很容易地通过Terminal.app的首选项进行更改。我没有直接发表评论,因为我希望得到更多答案;-)好的,非ASCINESS是固有的,因为我的用户是德国人,命令行参数是文件名。更重要的是,这些文件可能会有人的名字,所以我必须处理“魏穆勒”、“厄尔曼”之类的问题。因为这不是一个GUI应用程序,而是一个命令行工具,所以CFStringGetSystemEncoding无法剪切它,因为它与Terminal.app使用的内容无关(就个人而言,我大部分时间在Terminal中使用UTF-8,但~/.CFUserTextEncoding表示默认的“MacRoman”)。还有一件事。。。虽然这与我目前正在做的事情没有多大关系,但谢谢你提到TN1150,因为我不知道!???OSX上的文件名本质上是BSD级别的UTF-8,与终端首选的编码选择无关。(或者至少日本人是这样的