Проблема с кодировкой строки NSTask

В моей программе я grep-ing через NSTask. По какой-то причине иногда я не получал никаких результатов (хотя код, по-видимому, был таким же, как и команда, запускаемая из CLI, которая работала просто отлично), поэтому я проверил свой код и обнаружил в документации Apple, что при добавлении аргументов в объект NSTask, «объект NSTask преобразует как путь, так и строки в аргументах в соответствующие строки в стиле C (используя fileSystemRepresentation) перед передачей их задаче через argv[]» (snip ).

Проблема в том, что я могу найти такие термины, как «Рио Гальегос». К сожалению (как я проверил с помощью fileSystemRepresentation), он подвергается преобразованию и оказывается «RiÃÅo Gallegos».

Как я могу это решить?

-- Ry


person ryyst    schedule 28.03.2010    source источник


Ответы (1)


Проблема в том, что я могу найти такие термины, как «Рио Гальегос». К сожалению (как я проверил с помощью fileSystemRepresentation), он подвергается преобразованию и оказывается «RiÃÅo Gallegos».

Это одна из возможных интерпретаций. Вы имеете в виду, что «Río Gallegos» преобразуется в «Ri\xcc\x81o Gallegos» — байты UTF-8 для представления разложенного i + сочетания острого ударения.

Ваша проблема в том, что grep не интерпретирует эти байты как UTF-8. grep использует какую-то другую кодировку — по-видимому, MacRoman.

Решение состоит в том, чтобы указать grep использовать UTF-8. Для этого необходимо установить переменную LC_ALL в вашей задаче grep среда.

Быстрым и грязным значением для использования будет «en_US.UTF-8»; более правильным способом было бы получить код языка для основного пользовательского предпочитаемый язык, замените дефис, если он есть, на подчеркивание и в конце вставьте «.UTF-8». того, что.

