我有以下代码:
var reader = new StreamReader(inputSubtitle, encoding);
string str;
var list = new List<String>();
try
{
str = reader.ReadLine();
while (str != null)
{
list.Add(str);
str = reader.ReadLine();
}
return list;
}
编码基于字节顺序标记。字符集检测器代码(如果需要可以提供它)只是查看文件中前几个字节的十六进制值。这些文件通常是UTF-8,Windows ANSI(Codepage-1252)或UTF-16LE。目前最后一个失败,我不知道为什么。
在记事本中预览文本说它被编码为Unicode(用它表示UTF-16LE,afaik),在Firefox中打开表示它是UTF-16LE,BOM以字节FF FE开头。
以示例文字:
1
00:04:05,253 --> 00:04:11,886
<i>This is the first line</i>
- This is the second line.
我将此文件作为文件流发送到charset检测器(我在后端使用filestream作为输入),我在其中添加了以下调试行:
byte[] dataFromFileStream = new byte[(input.Length)];
input.Read(dataFromFileStream, 0, (int)input.Length);
Console.WriteLine(BitConverter.ToString(dataFromFileStream));
这会生成以下十六进制代码:
"FF-FE-31-00-(...)"
FF-FE是UTF16-LE的字节顺序标记。
使用StreamReader和编码设置为Encoding.Unicode打开此十六进制代码会将数据转换为单个字符串:
"\u0d00\u0a00 㨀 㐀㨀 㔀Ⰰ㈀㔀㌀ ⴀⴀ㸀 㨀 㐀㨀\u3100\u3100Ⰰ㠀㠀㘀\u0d00\u0a00㰀椀㸀吀栀椀猀 椀猀 琀栀攀 昀椀爀猀琀 氀椀渀攀㰀⼀椀㸀\u0d00\u0a00ⴀ 吀栀椀猀 椀猀 琀栀攀 猀攀挀漀渀搀 氀椀渀攀⸀"
将编码器设置为Encoding.GetEncoding(1201),例如作为UTF-16BE,正确打开文件并按预期将其解码为列表中的4行。
我注意到这个错误已经过了几个星期,之后代码才能正常运行。这是在更新中发生的事情吗? Encoding.Unicode在文档中被描述为UTF-16LE。
我改变了我的代码,暂时使用UTF-16BE作为解码器,让它再次运行,但这感觉不对。
答案 0 :(得分:0)
原来我犯了一个愚蠢的错误; Charset检测器读取几个字节以确定文件的编码。为了确保我有一个UTF-16LE文件(以FF-FE开头)而不是UTF-32LE(以FF-FE-00-00开头),我也读了第三个字节。但是,在读取这些字节后,我没有将FileStream的位置重置为0. 我的代码的早期版本,使用不同的构造函数,确实重置了起始位置。添加重置位置的代码修复了它。
<强>说明:强> StreamReader类不一定需要UTF文件中的BOM,因此它开始从charset检测器完成其后的位置读取。检测UTF-8或ANSI没有问题,因为它们以单个字节编码。 UTF-16对每个字符使用两个字节,因此从奇数字节开始导致所有内容看起来像读取器的反向字节顺序。因此解码像UTF-16BE“修复”了这个问题。