【问题标题】:how to write to beginning of file with Stream Writer?如何使用 Stream Writer 写入文件的开头?
【发布时间】:2012-09-02 06:27:37
【问题描述】:

我想将我的字符串插入文件的开头。但是在流编写器的开头没有附加功能。那么我该怎么做呢?

我的代码是:

string path = Directory.GetCurrentDirectory() + "\\test.txt";
StreamReader sreader = new StreamReader(path);
string str = sreader.ReadToEnd();
sreader.Close();

StreamWriter swriter = new StreamWriter(path, false);

swriter.WriteLine("example text");
swriter.WriteLine(str);
swriter.Close();

但它似乎没有优化。那么有没有其他办法呢?

【问题讨论】:

  • 写入文件的开头将覆盖那里的内容。考虑将数据附加到文件的末尾而不是开头。
  • 您需要读取整个文件,将其存储在一个字符串中,然后使用String.Insert 将新数据插入该字符串的开头,然后用修改后的字符串重写整个文件。
  • @0_______0 这就像我所做的一样。
  • @Oded 我害怕覆盖。所以我寻找另一种方式如果是!。
  • 为什么要写入文件的start

标签: c# stream


【解决方案1】:

你快到了:

        string path = Directory.GetCurrentDirectory() + "\\test.txt";
        string str;
        using (StreamReader sreader = new StreamReader(path)) {
            str = sreader.ReadToEnd();
        }

        File.Delete(path);

        using (StreamWriter swriter = new StreamWriter(path, false))
        {
            str = "example text" + Environment.NewLine + str;
            swriter.Write(str);
        }

【讨论】:

  • +1。同样简单的new StreamWriter(path, true) 修复也可以。
  • 代码编辑:删除了不必要的 .Close() 调用 - using 已经处理好了。
  • 答案没有考虑,文件大小可以超过虚拟内存空间的可用区域。
【解决方案2】:

如果您不必考虑其他进程写入同一文件并且您的进程具有创建目录的权限,则处理此问题的最有效方法是:

  1. 使用临时名称创建新文件
  2. 编写新文本
  3. 附加文件中的旧文本
  4. 删除文件
  5. 重命名临时文件

它不会那么酷和快速,但至少你不必为你现在使用的方法在内存中分配一个巨大的字符串。

但是,如果您确定文件会很小,例如少于几兆字节,那么您的方法还不错。

但是你可以稍微简化你的代码:

public static void InsertText( string path, string newText )
{
    if (File.Exists(path))
    {
        string oldText = File.ReadAllText(path);
        using (var sw = new StreamWriter(path, false))
        {
            sw.WriteLine(newText);
            sw.WriteLine(oldText);
        }
    }
    else File.WriteAllText(path,newText);
}

对于大文件(即 > 几 MB)

public static void InsertLarge( string path, string newText )
{
    if(!File.Exists(path))
    {
        File.WriteAllText(path,newText);
        return;
    }

    var pathDir = Path.GetDirectoryName(path);
    var tempPath = Path.Combine(pathDir, Guid.NewGuid().ToString("N"));
    using (var stream = new FileStream(tempPath, FileMode.Create, 
        FileAccess.Write, FileShare.None, 4 * 1024 * 1024))
    {
        using (var sw = new StreamWriter(stream))
        {
            sw.WriteLine(newText);
            sw.Flush();
            using (var old = File.OpenRead(path)) old.CopyTo(sw.BaseStream);
        }
    }
    File.Delete(path);
    File.Move(tempPath,path);
}

【讨论】:

  • 为什么需要显式创建后备文件流?
  • SerG,那是前段时间,但我敢打赌,因为它提供了缓冲区大小的过载。
【解决方案3】:

类似这样的:

    private void WriteToFile(FileInfo pFile, string pData)
    {
        var fileCopy = pFile.CopyTo(Path.GetTempFileName(), true);

        using (var tempFile = new StreamReader(fileCopy.OpenRead()))
        using (var originalFile = new  StreamWriter(File.Open(pFile.FullName, FileMode.Create)))
        {
            originalFile.Write(pData);
            originalFile.Write(tempFile.ReadToEnd());
            originalFile.Flush();
        }

        fileCopy.Delete();
    }

【讨论】:

    猜你喜欢
    • 2013-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-27
    相关资源
    最近更新 更多