2

我需要能够获取可能具有字节顺序标记 (BOM) 的任意文本输入来标记其编码,并将其输出为 ASCII。我们有一些不了解 BOM 的旧工具,我需要向它们发送纯 ASCII 数据。

现在,我刚刚写完这段代码,我简直不敢相信这里的低效率。数据的四个副本,更不用说 StreamReader 内部的任何中间缓冲区。有一个更好的方法吗?

// i_fileBytes is an incoming byte[]

string unicodeString = new StreamReader(new MemoryStream(i_fileBytes)).ReadToEnd();
byte[] unicodeBytes  = Encoding.Unicode.GetBytes(unicodeString.ToCharArray());
byte[] ansiBytes     = Encoding.Convert(Encoding.Unicode, Encoding.ASCII, unicodeBytes);
string ansiString    = Encoding.ASCII.GetString(ansiBytes);

我需要 StreamReader() 因为它有一个内部 BOM 检测器来选择编码来读取文件的其余部分。然后剩下的就是让它转换成最终的 ASCII 字符串。

有一个更好的方法吗?

4

2 回答 2

1

如果内存中已经有 i_fileBytes,则可以检查它是否以 BOM 开头,然后使用Encoding.Unicode.GetString. (使用允许您指定索引和长度的重载。)

所以作为代码:

int start = (i_fileBytes[0] == 0xff && i_fileBytes[1] == 0xfe) ? 2 : 0;
string text = Encoding.Unicode.GetString(i_fileBytes, start, i_fileBytes.Length-start);

但是请注意,这假定了真正的小端 UTF-16 编码。如果您确实需要首先检测编码,您可以重新实现 StreamReader 所做的事情,或者只是从前(比如说)10 个字节构建一个 StreamReader,然后使用 CurrentEncoding 属性来确定应该用于编码的内容。

编辑:现在,至于到 ASCII 的转换——如果你真的只需要它作为一个 .NET 字符串,那么大概你想要做的就是用“?”替换任何非 ASCII 字符。或类似的东西。(或者,抛出异常可能会更好......当然,这取决于你。)

编辑:请注意,在检测编码时,最好只调用Read()一次来读取一个字符。不要ReadToEnd()通过选择 10 个字节作为任意数量的数据来调用 as,它可能会在字符中间结束。我不知道这是否会引发异常,但无论如何它没有任何好处......

于 2008-11-21T18:57:57.137 回答
0
System.Text.Encoding.ASCII.GetBytes(new StreamReader(new MemoryStream(i_fileBytes)).ReadToEnd())

这应该可以节省一些往返行程。

于 2010-07-27T20:08:20.887 回答