Почему StringWriter.ToString возвращает `System.Byte[]`, а не данные?

UnZipFile метод записывает данные из inputStream в outputWriter, Зачем sr.ToString() возвращается System.Byte[] а не данные?

using (var sr = new StringWriter())
{
    UnZipFile(response.GetResponseStream(), sr);
    var content = sr.ToString();
}


public static void UnZipFile(Stream inputStream, TextWriter outputWriter)
{
    using (var zipStream = new ZipInputStream(inputStream))
    {
        ZipEntry currentEntry;
        if ((currentEntry = zipStream.GetNextEntry()) != null)
        {
            var size = 2048;
            var data = new byte[size];
            while (true)
            {
                size = zipStream.Read(data, 0, size);
                if (size > 0)
                {
                    outputWriter.Write(data);                       
                }
                else
                {
                    break;
                }
            }
        }
    }
}

3 ответа

Решение

Проблема на линии:

outputWriter.Write(data); 

StringWriter.Write не имеет перегрузки, ожидая byte[], Следовательно, Write(Object) называется вместо. И согласно MSDN:

Записывает текстовое представление объекта в текстовую строку или поток, вызывая метод ToString для этого объекта.

призвание ToString на байтовом массиве возвращает System.byte[], объясняя, как вы получаете эту строку в вашем StringWriter,

Причина проста:

data имеет тип byte[], Там нет перегрузки для byte[] на StringWriter поэтому он использует перегрузку для объекта. А потом звонит ToString() в байтовом массиве в штучной упаковке, который просто печатает тип.

Ваш код эквивалентен этому:

outputWriter.Write(data.ToString());

theateist,

Глядя на другие ответы здесь, я должен согласиться с тем, что причина, по которой "ToString()" возвращает System.Byte[], заключается в том, что именно это вы вкладываете в него, а все, что помещено в StringWriter, вызывает его собственное. Метод "ToString" при этом. (т.е. byte[].toString() = "System.byte[]"). На самом деле вся идея в том, что StringWriter предназначен только для записи в строку "buffer" (StringBuilder), поэтому теоретически, если ваш файл был достаточно большим (больше 2048), вы получите "System.Byte[]System"..Byte[]" (и т. Д.). Попробуйте это сделать в потоке памяти, а затем прочитать из этого потока, может быть лучшее понимание того, что вы смотрите. (Код не проверен, просто пример).

using (Stream ms = new MemoryStream())  
{
    UnZipFile(response.GetResponseStream(), ms);

    string content;

    ms.Position = 0;
    using(StreamReader s = new StreamReader(ms))
    {
        content = s.ReadToEnd();
    } 
}

public static void UnZipFile(Stream inputStream, Stream outputWriter)
{      
    using (var zipStream = new ZipInputStream(inputStream))
    {
        ZipEntry currentEntry;
        if ((currentEntry = zipStream.GetNextEntry()) != null)
        {
            int size = 2048;
            byte[] data = new byte[size]; 
            while (true)
            {
                size = zipStream.Read(data, 0, size);
                if (size > 0)
                {
                    outputWriter.Write(data);
                }
                else
                {
                    break;
                }
            }
        }
    }
}

Другая идея на самом деле заключается в использовании endcoding для получения строки

public string UnZipFile(Stream inputStream)
{
    string tmp;

    using(Stream zipStream = new ZipInputStream(inputStream))
    {
        ZipEntry currentEntry;

        if(currentEntry = zipStream.GetNextEntry()) != null)
        {
            using(Stream ms = new MemoryStream())
            {
                int size = 2048;
                byte[] data = new byte[size];
                while(true)
                {
                    if((size = zipStream.Read(data,0,size)) > 0)
                        ms.Write(data);
                    else
                        break;
                }
                tmp = Encoding.Default.GetString(ms.ToByteArray());
                }
            }
        }
    }
    return tmp;
}

Или, как последняя идея, вы могли бы изменить свой исходный код, чтобы иметь

outputWriter.Write(Encoding.Default.GetString(data));

Вместо

outputWriter.Write(data);

Кстати, пожалуйста, избегайте ключевого слова var в сообщениях, может быть, просто мой любимый пив, но код менее читабелен при использовании слабых типов.

StringWriter.Write: MSDN StringWriter.ToString: MSDN

Другие вопросы по тегам