2010-12-16 48 views
13

我知道在Stackoverflow之前已經詢問過此問題,但找不到解釋。StreamReader ReadToEnd()在第一次嘗試時返回空字符串

當我嘗試從壓縮字節數組中讀取一個字符串時,我在第一次嘗試時得到一個空字符串,在第二次嘗試之後,我獲得了字符串。

代碼示例:

public static string Decompress(byte[] gzBuffer) 
{ 
    if (gzBuffer == null) 
     return null; 
    using (var ms = new MemoryStream(gzBuffer)) 
    { 
     using (var decompress = new GZipStream(ms, CompressionMode.Decompress)) 
     { 
      using (var sr = new StreamReader(decompress, Encoding.UTF8)) 
      { 
       string ret = sr.ReadToEnd(); 
       // this is the extra check that is needed !? 
       if (ret == "") 
        ret = sr.ReadToEnd(); 
       return ret; 
      } 
     } 
    } 
} 

所有的建議表示讚賞。 - 維克多·卡塞爾

+0

我不認爲你需要檢查,它看起來多餘。 – Nick 2010-12-16 14:01:53

回答

1

嘗試添加ms.Position = 0string ret = sr.ReadToEnd();

+0

我試過了,它沒有幫助,我也試過ms.Seek(0,SeekOrigin.Begin)。 – 2010-12-16 14:11:15

1

The MSDN Page on the function提到了以下幾點:

如果當前方法拋出一個OutOfMemoryException,讀者的底層流對象的位置由數量前進該方法能夠讀取的字符,但已讀入內部ReadLine緩衝區的字符將被丟棄。如果在將數據讀入緩衝區後操作基礎流的位置,則基礎流的位置可能與內部緩衝區的位置不匹配。要重置內部緩衝區,請調用DiscardBufferedData方法;但是,這種方法會降低性能,只有在絕對必要時才應該調用。

也許嘗試調用DiscardBufferedData()ReadToEnd()之前,看看它做什麼(我知道你沒有得到的例外,但它是所有我能想到的...)?

+0

不,調用DiscarBufferedData()也沒有幫助。 – 2010-12-16 14:57:55

1

我希望這會有所幫助。

對於ByteArray中:

static byte[] CompressToByte(string data) 
{ 
    MemoryStream outstream = new MemoryStream(); 
    GZipStream compressionStream = 
    new GZipStream(outstream, CompressionMode.Compress, true); 
    StreamWriter writer = new StreamWriter(compressionStream); 
    writer.Write(data); 
    writer.Close(); 
    return StreamToByte(outstream); 
} 

static string Decompress(byte[] data) 
{ 
    MemoryStream instream = new MemoryStream(data); 
    GZipStream compressionStream = 
    new GZipStream(instream, CompressionMode.Decompress); 
    StreamReader reader = new StreamReader(compressionStream); 
    string outtext = reader.ReadToEnd(); 
    reader.Close(); 
    return outtext; 
} 

public static byte[] StreamToByte(Stream stream) 
{ 
    stream.Position = 0; 
    byte[] buffer = new byte[128]; 
    using (MemoryStream ms = new MemoryStream()) 
    { 
     while (true) 
     { 
      int read = stream.Read(buffer, 0, buffer.Length); 
      if (!(read > 0)) 
       return ms.ToArray(); 
      ms.Write(buffer, 0, read); 
     } 
    } 
}

您可以if(read <= 0)取代if(!(read > 0))。 出於某種原因if(read <= 0)不顯示上面corret。

對於流:

static Stream CompressToStream(string data) 
{ 
    MemoryStream outstream = new MemoryStream(); 
    GZipStream compressionStream = 
    new GZipStream(outstream, CompressionMode.Compress, true); 
    StreamWriter writer = new StreamWriter(compressionStream); 
    writer.Write(data); 
    writer.Close(); 
    return outstream; 
} 

static string Decompress(Stream data) 
{ 
    data.Position = 0; 
    GZipStream compressionStream = 
    new GZipStream(data, CompressionMode.Decompress); 
    StreamReader reader = new StreamReader(compressionStream); 
    string outtext = reader.ReadToEnd(); 
    reader.Close(); 
    return outtext; 
}
2

gzBuffer來自哪裏?你是否也編寫了生成壓縮數據的代碼?

您的緩衝區數據可能是無效的或者某種程度上不完整,也可能是由多個放氣流串聯在一起組成的。

+0

我發現了這個錯誤。正如邁克爾在壓縮程序中所建議的那樣。我錯過了在GZipStream上調用Close()。 compress.Write(raw,0,raw.Length); compress.Close(); return ms.ToArray(); 發生了什麼事情是數據似乎被保存在一個糟糕的狀態,需要在稍後的解壓縮例程中對ReadToEnd()進行兩次調用才能提取相同的數據。很奇怪! – 2010-12-17 09:05:43

3

我發現了這個錯誤。正如邁克爾在壓縮程序中所建議的那樣。我錯過了在GZipStream上調用Close()。

public static byte[] Compress(string text) 
{ 
    if (string.IsNullOrEmpty(text)) 
     return null; 

    byte[] raw = Encoding.UTF8.GetBytes(text); 
    using (var ms = new MemoryStream()) 
    { 
     using (var compress = new GZipStream (ms, CompressionMode.Compress)) 
     { 
      compress.Write(raw, 0, raw.Length); 
      compress.Close(); 

      return ms.ToArray(); 
     } 
    } 
} 

事情是這樣的數據似乎得到保存,在解壓縮程序需要兩次調用ReadToEnd的()以後提取相同的數據的糟糕狀態。很奇怪!