Подтвердить что ты не робот

Запись строки в поток и чтение ее не работает

Я хочу написать String для потока (в этом случае 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: ?

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

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


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

4b9b3361

Ответ 1

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

UPDATE

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

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 сразу после того, как вы закончили писать.

Ответ 3

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

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

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

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

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

Ответ 4

Я думаю, было бы намного более продуктивно использовать 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)

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

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

Ответ 5

Вам нужно reset поток в начало:

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

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

stringAsStream.Position = 0