Специальные символы в StreamWriter

Я использую streamwriter для записи строки в поток. Теперь, когда я получаю доступ к данным из потока, он добавляет символы «\ 0 \ 0 \ 0» в конец содержимого. Я должен добавить содержимое потока, поэтому это создает проблему, поскольку я не могу удалить эти символы с помощью методов trim() или remove() или replace().

Ниже приведен код, который я использую:

ДЛЯ ПИСЬМА:

using (MemoryMappedViewStream stream = mmf.CreateViewStream())
{
    using (StreamWriter writer = new StreamWriter(stream, System.Text.Encoding.Unicode))
    {
        try
        {
            string[] files = System.IO.Directory.GetFiles(folderName, "*.*", System.IO.SearchOption.AllDirectories);
            foreach (string str in files)
            {
                writer.WriteLine(str);
            }
            // writer.WriteLine(folderName);
        }
        catch (Exception ex)
        {
            Debug.WriteLine("Unable to write string. " + ex);
        }
        finally
        {
            mutex.ReleaseMutex();
            mutex.WaitOne();
        }
    }
}

ДЛЯ ЧТЕНИЯ:

 StringBuilder sb = new StringBuilder();
            string str = @"D:\Other Files\Test_Folder\New Text Document.txt";
 using (var stream = mmf.CreateViewStream())
                {
                    System.IO.StreamReader reader = new System.IO.StreamReader(stream);
                    sb.Append(reader.ReadToEnd());
                    sb.ToString().Trim('\0');
                    sb.Append("\n" + str);
                }

Как я могу предотвратить это?

[ОБНОВЛЕНИЯ] Написание

