Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/332.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# StreamReader.BaseStream在使用EndOfStream属性后出现问题_C#_Stream_Filestream_Streamreader - Fatal编程技术网

C# StreamReader.BaseStream在使用EndOfStream属性后出现问题

C# StreamReader.BaseStream在使用EndOfStream属性后出现问题,c#,stream,filestream,streamreader,C#,Stream,Filestream,Streamreader,首先,我知道我可以用不同的方法解决这个问题。我猜这个问题的存在只是因为使用了不同的方法。但我想知道在我的例子中到底发生了什么 我使用StreamReader读取文件。为了从中获取字节,我决定使用BaseStream。读取: int length = (int)reader.BaseStream.Length; byte[] file = new byte[length]; while(!reader.EndOfStream) {

首先,我知道我可以用不同的方法解决这个问题。我猜这个问题的存在只是因为使用了不同的方法。但我想知道在我的例子中到底发生了什么

我使用StreamReader读取文件。为了从中获取字节,我决定使用BaseStream。读取:

        int length = (int)reader.BaseStream.Length;
        byte[] file = new byte[length];
        while(!reader.EndOfStream)
        {
            int readBytes = reader.BaseStream.Read(file, 0, 
                (length-offset)>bufferSize?bufferSize:(length - offset));
            for (int i = 0; i<readBytes; i++)
            {
                ...
            }
            offset += readBytes;
        }
int length=(int)reader.BaseStream.length;
字节[]文件=新字节[长度];
而(!reader.EndOfStream)
{
int readBytes=reader.BaseStream.Read(文件,0,
(长度偏移)>bufferSize?bufferSize:(长度-偏移));

对于(int i=0;i它不是
StreamReader。BaseStream
有一些问题,但在您的代码中是一个问题。当您直接使用
包装在
StreamReader
中时

来自MSDN关于:

仅当内部缓冲区和基流的位置不匹配时,才需要调用此方法。当您将数据读入缓冲区,然后在基础流中查找新位置时,这些位置可能不匹配

这意味着,在您的情况下,当
已经到达结束位置时,
StreamReader
内部缓冲区的位置仍然保持在您直接读取底层流之前的值,因此
reader.EndOfStream
仍然=
false
。这就是您无法完成循环的原因

编辑:

我想你遗漏了什么,我给你这段代码来证明文件已经成功到达末尾。运行它,你会看到你的应用程序重复地说:我在文件末尾

编辑2

但是,偏移量和长度应该相等,im my case length-offset=1024(对于大于1kb的文件)。也许我做错了什么,但是如果我使用大小小于1kb的文件,readBytes总是等于0

这是因为您在(!reader.EndOfStream)
时第一次调用
,所以读取器必须读取文件(本例为1024字节-将字节读取到内部缓冲区),以确定文件是否结束(请参阅上面添加的两行代码),在它读取文件后,将查找1024字节,这就是为什么
长度-偏移量=1024
,如果您的文件小于1kb,则在第一次调用时,它已查找到文件的结尾。这就是您丢失数据的地方


第二个调用,它不查找,因为你不发送任何读请求给读者,所以它考虑不改变,那么它不需要再次读取文件来检查文件末尾是否有第二个调用不丢失数据。

你为什么要使用StreamReader?@ USR,就像我说的,可以避免这个问题而没有任何差异。文化。我只是好奇使用属性是如何以如此奇怪的方式影响内部流的。谢谢你们的回答。我知道StreamReader有内部缓冲区和他自己的位置。但我完全不安的是,最后1024字节的可用性取决于使用EndOfStream属性(不是方法,其目的是改变对象的状态)。问题是,如果我在代码中删除reader.EndOfStream,所有数据都将可用。使用类似于StreamReader的包装器会影响流中数据的可访问性,而流中数据是被包装的。所以我仍然不明白包装器到底是如何影响内部流的,以及为什么它会使最后1024个字节不可访问。谢谢编辑。你是对的,我的应用程序说我但偏移量和长度仍然应该相等,im my case length-offset=1024(对于大于1kb的文件)。也许我做错了什么,但如果我使用大小小于1kb的文件,readBytes总是等于0。感谢您的解释。因此,一般来说,当调用
EndOfStream
时,
Stream.position
将增加1024,如果可能的话(如果必要的话)。由于不适当地使用了
BaseStream
,这将导致数据泄漏。我做对了吗?
static void Main()
{
    using (StreamReader reader = new StreamReader(@"yourFile"))
    {
        int offset = 0;
        int bufferSize = 102400;
        int length = (int)reader.BaseStream.Length;
        byte[] file = new byte[length];
        while (!reader.EndOfStream)
        {


            // Add this line:
            Console.WriteLine(reader.BaseStream.Position);
            Console.ReadLine();



            int readBytes = reader.BaseStream.Read(file, 0,
                (length - offset) > bufferSize ? bufferSize : (length - offset));
            string str = Encoding.UTF8.GetString(file, 0, readBytes);
            offset += readBytes;
            if (reader.BaseStream.Position == length)
            {
                Console.WriteLine("I'm at the end of the file!  Current Tickcount: " + Environment.TickCount);
                Thread.Sleep(100);
            }
        }
    }
}