【问题标题】:Is there a better way to convert to ASCII from an arbitrary input?有没有更好的方法可以从任意输入转换为 ASCII?
【发布时间】:2008-11-21 18:41:38
【问题描述】:

我需要能够接受可能带有字节顺序标记 (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字符串。

有没有更好的方法来做到这一点?

【问题讨论】:

    标签: c# encoding stream ascii


    【解决方案1】:

    如果内存中已经有 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 字符。或类似的东西。 (或者,抛出异常可能会更好......当然,这取决于你。)

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

    【讨论】:

    • 是的,这是我正在考虑并想要避免的。我可以使用 Reflector 从 StreamReader 中提取 BOM 检测内容。虽然不是很干净和面向未来。不过,使用 StreamReader 只获取前 10 个字节很有趣。好主意!
    【解决方案2】:
    System.Text.Encoding.ASCII.GetBytes(new StreamReader(new MemoryStream(i_fileBytes)).ReadToEnd())
    

    这应该可以节省一些往返时间。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-11-24
      • 2010-11-04
      • 2014-07-27
      • 1970-01-01
      • 2022-09-23
      • 1970-01-01
      • 2016-07-23
      相关资源
      最近更新 更多