2016-12-07 7 views
1

Я хочу преобразовать строку типа «// u ****» в текст (unicode) в Haskell.Как преобразовать строку типа «// u ****» в текст?

У меня есть Java-файл объектов представленных, и имеет следующее содержание:

i18n.test.key=\u0050\u0069\u006e\u0067\u0020\uc190\uc2e4\ub960\u0020\ud50c\ub7ec\uadf8\uc778 

Я хочу преобразовать его в текст (Unicode) в Haskell.

Я думаю, что я могу сделать это так:

  1. Пересчитать "\ и ****" в word8 массиву
  2. Преобразовать word8 массив байтовой строки
  3. Использование Text.Encoding.decodeUtf8 конвертировать байтовой строки в текст

Но шаг 1 для меня немного сложный.

Как это сделать в Haskell?

ответ

1

Простое решение может выглядеть следующим образом:

decodeJava = T.decodeUtf16BE . BS.concat . gobble 

gobble []      = [] 
gobble ('\\':'u':a:b:c:d:rest) = let sym = convert16 [a,b] [c,d] 
           in sym : gobble rest 
gobble _      = error "decoding error" 

convert16 hi lo = BS.pack [read $ "0x"++hi, read $ "0x"++lo] 

Примечания:

  • Ваша строка UTF16-кодированными, поэтому вам нужно decodeUtf16BE.
  • Декодирование завершится неудачей, если в строке есть другие символы. Этот код будет работать с вашим примером, только если вы удалите завершающий i.
  • Построение слов путем добавления 0x и, в частности, с использованием read происходит очень медленно, но будет делать трюк для небольших данных.
+0

спасибо. он хорошо работает ~ –

1

Если вы замените \u на \x, то это действительный строковый литерал Haskell.

my_string = "\x0050\x0069\x006e..." 

Вы можете конвертировать в Text, если вы хотите, или оставить его в качестве String, или любой другой.

+0

Это не совсем правильно. Есть символы Unicode, которые представлены в двух символах Java. См. Мой ответ. – Ingo

0

Остерегайтесь, Java обычно использует UTF-16 для кодирования своих строк, поэтому интерпретация байтов как UTF-8, вероятно, не будет работать.

Если коды в файле являются UTF-16, вам необходимо сделать следующее:

  1. найти числовое значение (Unicode точку коды) для каждого quadrupel
  2. проверки, если это высокий суррогат персонаж. Если это так, следующий символ будет низким суррогатным персонажем. Пара суррогатных символов может быть сопоставлена ​​с точкой Unicode.
  3. сделать строки из вашего списка Юникода чисел с map fromEnum

Ниже приводится цитата из док Java http://docs.oracle.com/javase/7/docs/api/:

The символьного типа данных (и, следовательно, значение, объект Character инкапсулирует) основаны на исходной спецификации Unicode, которая определяет символы как 16-битные сущности фиксированной ширины. С тех пор стандарт Unicode был изменен, чтобы допускать символы, для представления которых требуется более 16 бит. Диапазон правовых кодовых пунктов теперь U + 0000 до U + 10FFFF, известный как скалярное значение Unicode. (См. Определение нотации U + n в стандарте Unicode.)

Набор символов от U + 0000 до U + FFFF иногда упоминается как базовая многоязычная плоскость (BMP). Символы, чьи кодовые точки больше U + FFFF, называются дополнительными символами. Платформа Java использует представление UTF-16 в массивах char и в классах String и StringBuffer. В этом представлении дополнительные символы представлены в виде пары значений char, первой из диапазона высоких суррогатов, (\ uD800- \ uDBFF), второй из диапазона низких суррогатов (\ uDC00- \ uDFFF).

В Java есть методы для сочетания высокого суррогатного персонажа и низкого суррогатного персонажа, чтобы получить точку Юникода. Вы можете проверить источник класса java.lang.Character, чтобы узнать, как именно они это делают, но я предполагаю, что это простая бит-операция.

Другая возможность - проверить библиотеку Haskell, которая выполняет декодирование UTF-16.

+0

THX очень много. вы правы, это декодирование Utf-16. –