Запись Строки к Потоку и чтение его назад не работают

Я хочу записать Строку в Поток (MemoryStream в этом случае) и считать байты один за другим.

stringAsStream = new MemoryStream();
UnicodeEncoding uniEncoding = new UnicodeEncoding();
String message = "Message";

stringAsStream.Write(uniEncoding.GetBytes(message), 0, message.Length);

Console.WriteLine("This:\t\t" + (char)uniEncoding.GetBytes(message)[0]);
Console.WriteLine("Differs from:\t" + (char)stringAsStream.ReadByte());

(Нежелательный) результат, который я получаю:

This:         M
Differs from: ?

Похоже, что это не читается правильно, поскольку первым символом "Message" является 'M', который работает при получении байтов от экземпляра UnicodeEncoding, но не при чтении их назад из потока.

Что я делаю неправильно?


Большее изображение: у Меня есть алгоритм, который будет работать над байтами Потока, я хотел бы быть максимально общим и работа с любым Потоком. Я хотел бы преобразовать Строку ASCII в MemoryStream или возможно использовать другой метод, чтобы смочь работать над Строкой как Поток. Рассматриваемый алгоритм будет работать над байтами Потока.

37
задан Deleted 13 April 2010 в 13:56
поделиться

4 ответа

После того, как вы напишете в MemoryStream и перед тем, как прочитать его обратно, вам нужно Искать обратно в начало MemoryStream , чтобы вы не чтение с конца.

ОБНОВЛЕНИЕ

Увидев ваше обновление, я думаю, что есть более надежный способ создания потока:

UnicodeEncoding uniEncoding = new UnicodeEncoding();
String message = "Message";

// You might not want to use the outer using statement that I have
// I wasn't sure how long you would need the MemoryStream object    
using(MemoryStream ms = new MemoryStream())
{
    var sw = new StreamWriter(ms, uniEncoding);
    try
    {
        sw.Write(message);
        sw.Flush();//otherwise you are risking empty stream
        ms.Seek(0, SeekOrigin.Begin);

        // Test and work with the stream here. 
        // If you need to start back at the beginning, be sure to Seek again.
    }
    finally
    {
        sw.Dispose();
    }
}

Как видите, этот код использует StreamWriter для записи всей строки (с правильной кодировкой) в MemoryStream . Это избавляет от проблем, связанных с записью всего массива байтов для строки.

Обновление: У меня несколько раз возникала проблема с пустым потоком. Достаточно позвонить Flush сразу после того, как вы закончите писать.

63
ответ дан 27 November 2019 в 04:07
поделиться

Вам необходимо сбросить поток в начало:

stringAsStream.Seek(0, SeekOrigin.Begin);
Console.WriteLine("Differs from:\t" + (char)stringAsStream.ReadByte());

Это также можно сделать, установив для свойства Position значение 0:

stringAsStream.Position = 0
1
ответ дан 27 November 2019 в 04:07
поделиться

Я думаю, было бы намного продуктивнее использовать TextWriter , в данном случае StreamWriter для записи в MemoryStream. После этого, как говорили другие, вам нужно «перемотать» MemoryStream, используя что-то вроде stringAsStream.Position = 0L; .

stringAsStream = new MemoryStream();

// create stream writer with UTF-16 (Unicode) encoding to write to the memory stream
using(StreamWriter sWriter = new StreamWriter(stringAsStream, UnicodeEncoding.Unicode))
{
  sWriter.Write("Lorem ipsum.");
}
stringAsStream.Position = 0L; // rewind

Обратите внимание:

StreamWriter по умолчанию использует экземпляр UTF8Encoding, если не указано иное. Этот экземпляр UTF8Encoding создается без метки порядка байтов (BOM)

Кроме того, вам обычно не нужно создавать новый UnicodeEncoding () , поскольку он уже есть в качестве статического члена класса. для использования в удобных вариантах utf-8, utf-16 и utf-32.

И затем, наконец (как говорили другие), вы пытаетесь преобразовать байт напрямую в char , а это не так. Если бы у меня был поток памяти и я знал, что это строка, я бы использовал TextReader , чтобы вернуть строку из байтов. Мне кажется «опасным» возиться с необработанными байтами.

5
ответ дан 27 November 2019 в 04:07
поделиться

Вы используете message.Length , который возвращает количество символов в строке, но вы должны использовать для чтения нубмер байт . Вы должны использовать что-то вроде:

byte[] messageBytes = uniEncoding.GetBytes(message);
stringAsStream.Write(messageBytes, 0, messageBytes.Length);

Затем вы читаете один байт и ожидаете получить из него символ, просто приведя его к char . UnicodeEncoding будет использовать два байта на символ.

Как говорит Джастин, вы также не пытаетесь вернуться к началу потока.

В принципе, я боюсь, что здесь все не так. Пожалуйста, дайте нам более широкую картину, и мы поможем вам понять, чем вы должны на самом деле делать. Использование StreamWriter для записи, а затем StreamReader для чтения - это, возможно, то, что вам нужно, но мы не можем точно сказать, исходя только из того короткого фрагмента кода, который вы показали.

16
ответ дан 27 November 2019 в 04:07
поделиться
Другие вопросы по тегам:

Похожие вопросы: