【问题标题】:How to find condition that start char in UTF-8 file is read, using FileStream and StreamReader?如何使用 FileStream 和 StreamReader 查找读取 UTF-8 文件中开始字符的条件?
【发布时间】:2015-05-19 08:29:20
【问题描述】:

在 C# .NET 4.0(实际上是 4.5.2)中,我的代码读取一个 UTF-8 文件。

            FileStream fstream = new FileStream(path, FileMode.Open);
            BufferedStream stream = new BufferedStream(fstream);

            using (StreamReader reader = new StreamReader(stream, new UTF8Encoding())) {              
                int i;
                while((i = reader.Read()) > -1) {
                    //a guess at a condition that is true I.F.F. reader has read character 1 of the file
                    if (stream.Position == (0 + sizeof(char)) || stream.Position == (0 + sizeof(int)) ) {
                        //while loop has reader read through all characters, 
                        //but within this block, the reader has surely read character 1?
                        char c = (char)i;


                    }
                }

                reader.Close();
                return 0;
            }

I.F.F.我们达到了 StreamReader 读取 UTF-8 文件的起始字符的条件,然后在读取的第一个字符上运行一些函数。

使用 FileStream 和 StreamReader 读取 UTF-8 文件,如何知道是否满足上述条件?

我正在寻找使用 C# .NET 4.0 System.IO 命名空间中已存在的属性或方法的答案。我认为使用 Stream.Position (BufferedStream.Position) 属性是找出阅读器在文件中的位置(即在什么字符处)的明显方法,但是在尝试以 @ 中的某个字符开头的 UTF-8 文件时987654322@ 到 '9'(48 到 57),带有 reader.Read() 的循环读取该字符,然后 stream.Position = 43 。我不知道为什么在读取第一个字符后所有整数值中的 43 是 stream.Position 的值,或者 43 是什么意思。

更新:随着循环迭代和阅读器读取更多字符,stream.Position 值保持在 43。我不知道 Position 属性是否有用。

【问题讨论】:

  • 你想完成什么?现有的代码不是很有启发性。我不明白这是什么意思。
  • 将 UTF 文件读入 C# charString 值。总体问题是根据文件中char 的位置和char 值执行一些操作。存在预期的格式,因此文件的第 nth 行的 char 值的读取和使用与 n + 1n + 2 行不同。 n 行的 ith 字符可能会更改一个字段,而 char i + 1 会设置另一个字段并在某处更改状态。这有帮助吗?
  • 好的,你能用 File.ReadAllText/Lines 处理你从中得到的字符串吗?
  • 当然,或者使用 StreamReader.ReadToEnd() 的许多其他方法来做到这一点;将char 读入一个巨大的内存块,但这与以缓冲方式读取数据相比会受到批评,比如使用 BufferedStream。
  • 对了,这里可以成功使用StreamReader了。另一种方式似乎更容易。一旦您遍历一系列行,解决方案可能很明显。然后可以在普通字符串上完成所有位置计算。我只是想让你知道这件事。也许 xanatos 的回答也能解决问题。

标签: c#-4.0 utf-8 io stream


【解决方案1】:
bool first = true;    

while((i = reader.Read()) > -1) 
{
    if (first)
    {
        first = false;
        // Do first character things
    }

请注意,第一个字符的概念很复杂:如果第一个字形是è,它在文件中占据了两个字节,会发生什么?流位置至少为 2 :-)

一般情况下,您可以检查StreamReader.BaseStreamPosition 是什么,但是Position 几乎没用,因为可能存在多级缓存,或者仅仅因为读取单个charStreamReader 可能已经消耗了 1-4 个字节(à 是一个字节,而一些 Unicode 字符是长 4 个字节)......然后 UTF8 文件可以有一个 BOM(初始标头长 3 个字节)。这通常也会从StreamReader 跳过。

不过,如果您愿意,您可以继承整个 StreamReader 类,覆盖所有 Read*,并保留一个内部标志 SomethingHasBeenRead。这并不难(StreamReader 中的一切都是 virtual)... 只是有点长。

【讨论】:

  • @T.Webster 你错了。 .NET char 是两个字节,Unicode 字符的 UTF8 代码可以是 1-4 个字节。 Encoding.UTF8.GetBytes("aè").Length == 3.
  • @T.Webster 甚至这有点不精确......在 Unicode 中可能有 100 万个可能的代码点。所有都可以用 UTF32 表示,每个代码点使用 4 个字节。使用 UTF16(如 C# char)您使用 2 或 4 个字节,因此 1 或 2 char,具体取决于代码点。如果您使用 2 个char,它们被称为“代理对”。使用 UTF16,每个代码点可以用 1-4 个字节表示。当您使用Encoding.UTF8 时,字符串在其代码点中“虚拟地”转换(因此对代理对进行分组),然后转换为 UTF8。
  • 是的,我考虑过这种方法,但我一直在寻找在 .NET 4.0 System.IO 命名空间中使用某些类/成员的解决方案的原因是,它看起来更干净,错误更少 -比这样写下你自己的变量更容易。如果一个错误使这些变量无效怎么办?此外,使用 BufferedStream.Position 之类的东西来查找我们在文件 btw char size is 2 bytes btw) 中的字符的通用方法是我所希望的。
  • @T.Webster 简单的事情是:我无法检查StreamReader 是否至少读取了一个字符。 (在响应中添加了一些行)
  • @T.Webster 注意StreamReader.ReadLine()StreamReader.ReatToEnd() 不要使用StreamReader.Read()! (也不是其他方法)。他们都是独立的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-10-09
  • 2016-07-27
  • 2011-10-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-25
相关资源
最近更新 更多