2016-02-27 35 views
2

首先,我明白我可以使用不同的方法解決此問題。我猜這個問題的存在只是因爲以不正確的方式使用不同的方法。但我想知道我的例子中究竟發生了什麼。使用EndOfStream屬性後StreamReader.BaseStream問題

我正在使用StreamReader讀取文件。爲了從它那裏得到字節,我決定使用BaseStream.Read:

 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; 
     } 

BaseStream.Read拒絕領取最後的1024個字節時財產StreamReader.EndOfStream在閱讀之前使用。後來我發現信息,即EndOfStream試圖讀取1個字節,但實際上他讀取了1024字節應有的性能。顯然這1kb變得不可能達到。

編輯:如果我刪除代碼reader.EndOfStream財產,reader.BaseStream.Read將正常工作。這是主要的問題。

我再次明白,這個代碼示例是絕對低效的。我只是想了解在這個例子中流是如何工作的,並且由於代碼不好而存在這個問題(或者StreamReader.BaseStream有一些問題)?提前致謝。

+0

你爲什麼要使用的StreamReader呢? – usr

+0

@usr就像我說過的,可以毫無困難地避免這個問題。我只是好奇使用財產的事實如何以這種奇怪的方式影響內部流。 –

回答

0

這不是StreamReader.BaseStream有一些問題,但在您的代碼中有問題。當您直接與StreamReader內部包裝的Stream一起工作時。

從MSDN約StreamReader.DiscardBufferedData

您需要調用此方法僅在內部緩衝區的BaseStream的位置並不相符。當您將數據讀入緩衝區然後在基礎流中尋找新位置時,這些位置可能會不匹配。

意味着,在你的情況下,當Stream已經到達末端位置,StreamReader內部緩衝區的位置仍然存在的價值,你directedly讀取底層流之前,因此reader.EndOfStream仍然= false。那爲什麼你不能完成循環。

編輯:

我想你失去了一些東西,我給你這個代碼證明文件成功到達終點。運行它,你會發現你的應用重複地說:我在文件的末尾!

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); 
      } 
     } 
    } 
} 

編輯2

但儘管如此,偏移和長度應該是平等的,即時我的情況長度 - (在文件的情況下,除1KB大)偏移= 1024。也許我做錯了什麼,但如果我使用大小小於1kb的文件,readBytes總是等於0。

那是因爲你對while (!reader.EndOfStream)第一個電話,讀者需要閱讀的文件(這裏指的是1024個字節 - 讀取的字節到內部緩衝區),如果文件結束到detemine或不(見的代碼,我的兩行上面添加),後讀取該文件seeked 1024個字節,那爲什麼length - offset = 1024,如果你的文件超過1KB小則與此第一個呼叫,它已經尋求到文件末尾。這是你丟失數據的地方。

到它的第二個電話,它不求,因爲你不發送任何讀取請求給讀者,所以考慮不變,則不需要再次讀取文件,在文件的最後檢查那爲什麼第二個電話不會丟失數據。

+0

謝謝你的回答。我明白** StreamReader **有內部緩衝區和他自己的位置。但我完全不安,最後1024字節的可用性取決於使用EndOfStream **屬性**(不是方法,其目的是改變對象的狀態)。事情是,如果我在代碼中刪除** reader.EndOfStream **,所有數據都將可用。使用像** StreamReader **這樣的包裝會影響** Stream **中數據的可訪問性,該數據已被封裝。所以我仍然不明白wrapper如何影響內部流,以及爲什麼它會使最後的1024個字節無法訪問。 –

+0

@NickSemianiuk看到我的編輯。 – Sakura

+0

感謝您的編輯。你是對的,我的應用程序說 - 我在文件末尾!但是,** offset **和** length **應該是相等的,即我的情況** length - offset = 1024 **(如果文件大於1kb)。也許我做錯了什麼,但如果我使用的文件尺寸小於1KB,** **的ReadBytes總是等於0 –