如何让Matlab在UTF-16文本文件中写入BOM(字节顺序标记)?

7

我正在使用Matlab创建UTF16文本文件,稍后将使用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();

以下是十六进制输出:

偏移量(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.

上述方法可以正常工作。但我想使用带有BOM的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没有写入BOM。如果我手动添加BOM,则可以使Java代码正常工作。添加BOM后,以下文件正常工作。
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输出BOM?我知道我可以单独写出BOM,但我更希望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

在我的系统中,MATLAB报告说不支持UTF-16。我认为使用UTF-8会更安全。此外,UTF-8能够解决你在小端/大端方面的问题。


我通常会使用UTF-8,但是我需要UTF-16字符集中独有的字符,例如带长音符和短音符的元音字母。所以UTF-8对于我的工作来说不适用。 - Richard Povinelli
2
@Richard:你到底在说什么?UTF-8和UTF-16是完全相同字符的不同编码方式。如果你对Unicode没有任何了解,那么成功的机会很小。 - Hugh
2
@Huw:+1 UTF-8和UTF-16都能够表示Unicode字符集中的每个字符(根据维基百科,共有1112064个代码点)...不过你不应该因为这个误解而责怪他,毕竟Unicode是一个非常复杂的标准 :) - Amro
@Romeo:你说得对。我现在明白UTF-8是一种可变长度编码。维基百科UTF-8页面为我澄清了这一点。 - Richard Povinelli
@Huw:我在说什么呢?是对UTF-8的错误理解。你是正确的。我以为UTF-8是ASCII标准的重命名,这是不正确的。 - Richard Povinelli
显示剩余2条评论

2

尝试以下代码(我使用 UNICODE2NATIVENATIVE2UNICODE 函数进行转换):

%# 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):

(第一个链接到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

当我尝试运行您的命令时:

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.

你确定你以想要的方式成功打开了文件吗?你可能在某个地方忽略了一个警告信息吗?

关闭警告 MATLAB:iofun:UnsupportedEncoding; - Richard Povinelli
然而,该文件确实作为UTF16-LE文本文件打开。当我使用“UTF16-LE”时,我得到与使用“UTF16”时相同的错误。使用“UTF16-BE”会产生大端编码。尽管Matlab支持UTF16-BE和UTF16-LE,但警告仍然存在。 - Richard Povinelli

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接