Как заставить Matlab писать BOM (маркеры порядка байтов) для текстовых файлов UTF-16? - PullRequest
7 голосов
/ 08 ноября 2011

Я создаю текстовые файлы UTF16 с Matlab, которые я позже читаю при использовании Java В Matlab я открываю файл с именем fileName и записываю в него следующее:

fid = fopen(fileName, 'w','n','UTF16-LE');
fprintf(fid,"Some stuff.");

В Java я могу прочитать текстовый файл, используя следующий код:

FileInputStream fileInputStream = new FileInputStream(fileName);
Scanner scanner = new Scanner(fileInputStream, "UTF-16LE"); 
String s = scanner.nextLine();

Вот шестнадцатеричный вывод:

Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13
00000000  73 00 6F 00 6D 00 65 00 20 00 73 00 74 00 75 00 66 00 66 00  s.o.m.e. .s.t.u.f.f.

Приведенный выше подход работает отлично. Но я хочу иметь возможность записывать файл с использованием UTF16 с спецификацией, чтобы дать мне больше гибкости, чтобы мне не приходилось беспокоиться о больших или маленьких порядковых номерах. В Matlab я закодировал:

fid = fopen(fileName, 'w','n','UTF16');
fprintf(fid,"Some stuff.");

В Java я изменяю код на:

FileInputStream fileInputStream = new FileInputStream(fileName);
Scanner scanner = new Scanner(fileInputStream, "UTF-16");
String s = scanner.nextLine();

В этом случае строка s искажена, потому что Matlab не записывает спецификацию. Я могу заставить Java-код работать нормально, если добавлю спецификацию вручную. С добавленной спецификацией следующий файл работает нормально.

Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15
00000000  FF FE 73 00 6F 00 6D 00 65 00 20 00 73 00 74 00 75 00 66 00 66 00  ÿþs.o.m.e. .s.t.u.f.f.

Как я могу заставить Matlab выписать спецификацию? Я знаю, что мог бы выписать спецификацию отдельно, но я бы предпочел, чтобы Matlab сделал это автоматически.

Добавление

Я выбрал ответ ниже из Amro , потому что он точно решает поставленный мной вопрос.

Одним из ключевых открытий для меня было различие между стандартом Unicode и UTF (формат преобразования Unicode) (см. http://unicode.org/faq/utf_bom.html). Стандарт Unicode предоставляет уникальные идентификаторы (кодовые точки) для символов. UTF обеспечивают сопоставления каждого кода указывать «на уникальную последовательность байтов». Поскольку все, кроме нескольких символов, которые я использую, находятся в первых 128 кодовых точках, я собираюсь перейти на использование UTF-8, как предлагает Romeo . UTF -8 поддерживается Matlab (предупреждение, показанное ниже, подавлять не нужно.) И Java, и для моего приложения будут генерироваться текстовые файлы меньшего размера.

Я подавляю предупреждение Matlab

Warning: The encoding 'UTF-16LE' is not supported.

с

warning off MATLAB:iofun:UnsupportedEncoding;

Ответы [ 3 ]

4 голосов
/ 08 ноября 2011

В моей системе MATLAB сообщает, что UTF-16 не поддерживается. Я думаю, что будет безопаснее использовать UTF-8. Кроме того, UTF-8 решит вашу проблему с Little Endian / Big Endian.

2 голосов
/ 09 ноября 2011

Попробуйте следующий код (я использую функции UNICODE2NATIVE и NATIVE2UNICODE для преобразования):

%# convert string and write as bytes
str = 'Some stuff.';
b = unicode2native(str,'UTF-16');
fid = fopen('utf16.txt','wb');
fwrite(fid, b, '*uint8');
fclose(fid);

Мы можем даже проверить шестнадцатеричные значения записанных байтов (первые два - BOM ):

>> cellstr(dec2hex(b))'
ans = 
  Columns 1 through 10
    'FF'    'FE'    '53'    '00'    '6F'    '00'    '6D'    '00'    '65'    '00'
  Columns 11 through 20
    '20'    '00'    '73'    '00'    '74'    '00'    '75'    '00'    '66'    '00'
  Columns 21 through 24
    '66'    '00'    '2E'    '00'

>> char(b)
ans =
ÿþS o m e   s t u f f . 

Теперь мы можем прочитать созданный файл, используя собственные методы MATLAB:

%# read bytes and convert back to Unicode string
fid = fopen('utf16.txt', 'rb');
b = fread(fid, '*uint8')';          %'
fclose(fid);
str = native2unicode(b,'UTF-16')

Или используйте Java методы напрямую, если вы предпочитаете:

scanner = java.util.Scanner(java.io.FileInputStream('utf16.txt'), 'UTF-16');
str = scanner.nextLine()
scanner.close()

оба должны правильно прочитать строку ...

0 голосов
/ 09 ноября 2011

Когда я пытаюсь выполнить команду:

fid = fopen(fileName, 'w', 'n', 'UTF16');

Вот что я вижу:

>> fid = fopen('foo.txt', 'w', 'n', 'UTF16');
Warning: The encoding 'UTF-16' is not supported.
See the documentation for FOPEN.

Вы уверены, что успешно открываете файл так, как хотите??Возможно, вы где-то глотаете предупреждающее сообщение?

...