Чтение текстового файла в кодировке UTF-8 в Mathematica - PullRequest
14 голосов
/ 08 апреля 2011

Как мне прочитать текстовый файл в Mathematica utf-8 в кодировке?

Вот что я делаю сейчас:

text = Import["charData.txt", "Text", CharacterEncoding -> "UTF8"];

но это говорит мне, что

$CharacterEncoding::utf8: "The byte sequence {240} could not be interpreted as a character in the UTF-8 character encoding"

и так далее. Я не уверен почему. Я считаю, что файл действителен utf-8.

Вот файл, который я пытаюсь прочитать:

http://dl.dropbox.com/u/38623/charData.txt

1 Ответ

9 голосов
/ 09 апреля 2011

Короткая версия: функция Mathematica UTF-8 не работает для кодов символов с более чем 16 битами.Вместо этого используйте кодировку UTF-16, если это возможно.Но имейте в виду, что обработка Mathematica 17+ битовых кодов символов, как правило, ошибочна.Далее следует длинная версия ...

Как отмечают многочисленные комментаторы, проблема, похоже, заключается в поддержке Mathematica символов Unicode, коды которых больше 16 бит.Первый такой символ в цитируемом текстовом файле: U + 20B9B (?), который появляется в строке 10.

Некоторые версии интерфейса Mathematica (например, 8.0.1 на 64-Windows 7) может обрабатывать соответствующий символ при непосредственном вводе:

In[1]:= $c="?";

Но мы сталкиваемся с проблемами, если пытаемся создать символ из его Unicode:

In[2]:= 134043 // FromCharacterCode

During evaluation of In[2]:= FromCharacterCode::notunicode:
A character code, which should be a non-negative integer less
than 65536, is expected at position 1 in {134043}. >>
Out[2]= FromCharacterCode[134043]

Один, затемИнтересно, что Mathematica считает кодом для этого символа?

In[3]:= $c // ToCharacterCode
        BaseForm[%, 16]
        BaseForm[%, 2]

Out[3]= {55362,57243}
Out[4]//BaseForm= {d842, df9b}
Out[5]//BaseForm= {1101100001000010, 1101111110011011}

Вместо одного значения Юникода, как можно было ожидать, мы получаем два кода, которые соответствуют UTF-16 представление этого персонажа.Mathematica также может выполнять обратное преобразование:

In[6]:= {55362,57243} // FromCharacterCode

Out[6]= ?

Какова же концепция Mathematica в отношении кодировки UTF-8 этого символа?

In[7]:= ExportString[$c, "Text", CharacterEncoding -> "UTF8"] // ToCharacterCode
        BaseForm[%, 16]
        BaseForm[%, 2]

Out[7]= {237,161,130,237,190,155}
Out[8]//BaseForm= {ed, a1, 82, ed, be, 9b}
Out[9]//BaseForm= {11101101, 10100001, 10000010, 11101101, 10111110, 10011011}

Внимательный читатель заметит, чтоэто кодировка UTF-8 кодировки символа UTF-16.Может ли Mathematica расшифровать эту интересную кодировку?

In[10]:= ImportString[
           ExportString[{237,161,130,237,190,155}, "Byte"]
         , "Text"
         , CharacterEncoding -> "UTF8"
         ]

Out[10]= ?

Да, это возможно!Но ... ну и что?

Как насчет выражения real UTF-8 для этого символа:

In[11]:= ImportString[
           ExportString[{240, 160, 174, 155}, "Byte"]
         , "Text"
         , CharacterEncoding -> "UTF8"
         ]
Out[11]= $CharacterEncoding::utf8: The byte sequence {240} could not be
interpreted as a character in the UTF-8 character encoding. >>
$CharacterEncoding::utf8: The byte sequence {160} could not be
interpreted as a character in the UTF-8 character encoding. >>
$CharacterEncoding::utf8: The byte sequence {174} could not be
interpreted as a character in the UTF-8 character encoding. >>
General::stop: Further output of $CharacterEncoding::utf8 will be suppressed
during this calculation. >>
ð ®

... но мы видим ошибку, о которой сообщалось воригинальный вопрос.

Как насчет UTF-16?UTF-16 отсутствует в списке допустимых кодировок символов, но "Unicode" есть.Поскольку мы уже видели, что Mathematica, похоже, использует UTF-16 в качестве собственного формата, давайте возьмемся за него (используя UTF-16 с прямым порядком байтов с меткой порядка байтов):

In[12]:= ImportString[
           ExportString[
             FromDigits[#, 16]& /@ {"fe", "ff", "d8", "42", "df", "9b"}
             , "Byte"
           ]
         , "Text"
         , CharacterEncoding -> "Unicode"
         ]
Out[12]= ?

Itработает.В качестве более полного эксперимента я перекодировал цитируемый текстовый файл из вопроса в UTF-16 и успешно импортировал его.

Документация Mathematica по большей части об этом молчит.Интересно отметить, что упоминание Unicode в Mathematica, по-видимому, сопровождается предположением, что коды символов содержат 16 битов.См., Например, ссылки на Unicode в Необработанные кодировки .

Из этого следует сделать вывод, что поддержка Mathematica для транскодирования UTF-8 отсутствует / глючит для кодов длиннее 16 бит.UTF-16, очевидный внутренний формат Mathematica, похоже, работает правильно.Так что это обходной путь, если вы можете перекодировать ваши файлы и , вы можете принять, что результирующие строки будут на самом деле в формате UTF-16, а не в истинных строках Unicode.

Postscript

Через некоторое время после написания этого ответа я попытался снова открыть записную книжку Mathematica, в которой он содержится.Каждое появление проблемного персонажа в блокноте было уничтожено и заменено тарабарщиной.Я предполагаю, что есть еще больше ошибок Unicode, даже в Mathematica 8.0.1;)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...