StreamReader ReadToEnd () возвращает пустую строку с первой попытки - PullRequest
13 голосов
/ 16 декабря 2010

Я знаю, что этот вопрос уже задавался в 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;
            }
        }
    }
}

Все предложения приветствуются. - Виктор Кассель

Ответы [ 5 ]

4 голосов
/ 17 декабря 2010

Я нашел ошибку. Это было то, что Майкл предложил в процедуре сжатия. Я пропустил вызов Close () на GZipStream.

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 () в процедуре распаковки позже, чтобы извлечь те же данные. Очень странно!

2 голосов
/ 16 декабря 2010

Откуда приходит gzBuffer?Вы также написали код, который создает сжатые данные?

Возможно, имеющиеся у вас буферные данные недействительны или как-то неполны, или, возможно, они состоят из нескольких потоков дефляции, соединенных вместе.

2 голосов
/ 16 декабря 2010

попробуйте добавить ms.Position = 0 до string ret = sr.ReadToEnd();

1 голос
/ 16 декабря 2010

Надеюсь, это поможет.

Для 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) не отображается правильно.

Для потока:

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;
}
1 голос
/ 16 декабря 2010

Страница MSDN в функции упоминает следующее:

Если текущий метод генерирует исключение OutOfMemoryException, позиция читателя в базовом объекте Stream увеличивается на числосимволы, которые метод смог прочитать, но символы, уже прочитанные во внутренний буфер ReadLine, отбрасываются.Если вы манипулируете позицией базового потока после считывания данных в буфер, позиция базового потока может не совпадать с позицией внутреннего буфера.Чтобы сбросить внутренний буфер, вызовите метод DiscardBufferedData;однако этот метод замедляет производительность и должен вызываться только в случае крайней необходимости.

Возможно, попробуйте позвонить DiscardBufferedData() до вашего ReadToEnd() и посмотреть, что он делает (я знаю, вы не получаете исключение, но это все, что я могу придумать ...)?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...