【问题标题】:Writing a Text File in memory and saving it with savefiledialog在内存中写入文本文件并使用 savefiledialog 保存
【发布时间】:2011-08-07 20:33:54
【问题描述】:

我正在尝试在内存中创建一个文本文件,向其中添加一些行,最后将文件保存在文本文件中。我可以处理 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() 在不同的地方添加更多的行,所以我想在程序结束时保存它(所以这应该包含在 using{} 之类的东西之间)

更新

StringBuilder 似乎是一个更可靠的选择!当我使用 MemoryStream 执行此操作时,我的文本文件中出现了奇怪的剪切。

谢谢。

【问题讨论】:

  • 为什么要先在内存中创建它,这会很慢还是交互式的?获得FileSaveDialog 的文件名后,为什么不直接将其写入磁盘?
  • 好吧,我有一个简单的程序,不想费心寻找临时路径或文件,我希望仅在操作完成后保存此文件。然后应该出现一个 FileSaveDialog,让用户将文件保存在他想要的任何地方。
  • 我在我的答案中添加了一个新代码。你可以看到。它只需要在您的代码中添加另一行。
  • 您的要求已添加到我的回答中。
  • @Sean87 真的不知道将写入文本文件部分包装到using 语句中的问题是什么?

标签: c# memorystream savefiledialog textwriter


【解决方案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());

【讨论】:

  • @Marc 谢谢,我的文件将超过 1000 行,但是这个 'foo.txt' 将保存在哪里?会以这种方式通过保存对话框来完成吗?
  • @Sean87 写的?在当前目录中,无论是什么。您可以将其替换为您喜欢的任何路径 - 这纯粹是指示性的。
  • @Marc 并在第二个字符串的末尾添加缺少的 "
  • @Farzin - 我会将其更正为path;该问题显示没有变量名为dialog...
  • 我改变了主意,现在我正在使用 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 是一个字符串,表示有效的文件系统入口路径,由您在应用程序的某处预定义。

【讨论】:

  • 失望问题是我会在程序的不同位置向内存流中添加行,将所有程序包装在 using{} 语句中是不切实际的
  • @Sean87:您可以在任何您希望/要求的范围内声明StringWriter,只要确保在实际完成后处理。
  • +1 StringWriter 绝对是去这里的方式。比MemoryStream好用多了。
【解决方案3】:

假设您的 SaveFileDialog 名称是“对话”

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());

【讨论】:

  • 您的示例不起作用,因为您将文本附加到字符串text,所以最后您将得到所有行连接。相反,您应该执行text += "some other text" + Environment.NewLine 之类的操作,或者只使用\r\n
  • 那里有几个错误;你不是 using 几个 IDisposable 对象,但更重要的是:你正在编写 oversized 后备缓冲区 (GetBuffer()) 而不限制实际长度的有效数据。
  • @Marc 他只想在文件中写入一些字符串。无需使用 IDisposable 对象或关心缓冲区的大小。不要忘记GC! GC 是为您设计的,并且在这种简单的情况下不关心缓冲区。
  • @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)

【讨论】:

  • @Jordell 嗯不认为这会有所帮助,代码的内存流部分会发生什么?
  • 为什么需要它?只需将其直接写入“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 对象(在您的示例中为 MemoryStream),您可以执行相同操作,但替换该行:

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

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

编辑:
关于将语句包装在using

考虑到这根本不是问题。在我的第一个示例中,您所要做的就是保留 StringBuilder 对象,并继续向其添加行。获得所需内容后,只需将数据写入文本文件即可。

如果您打算多次写入文本文件,只需在每次写入时清除StringBuilder,以免得到重复数据。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多