我需要能够对其上的字节顺序标记(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字符串。

有更好的方法吗?

有帮助吗?

解决方案

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

代码:

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字符??<!> QUOT;或类似的东西。 (或者,抛出异常可能会更好......当然,这取决于你。)

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

其他提示

System.Text.Encoding.ASCII.GetBytes(new StreamReader(new MemoryStream(i_fileBytes)).ReadToEnd())

这应该可以节省几次往返。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top