Запись текстового файла в память и сохранение его с помощью savefiledialog

#c# #memorystream #savefiledialog #textwriter

#c# #memorystream #savefiledialog #textwriter

Вопрос:

Я пытаюсь создать текстовый файл в памяти, добавить к нему несколько строк и в конце сохранить файл в текстовом файле. Я могу обработать часть savedialog, но я не знаю, как получить текстовый файл из памяти. Любая помощь и советы будут оценены.

Что я делаю до сих пор, так это:

 //Initialize in memory text writer
MemoryStream ms = new MemoryStream(); 
TextWriter tw = new StreamWriter(ms);

tw.WriteLine("HELLO WORLD!");
tw.WriteLine("I WANT TO SAVE THIS FILE AS A .TXT FILE!);
  

пожалуйста, обратите внимание
Я вызову tw.WriteLine () добавляет больше строк в разные места, поэтому я хочу сохранить это в конце программы (поэтому это не должно быть обернуто чем-то вроде использования{})

Обновить

StringBuilder кажется более надежным вариантом для этого! Я получаю странные вырезы в моем текстовом файле, когда я делаю это с помощью MemoryStream.

Спасибо.

Комментарии:

1. Зачем сначала создавать его в памяти, это будет медленно или интерактивно? Почему бы просто не записать его на диск, как только у вас будет имя файла из FileSaveDialog ?

2. Ну, у меня простая программа, и я не хочу заморачиваться с поиском временного пути или файла, я хочу, чтобы этот файл сохранялся только после завершения операции. затем должен появиться FileSaveDialog, позволяющий пользователю сохранять файл в любом месте, где он хочет.

3. Я добавил новый код к своему ответу. вы можете это увидеть. для этого нужно добавить только еще одну строку в ваш код.

4. ваши требования добавлены к моему ответу.

5. @Sean87 на самом деле не знаю, в чем проблема переноса части записи в текстовый файл в using инструкцию?

Ответ №1:

Я думаю, что вашим лучшим вариантом здесь было бы записать в StringBuilder , а когда закончите, File.WriteAllText . Если содержимое большое, вы могли бы рассмотреть возможность записи непосредственно в файл в первую очередь (через File.CreateText(path) ), но для файлов малого и среднего размера это должно быть нормально.

 var sb = new StringBuilder();

sb.AppendLine("HELLO WORLD!");
sb.AppendLine("I WANT TO SAVE THIS FILE AS A .TXT FILE!");

File.WriteAllText(path, sb.ToString());
  

Комментарии:

1. @Marc Спасибо, мои файлы, обратите внимание, будут содержать более 1000 строк, но где это ‘foo.txt ‘ будет сохранен? можно ли это сделать с помощью диалогового окна сохранения таким образом?

2. @Sean87 как написано? в текущем каталоге, что бы это ни было. Вы можете заменить его любым путем, который вам нравится — это было чисто показательно.

3. @Marc а также добавьте недостающее " в конце вашей 2-й строки

4. @Farzin — Я исправлю это на path ; в вопросе не показана вызываемая переменная dialog

5. Я передумал и теперь использую StringBuilder, поскольку MemoryStreams просто что-то перепутывает в моем текстовом файле, в основном я получаю вырезанный текст!! В любом случае спасибо!

Ответ №2:

Или что-то почти такое же, как ответ @ Marc, но достаточно другое, что, я думаю, стоит опубликовать там в качестве допустимого решения:

 using (var writer = new StringWriter())
{
    writer.WriteLine("HELLO WORLD!");
    writer.WriteLine("I WANT TO SAVE THIS FILE AS A .TXT FILE!");
    File.WriteAllLines(path, writer.GetStringBuilder().ToString());
}
  

Где path — строка, представляющая допустимый путь входа в файловую систему, предварительно определенный вами где-то в приложении.

Комментарии:

1. Разочарование Проблема в том, что я буду добавлять строки в свой memorystream в разных местах моей программы, нецелесообразно заключать всю мою программу в оператор using{}

2. @Sean87: Вы можете объявить StringWriter в любой области, которую вы пожелаете / требуете, просто не забудьте удалить, когда вы действительно закончите.

3. 1 StringWriter — это определенно правильный путь. Это намного проще в использовании, чем MemoryStream .

Ответ №3:

Предположим, что ваше SaveFileDialog имя «dialog»

 File.WriteAllBytes(dialog.FileName, Encoding.UTF8.GetBytes("Your string"));
  

или

 var text = "Your string";
text  = "some other text";
File.WriteAllText(dialog.FileName, text);
  

также в вашем собственном решении вы можете сделать это :

 MemoryStream ms = new MemoryStream(); 
TextWriter tw = new StreamWriter(ms);

tw.WriteLine("HELLO WORLD!");
tw.WriteLine("I WANT TO SAVE THIS FILE AS A .TXT FILE!);

// just add this
File.WriteAllBytes(dialog.FileName, ms.GetBuffer());
  

Комментарии:

1. ваш пример не сработает, потому что вы добавляете текст к строке text , поэтому в конце у вас будут объединены все строки. Вместо этого вы должны сделать что-то вроде text = "some other text" Environment.NewLine или просто использовать rn

2. есть несколько ошибок; вы не using несколько IDisposable объектов, но что более важно: вы записываете слишком большой резервный буфер ( GetBuffer() ) без ограничения фактической длины допустимых данных.

3. @Marc Он хочет просто записать несколько строк в файл. нет необходимости использовать IDisposable объекты или заботиться о размере буфера. не забывайте GC! GC разработан для вас и для того, чтобы не заботиться о буфере в этих простых ситуациях.

4. @FarzinZaker Это не то, что имеет в виду Marc. Он имеет в виду, что вы используете одноразовые вещи, не избавляясь от них! И GetBuffer , цитируя MSDN, «Обратите внимание, что буфер содержит выделенные байты, которые могут быть неиспользуемыми». Таким образом, вы потенциально записываете недопустимые данные. Это не имеет ничего общего с тем, что хочет пользователь, а просто ваш неправильный код. Также отсутствует цитата, нарушающая ваш код.

Ответ №4:

Что-то вроде этого.

 Microsoft.Win32.SaveFileDialog dlg = new Microsoft.Win32.SaveFileDialog();
dlg.FileName = "Document"; // Default file name
dlg.DefaultExt = ".text"; // Default file extension
dlg.Filter = "Text documents (.txt)|*.txt"; // Filter files by extension

// Show save file dialog box
Nullable<bool> result = dlg.ShowDialog();

// Process save file dialog box results
if (result == true)
{
    // Save document
    using (FileStream file = File.CreateText(dlg.FileName)
    {
        ms.WriteTo(file)
    }
}
  

Я не беспокоился о том, существует ли файл уже, но это должно подвести вас ближе.

Вам также может понадобиться ms.Seek(SeekOrgin.Begin, 0) .

Комментарии:

1. @Jordell Хм, не думаю, что это помогло бы, что произойдет с частью кода memorystream?

2. Зачем вам это нужно? Просто запишите его прямо в ‘FileStream’.

Ответ №5:

Другим способом добавления текста в конец файла может быть:

 if (saveFileDialog.ShowDialog() == DialogResult.OK) {
    using (var writer = new StreamWriter(saveFileDialog.Filename, true)) {
        writer.WriteLine(text);
    }
}
  

предположим, что text это строка, которую вам нужно сохранить в свой файл.
Если вы хотите добавить новые строки к этой строке простым способом, вы можете сделать:

 var sb = new StringBuilder();
sb.AppendLine("Line 1");
sb.AppendLine("Line 2");
  

и результирующая строка будет sb.ToString()

Если у вас уже есть Stream объект (в вашем примере a MemoryStream ), вы можете сделать то же самое, но заменить строку:

 using (var writer = new StreamWriter(saveFileDialog.Filename, true)) {
  

Автор:

 using (var writer = new StreamWriter(memoryStream)) {
  

Редактировать:
О переносе инструкций внутрь using :

Учтите, что это вообще не проблема. В моем первом примере все, что вам нужно будет сделать, это сохранить этот StringBuilder объект и продолжать добавлять к нему строки. Как только у вас будет то, что вы хотите, просто запишите данные в текстовый файл.

Если вы планируете записывать в текстовый файл более одного раза, просто очищайте StringBuilder каждый раз при записи, чтобы не получать дублирующиеся данные.