C#:预先开始一个文件

使用C#将文本添加到文件开头的最佳方法是什么?

我找不到一个简单的方法来做到这一点,但想出了一些解决办法。

  1. 打开新文件,写入我想要添加的文本,将旧文件中的文本附加到新文件的末尾。

  2. 由于我想添加的文本应该less于200个字符,所以我在考虑将空格字符添加到文件的开头,然后用我想要添加的文本覆盖空格。

有没有其他人遇到这个问题,如果是的话,你做了什么?

添加到文件的开头(预先挂起而不是附加)通常不是受支持的操作。 你的#1选项是好的。 如果你不能写一个临时文件,你可以把整个文件放到内存中,把你的数据预先存储到字节数组中,然后将其覆盖掉(这只有在你的文件很小而且你不需要一次在内存中有一堆,因为预先configuration数组不是一件容易的事情)。

这适用于我,但对于小文件。 也许这不是一个很好的解决scheme,否则。

string currentContent = String.Empty; if (File.Exists(filePath)) { currentContent = File.ReadAllText(filePath); } File.WriteAllText(filePath, newContent + currentContent ); 

我认为最好的办法是创build一个临时文件。 添加您的文本,然后读取原始文件的内容,将其添加到临时文件。 然后你可以用临时文件覆盖原件。

你应该能够做到这一点,而无需打开一个新的文件。 使用以下File方法:

 public static FileStream Open( string path, FileMode mode, FileAccess access ) 

确保指定FileAccess.ReadWrite。

使用从File.Open返回的FileStream,将所有现有数据读入内存。 然后将指针重置到文件的开头,写入新的数据,然后写入现有的数据。

(如果文件太大或者您怀疑使用的内存过多,则无需将整个文件读入内存就可以执行此操作,但实现此操作仅供读者参考。)

是的,基本上你可以使用这样的东西:

 public static void PrependString(string value, FileStream file) { var buffer = new byte[file.Length]; while (file.Read(buffer, 0, buffer.Length) != 0) { } if(!file.CanWrite) throw new ArgumentException("The specified file cannot be written.", "file"); file.Position = 0; var data = Encoding.Unicode.GetBytes(value); file.SetLength(buffer.Length + data.Length); file.Write(data, 0, data.Length); file.Write(buffer, 0, buffer.Length); } public static void Prepend(this FileStream file, string value) { PrependString(value, file); } 

然后

 using(var file = File.Open("yourtext.txt", FileMode.Open, FileAccess.ReadWrite)) { file.Prepend("Text you want to write."); } 

虽然在大文件的情况下不是很有效。

