#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
каждый раз при записи, чтобы не получать дублирующиеся данные.