// Lock
            bool mutexCreated;
            Mutex mutex = new Mutex(true, fileName, out mutexCreated);
            if (!mutexCreated)
                mutex = new Mutex(true);
            try
            {
                using (MemoryMappedViewStream stream = mmf.CreateViewStream())
                {
                    using (BinaryWriter writer = new BinaryWriter(stream))
                    {
                        try
                        {
                            string[] files = System.IO.Directory.GetFiles(folderName, "*.*", System.IO.SearchOption.AllDirectories);
                            foreach (string str in files)
                            {
                                writer.Write(str);
                            }
                            writer.Flush();
                        }
                        catch (Exception ex)
                        {
                            Debug.WriteLine("Unable to write string. " + ex);
                        }
                        finally
                        {
                            mutex.ReleaseMutex();
                            mutex.WaitOne();
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine("Unable to monitor memory file. " + ex);
            }

Чтение

StringBuilder sb = new StringBuilder();
            string str = @"D:\Other Files\Test_Folder\New Text Document.txt";
            try
            {
                using (var stream = mmf.CreateViewStream())
                {
                    System.IO.BinaryReader reader = new System.IO.BinaryReader(stream);
                    sb.Append(reader.ReadString());
                    sb.Append("\n" + str);
                }
                using (var stream = mmf.CreateViewStream())
                {
                    System.IO.BinaryWriter writer = new System.IO.BinaryWriter(stream);
                    writer.Write(sb.ToString());
                }
                using (var stream = mmf.CreateViewStream())
                {
                    System.IO.BinaryReader reader = new System.IO.BinaryReader(stream);
                    Console.WriteLine(reader.ReadString());
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine("Unable to monitor memory file. " + ex);
            }

person Deepak Kumar    schedule 07.03.2012    source источник
comment
Вы пробовали Writer.Flush() после того, как закончили запись в файл?   -  person GrandMasterFlush    schedule 07.03.2012
comment
Только что попробовал с write.Flush(), но обратите внимание, работает..   -  person Deepak Kumar    schedule 07.03.2012
comment
Я не думаю, что поток добавляет что-то к концу контента. Строка терминатора '\0\0\0\' зависит от кодировки. Этот ответ может быть полезен.   -  person Alberto De Caro    schedule 07.03.2012
comment
using() подразумевает Flush, но может переместить код Mutex за пределы блока записи.   -  person Henk Holterman    schedule 07.03.2012
comment
И создайте свой Reader с явной кодировкой Unicode.   -  person Henk Holterman    schedule 07.03.2012
comment
Mutex может быть проблемой? Я пробовал Reader с кодировкой Unicode. Но никакой помощи.   -  person Deepak Kumar    schedule 07.03.2012
comment
Ваш текущий код записи ожидает мьютекс с потоком, все еще открытым (и не сброшенным).   -  person Henk Holterman    schedule 07.03.2012


Ответы (2)


Ваша комбинация MMF и TextWriter/TextReader, особенно ReadToEnd(), не подходит.

TextReader нуждается в концепции EOF базового файла, а MMF просто не предоставляет ее таким же образом. Вы получите свои струны, набитые \0\0... до вместимости MMF.

Как возможное исправление:

  • собрать строки для записи в StringBuilder
  • используйте BinaryWriter, чтобы записать его как 1 строку
  • прочитайте его с помощью BinaryReader.

Другие варианты - использовать WriteLine/ReadLine и определить некоторый маркер EOF (пустая строка или специальная строка).

BinaryWriter добавит к строке префикс длины, чтобы Reader знал, когда остановиться.

person Henk Holterman    schedule 07.03.2012
comment
Когда я пытаюсь читать из BinaryReader с помощью метода ReadString(), он возвращает только одну первую строку. Как я могу получить все данные из считывателя? - person Deepak Kumar; 07.03.2012
comment
Он должен вернуть всю строку, включая '\n'. Проверьте код написания или опубликуйте обе части. - person Henk Holterman; 07.03.2012
comment
Отредактируйте свой вопрос, опубликуйте 2-ю часть. - person Henk Holterman; 07.03.2012
comment
Я только что опубликовал код записи и чтения. Пожалуйста ознакомтесь. В коде записи есть путь к трем файлам, которые я записываю в файл MMF. И при чтении кода я сначала читаю существующий MMF, а затем добавляю в него еще один путь к файлу. - person Deepak Kumar; 07.03.2012
comment
Что касается обновления: это ясно, вы пишете несколько строк и читаете только 1. Еще раз прочитайте мои 1-й и 2-й пункты. - person Henk Holterman; 07.03.2012
comment
Я тоже так сделал. Но это не помогло. - person Deepak Kumar; 07.03.2012
comment
Извините, я думаю, что я сделал что-то не так раньше. Теперь он работает со StringBuilder. - person Deepak Kumar; 07.03.2012
comment
Привет, Хенк, у меня проблема. Не могли бы вы ответить здесь или где я могу поговорить с вами по поводу? - person Deepak Kumar; 09.03.2012
comment
Если у вас возникла новая проблема, выполните шаги публикации нового вопроса. Сделайте это ясным и независимым, чтобы другие тоже могли помочь. - person Henk Holterman; 09.03.2012
comment
Я просто написал вопрос. Пожалуйста, проверьте здесь stackoverflow.com/questions/9631778/ - person Deepak Kumar; 09.03.2012

StreamWriter не добавляет '\0'. Это всего лишь содержимое отображаемого в память файла, то, что было там до того, как вы начали писать. StreamReader нуждается в индикаторе конца файла, чтобы знать, когда прекращается чтение. В MMF нет ничего, кроме размера раздела. Как и второй аргумент, вы передаете MemoryMappedFile.CreateNew(string, long).

Или, другими словами, вы создали MMF, который слишком велик для потока. Ну, конечно, у вас не было машины времени, чтобы догадаться, насколько большим его сделать. Вам определенно нужно что-то с этим делать, обрезка нулей не достаточно хороша. Это пойдет не так во второй раз, когда вы запишете более короткий поток. Читатель теперь по-прежнему будет видеть байты из содержимого предыдущего потока, и они не будут равны нулю.

В противном случае это обычная головная боль с mmfs, они просто куски памяти, а поток - очень плохая абстракция этого. Одна из основных причин, по которой mmfs так долго не поддерживались .NET, хотя они являются очень важной функцией ОС. Вам нужны указатели для сопоставления mmf, и это просто плохо поддерживается на управляемом языке.

Я не вижу хорошего способа научить StreamReader новым трюкам в этом случае. Копирование байтов из mmf в MemoryStream решит проблему, но скорее лишает смысла mmf.

Вместо этого рассмотрите возможность использования трубы.

person Hans Passant    schedule 07.03.2012