【问题标题】:Reading a stream that may have non-ASCII characters读取可能包含非 ASCII 字符的流
【发布时间】:2012-10-17 08:09:58
【问题描述】:

我有一个从流中读取字符串数据的应用程序。字符串数据通常是英文的,但有时会遇到类似“Jalapeño”的内容,而“ñ”则显示为“?”。在我的实现中,我更喜欢将流内容读入字节数组,但我可以通过将内容读入字符串来获得。知道我可以做些什么来使这项工作正确吗?

当前代码如下:

byte[] data = new byte[len];  // len is known a priori
byte[] temp = new byte[2];
StreamReader sr = new StreamReader(input_stream);
int position = 0;
while (!sr.EndOfStream)
{
  int c = sr.Read();
  temp = System.BitConverter.GetBytes(c);
  data[position] = temp[0];
  position++;
}
input_stream.Close();
sr.Close();

【问题讨论】:

  • int c 实际上为 EOF 持有一个 char 或 -1,对于非 ASCII 值,它看起来像你扔掉了一半的值 并且 从根本上改变了编码...

标签: c# stream ascii non-ascii-characters


【解决方案1】:

您可以将encoding 传递给 StreamReader,如下所示:

StreamReader sr = new StreamReader(input_stream, Encoding.UTF8);

但是,我知道根据文档默认使用 Encoding.UTF8。

更新

下面的“墨西哥胡椒”很好:

byte[] bytes;
using (var stream = new FileStream("input.txt", FileMode.Open, FileAccess.Read, FileShare.Read))
{
    var index = 0;
    var count = (int) stream.Length;
    bytes = new byte[count];
    while (count > 0)
    {
        int n = stream.Read(bytes, index, count);
        if (n == 0)
            throw new EndOfStreamException();

        index += n;
        count -= n;
    }
}

// test
string s = Encoding.UTF8.GetString(bytes);
Console.WriteLine(s);

这样:

byte[] bytes;
using (var stream = new FileStream("input.txt", FileMode.Open, FileAccess.Read, FileShare.Read))
{
    var reader = new StreamReader(stream);
    string text = reader.ReadToEnd();
    bytes = Encoding.UTF8.GetBytes(text);
}

// test
string s = Encoding.UTF8.GetString(bytes);
Console.WriteLine(s);

据我了解,当文本以 UTF 编码存储时,文本中的“ñ”字符表示为 0xc391。当你只读取一个字节时,你会丢失数据。

我建议将整个流作为字节数组读取(第一个示例),然后进行编码。或使用 StreamReader 为您完成工作。

【讨论】:

  • 谢谢 - 但 'ñ' 字符仍显示为 '?'即使指定 Encoding.UTF8。
  • 注意 Console.WriteLine 可能会写“?”对于有效的 UNICODE 字符,例如中文或日文。
  • 感谢 Werner,上面的第二个示例“就像这样”完美运行!
【解决方案2】:

由于您正在尝试将内容填充到字节数组中,因此请不要打扰阅读器 - 它对您没有帮助。只使用流:

byte[] data = new byte[len];
int read, offset = 0;
while(len > 0 &&
    (read = input_stream.Read(data, offset, len)) > 0)
{
    len -= read;
    offset += read;
}
if(len != 0) throw new EndOfStreamException();

【讨论】:

  • 谢谢你,马克,这很有帮助。我在复制字符串“Jalapeño”时遇到了后续问题。当我执行string s = System.Text.Encoding.UTF8.GetString(data)string s = System.Text.Encoding.Unicode.GetString(data) 时,它们都不起作用。我得到一个 StackOverflow 异常(多么合适!)。关于如何在保留原始字符的同时从流中返回字符串,您有什么建议吗?
  • @haxor 它是用什么编码存储的?
  • 这是我必须应对的挑战之一 - 我只能假设 ASCII 或 UTF8。
  • 您认为直接进入字符串并完全绕过 byte[] 会更好吗?
  • @haxor 您能否发布问题如此严重的字节序列?即“Jalapeo”的字节序列?
猜你喜欢
  • 2011-04-19
  • 2015-12-08
  • 2013-08-30
  • 2016-02-29
  • 2012-08-06
  • 2023-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多