使用这个类:

 public static class File2 { private static readonly Encoding _defaultEncoding = new UTF8Encoding(false, true); // encoding used in File.ReadAll*() private static object _bufferSizeLock = new Object(); private static int _bufferSize = 1024 * 1024; // 1mb public static int BufferSize { get { lock (_bufferSizeLock) { return _bufferSize; } } set { lock (_bufferSizeLock) { _bufferSize = value; } } } public static void PrependAllLines(string path, IEnumerable<string> contents) { PrependAllLines(path, contents, _defaultEncoding); } public static void PrependAllLines(string path, IEnumerable<string> contents, Encoding encoding) { var temp = Path.GetTempFileName(); File.WriteAllLines(temp, contents, encoding); AppendToTemp(path, temp, encoding); File.Replace(temp, path, null); } public static void PrependAllText(string path, string contents) { PrependAllText(path, contents, _defaultEncoding); } public static void PrependAllText(string path, string contents, Encoding encoding) { var temp = Path.GetTempFileName(); File.WriteAllText(temp, contents, encoding); AppendToTemp(path, temp, encoding); File.Replace(temp, path, null); } private static void AppendToTemp(string path, string temp, Encoding encoding) { var bufferSize = BufferSize; char[] buffer = new char[bufferSize]; using (var writer = new StreamWriter(temp, true, encoding)) { using (var reader = new StreamReader(path, encoding)) { int bytesRead; while ((bytesRead = reader.ReadBlock(buffer,0,bufferSize)) != 0) { writer.Write(buffer,0,bytesRead); } } } } } 

前置:

 private const string tempDirPath = @"c:\temp\log.log", tempDirNewPath = @"c:\temp\log.new"; StringBuilder sb = new StringBuilder(); ... File.WriteAllText(tempDirNewPath, sb.ToString()); File.AppendAllText(tempDirNewPath, File.ReadAllText(tempDirPath)); File.Delete(tempDirPath); File.Move(tempDirNewPath, tempDirPath); using (FileStream fs = File.OpenWrite(tempDirPath)) { //truncate to a reasonable length if (16384 < fs.Length) fs.SetLength(16384); fs.Close(); } 
 // The file we'll prepend to string filePath = path + "\\log.log"; // A temp file we'll write to string tempFilePath = path + "\\temp.log"; // 1) Write your prepended contents to a temp file. using (var writer = new StreamWriter(tempFilePath, false)) { // Write whatever you want to prepend writer.WriteLine("Hi"); } // 2) Use stream lib methods to append the original contents to the Temp // file. using (var oldFile = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.Read, FileShare.Read)) { using (var tempFile = new FileStream(tempFilePath, FileMode.Append, FileAccess.Write, FileShare.Read)) { oldFile.CopyTo(tempFile); } } // 3) Finally, dump the Temp file back to the original, keeping all its // original permissions etc. File.Replace(tempFilePath, filePath, null); 

即使你正在写的东西很小,Temp文件也会在.Replace()之前得到整个原始文件,所以它需要在磁盘上。

请注意,此代码不是线程安全的; 如果多个线程访问此代码,则可能会在这里进行的文件交换中丢失写入。 也就是说,这也是非常昂贵的,所以你要打开对它的访问权限 – 通过多个提供者将写入传递给缓冲区,缓冲区通过一个消费者线程定期清空。

下面的algorithm可以很容易地解决这个问题,它对于任何大小的文件,包括非常大的文本文件都是最有效的:

 string outPutFile = @"C:\Output.txt"; string result = "Some new string" + DateTime.Now.ToString() + Environment.NewLine; StringBuilder currentContent = new StringBuilder(); List<string> rawList = File.ReadAllLines(outPutFile).ToList(); foreach (var item in rawList) { currentContent.Append(item + Environment.NewLine); } File.WriteAllText(outPutFile, result + currentContent.ToString()); 

使用两个stream,你可以做到这一点,但请记住,这将仍然遍及整个文件的每一个添加

 using System; using System.IO; using System.Text; namespace FilePrepender { public class FilePrepender { private string file=null; public FilePrepender(string filePath) { file = filePath; } public void prependline(string line) { prepend(line + Environment.NewLine); } private void shiftSection(byte[] chunk,FileStream readStream,FileStream writeStream) { long initialOffsetRead = readStream.Position; long initialOffsetWrite= writeStream.Position; int offset = 0; int remaining = chunk.Length; do//ensure that the entire chunk length gets read and shifted { int read = readStream.Read(chunk, offset, remaining); offset += read; remaining -= read; } while (remaining > 0); writeStream.Write(chunk, 0, chunk.Length); writeStream.Seek(initialOffsetWrite, SeekOrigin.Begin); readStream.Seek(initialOffsetRead, SeekOrigin.Begin); } public void prepend(string text) { byte[] bytes = Encoding.Default.GetBytes(text); byte[] chunk = new byte[bytes.Length]; using (FileStream readStream = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { using(FileStream writeStream = File.Open(file, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite)) { readStream.Seek(0, SeekOrigin.End);//seek chunk.Length past the end of the file writeStream.Seek(chunk.Length, SeekOrigin.End);//which lets the loop run without special cases long size = readStream.Position; //while there's a whole chunks worth above the read head, shift the file contents down from the end while(readStream.Position - chunk.Length >= 0) { readStream.Seek(-chunk.Length, SeekOrigin.Current); writeStream.Seek(-chunk.Length, SeekOrigin.Current); shiftSection(chunk, readStream, writeStream); } //clean up the remaining shift for the bytes that don't fit in size%chunk.Length readStream.Seek(0, SeekOrigin.Begin); writeStream.Seek(Math.Min(size, chunk.Length), SeekOrigin.Begin); shiftSection(chunk, readStream, writeStream); //finally, write the text you want to prepend writeStream.Seek(0,SeekOrigin.Begin); writeStream.Write(bytes, 0, bytes.Length); } } } } } 

将文件的内容放入一个string中。 将要添加到文件顶部的新数据追加到该string – string = newdata + string 。 然后将文件的查找位置移动到0并将string写入文件。