StreamReader ReadToEnd()在第一次尝试时返回空字符串

时间:2010-12-16 13:53:32

标签: c# streamreader

我知道之前在Stackoverflow上已经问过这个问题,但找不到解释。

当我尝试从压缩字节数组中读取字符串时,我在第一次尝试时得到一个空字符串,在第二次尝试时我得到了字符串。

代码示例:

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

所有建议都表示赞赏。 - Victor Cassel

5 个答案:

答案 0 :(得分:4)

我发现了这个错误。正如迈克尔在压缩程序中所建议的那样。我错过了在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()以提取相同的数据。很奇怪!

答案 1 :(得分:2)

尝试在ms.Position = 0

之前添加string ret = sr.ReadToEnd();

答案 2 :(得分:2)

gzBuffer来自哪里?您是否也编写了生成压缩数据的代码?

也许您拥有的缓冲区数据无效或不完整,或者它可能包含多个连接在一起的deflate流。

答案 3 :(得分:1)

The MSDN Page on the function提及以下内容:

  

如果当前方法抛出OutOfMemoryException,则读取器在底层Stream对象中的位置按方法能够读取的字符数提前,但已经读入内部ReadLine缓冲区的字符将被丢弃。如果在将数据读入缓冲区后操纵基础流的位置,则基础流的位置可能与内部缓冲区的位置不匹配。要重置内部缓冲区,请调用DiscardBufferedData方法;但是,这种方法会降低性能,只有在绝对必要时才应调用。

或许尝试在DiscardBufferedData()之前调用ReadToEnd()并查看它的作用(我知道你没有得到例外,但这是我能想到的全部......)?

答案 4 :(得分: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)

For Stream:

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