person Peter Hosey    schedule 29.03.2010
comment
Спасибо за ответ, но это не работает ... Я также пытался установить переменные LC_CTYPE и LANG в среде задачи grep, но все равно не повезло. - person ryyst; 29.03.2010
comment
Как вы определили, что grep интерпретирует байты так, как вы показали в своем вопросе? - person Peter Hosey; 29.03.2010
comment
С помощью метода NSString fileSystemRepresentation и операторов NSLog(). Эксперименты показали, что работают только строки без нестандартных символов, таких как 'í'. Я вижу, что это не доказательство, но убедительное доказательство. - person ryyst; 29.03.2010
comment
И как вы просматриваете вывод NSLog? - person Peter Hosey; 29.03.2010
comment
С помощью консоли отладчика в XCode. - person ryyst; 29.03.2010
comment
Хорошо, тогда. Попробуйте следующее: NSLog(@"%@ = %lu bytes", myString, (unsigned long)strlen([myString fileSystemRepresentation])); Что в этом журнале? - person Peter Hosey; 29.03.2010
comment
Если myString — Río Gallegos (без кавычек), результат будет следующим: Río Gallegos = 14 байт. - person ryyst; 29.03.2010
comment
Кстати, если я попробую: NSLog(@%s = %lu bytes, Río Gallegos, (unsigned long)strlen(Río Gallegos)); Записывается: R√≠o Gallegos = 13 байт. - person ryyst; 29.03.2010
comment
ryyst: Интересно. Этот вывод кажется правильным, поэтому grep действительно неправильно его интерпретирует. Либо так, либо целевой текст действительно не содержит шаблона. (Возможно, целевой текст не является UTF-8 или использует другую форму нормализации? Я не думаю, что grep действительно понимает кодировки или Unicode.) - person Peter Hosey; 30.03.2010
comment
Что ж, запуск grep Río Gallegos ‹filename.txt› действительно показывает результаты, поэтому я думаю, что это действительно проблема с кодировкой. Этот небольшой фрагмент (pastebin.org/128441) показывает, что строки, закодированные с помощью fileSystemRepresentation, на самом деле чрезвычайно ограничены. Я думаю просто об использовании вызовов system(), NSTask меня очень раздражает. - person ryyst; 30.03.2010
comment
райст: Эм. Ну, этот код объясняет это. Во-первых, ни NSTask, ни grep не интерпретируют байты как MacRoman; NSString есть. И он делает это, потому что вы сказали ему. Итак, не делайте этого. Байты имеют формат UTF-8, поэтому интерпретируйте их как таковые. (Кроме того, как вы получаете «Río Gallegos» из указателя на переменную char, которой вы присвоили int?) - person Peter Hosey; 30.03.2010
comment
Хорошо, но даже если я напутал с кодировками во фрагменте, это на самом деле не объясняет проблему, с которой я сталкиваюсь при работе с NSTask, не так ли? Это (lists.apple.com/archives/Cocoa-dev/ 2007/Apr/msg01324.html) также может быть интересным чтением, так как он охватывает именно мою проблему. Однако все они просто говорят, что он должен работать только OOB, что, очевидно, не работает в моем случае... Кстати, я могу выложить весь код, относящийся к NSTask, если это упростит вам задачу. И спасибо за все ваши усилия! - person ryyst; 30.03.2010
comment
Я думаю, нам нужно понять, откуда на самом деле исходит это мистическое «с». Присвоение int переменной char не создает допустимую строку ни в какой кодировке. - person Peter Hosey; 30.03.2010
comment
Хм, я всегда думал, что это способ перечисления символов C - видимо, я ошибаюсь? В любом случае, как эти две проблемы связаны друг с другом? - person ryyst; 30.03.2010
comment
Что ж, код, который вы показываете, крайне маловероятен для получения заявленного вами результата. Вы объявили переменную, содержащую a char — только одну, а не массив. Затем в цикле вы присвоили этой переменной int; при первом проходе по циклу он равен нулю. Затем вы берете адрес этого char и обрабатываете его как строку C; символ в указателе равен нулю, это пустая строка C. Во второй раз в цикле символ в указателе равен 1, а любые символы после этого могут быть любыми — вы получите случайный мусор, почти наверняка не имя человека. - person Peter Hosey; 30.03.2010
comment
Дикая теория: вы хотели представить целое число в виде десятичных цифр? Присвоение переменной char (или массиву char) этого не сделает; единственное «преобразование» — это отсечение неподходящих частей. Присвоение 1, скажем, переменной char поместит в нее 1 (например, 0x01, а не '1', что равно 0x31) байта. Если вы хотели сделать преобразование числа в десятичное представление в строке, используйте stringWithFormat: NSString. - person Peter Hosey; 30.03.2010
comment
Нет, я не пытался создавать полезные строки или что-то в этом роде, я просто хотел перечислить некоторые символы и посмотреть, что с ними сделает fileSystemRepresentation. Теперь я попытался поместить строку с RiÃÅo Gallegos в свой текстовый файл. При передаче Río Gallegos в качестве аргумента моему объекту NSTask он теперь действительно находит добавленную мной строку — grep, по-видимому, действительно неверно интерпретирует аргумент. Я до сих пор не знаю, как заставить NSTask или grep делать то, что они делают сейчас... - person ryyst; 30.03.2010
comment
Что вы имеете в виду под фразой «grep… неправильно интерпретирует аргумент»? Если он находит строку, разве это не означает, что он правильно ее интерпретировал? И зачем вы поместили «Риао Гальегос» в текстовый файл? Вы должны ввести «Río Gallegos» как UTF-8, затем загрузить данные из файла, декодировать данные как UTF-8, чтобы получить строку ( developer.apple.com/mac/library /documentation/Cocoa/Reference/: ) и передайте эту строку задаче. - person Peter Hosey; 31.03.2010
comment
О, и не используйте TextEdit для редактирования файла; это глупо о UTF-8. Вместо этого используйте TextWrangler: barebones.com/products/textwrangler Другой способ — поместить строку в ваш Info.plist. Однако, предполагая, что вы не собираетесь получать настоящую строку, которую будете использовать в своем приложении для доставки, ни из одного из этих источников, вам придется исправить везде, где вы действительно создаете строку. - person Peter Hosey; 31.03.2010
comment
Это не проблема с текстовым файлом, и я не испортил NSStrings. Это NSTask выполняет преобразование, которого не должно, и grep больше не понимает аргументы правильно. Я не уверен, что проблема вообще может быть решена. - person ryyst; 31.03.2010