Разумный (r) способ получить кодировку символов CLI в Mac OS X? - PullRequest
4 голосов
/ 18 июня 2010

Я писал CLI-Tool для Mac OS X (10.5+), который должен иметь дело с аргументами командной строки, которые могут содержать символы не ASCII.

Для дальнейшей обработки я преобразуюэти аргументы, использующие + [NSString stringWithCString: encoding:].

Моя проблема в том, что я не смог найти хорошую информацию о том, как определить кодировку символов, используемую оболочкой, в которой работает указанный cli-toolв.
В качестве решения я пришел к следующему:

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];

Однако я нахожу это немного грубым - что заставляет меня думать, что я упустил что-то очевидное ... ноЧто?

Есть ли более разумный способ добиться того же самого?

Заранее спасибо

D

Ответы [ 3 ]

1 голос
/ 02 июля 2015

Разве вы не можете просто использовать [[NSProcessInfo processInfo] arguments]?

1 голос
/ 19 июня 2010

Ответ зависит от того, из чего исходит неприязнь.

  1. В OS X переменная окружения LANG не не отражает выбор языка в графическом интерфейсе. Очень немногие люди установят LANG в командной строке.
  2. Выбор «системной кодировки» в графическом интерфейсе хранится в ~/.CFUserTextEncoding и может быть получен CFStringGetSystemEncoding, см. Этот Apple doc .
  3. Тем не менее, эта "системная кодировка" редко используется , за исключением очень старых, не поддерживающих Юникод программ. Любая здравомыслящая программа Какао использует только Юникод и больше ничего.
  4. В частности, путь к файлу на уровне Какао всегда кодируется (вариант) UTF-8. Итак, чтобы получить NSString из строки C, используйте

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

    и чтобы получить C-строку для пути к файлу из NSString, используйте

     char*path=[string fileSystemRepresentation];
    

    Здесь рекомендуется не использовать просто [string UTF8String], из-за тонкости см. Apple doc .

  5. Итак, я рекомендую вам не заботиться о кодировке и просто предположить UTF-8.

  6. Тем не менее, может быть очень небольшое количество людей, которые задают LANG в командной строке, и вы можете позаботиться о них. Тогда то, что вы сделали, это единственное, что я могу придумать.
0 голосов
/ 05 июля 2010

Ладно, похоже, их нет!

Как указал Юджи, основная кодировка имен файлов - это UTF-8, несмотря ни на что. Следовательно, необходимо обработать два сценария :

  1. Аргументы, вводимые пользователем, символ за персонажем.
  2. Аргументы, которые завершаются табуляцией или вывод команд типа ls, так как они не преобразуют символы.

Второй случай просто охвачен предположением UTF-8.

Первый случай, однако, проблематичен:

  • В Mac OS 10.6 $ LANG содержит IANA-имя используемой кодировки, например de_DE.IANA_NAME.
  • До Snow Leopard это не так для кодировок, отличных от UTF-8!

Я не проверял каждый набор символов, который мог придумать, но ни один из европейских не был включен. Вместо этого только $ LANG был языковым языком (de_DE в моем случае)!

Поскольку результаты вызова +[NSString stringWithCString:encoding:] с неправильной кодировкой не определены , вы не можете с уверенностью предположить, что в этом случае он вернет nil (если, например, это Только для ASCII, это может прекрасно работать!).

Что добавляет к общему беспорядку, так это то, что $LANG не гарантируется , чтобы быть рядом, в любом случае: в настройках Terminal.app есть флажок, который позволяет пользователю вообще не устанавливать $LANG (не говоря уже о X11.app, который, кажется, не обрабатывает входные данные не ASCII ...).

Так что же осталось:

  1. Проверка на наличие $LANG. Если он не установлен, перейдите к: 4!
  2. Проверьте, содержит ли $LANG информацию о кодировке. Если это не так, Goto: 4!
  3. Проверьте, существует ли кодировка UTF-8. Если это Гото: 6, иначе ...
  4. Если argc больше 2 и [[NSString stringWithCString: argv[0] encoding: NSUTF8StringEncoding] isEqualToString: yourForceUTFArgumentFlag], распечатайте, что вы сейчас принудительно используете UTF-8 и перейдите к 6. Если нет:
  5. Предположим, вы ничего не знаете, выдайте предупреждение о том, что ваш пользователь должен установить кодировку терминала в UTF-8 и может рассмотреть возможность передачи yourForceUTFArgumentFlag в качестве первого аргумента и exit () .
  6. Предположим, UTF-8 и делать то, что вы должны ...

Звучит дерьмово? Это потому, что это так, но я не могу придумать какой-либо разумный способ сделать это.


Еще одно замечание: Если вы используете UTF-8 в качестве кодировки, stringWithCString: encoding: возвращает ноль всякий раз, когда встречается не-ASCII-символы в C-строке, которая не закодирована в UTF-8.)

...