FileStream 和 StreamWriter - 如何在写入后截断文件的其余部分?

Posted

技术标签:

【中文标题】FileStream 和 StreamWriter - 如何在写入后截断文件的其余部分?【英文标题】:FileStream and StreamWriter - How to truncate the remainder of the file after writing? 【发布时间】:2012-01-17 20:28:59 【问题描述】:
var fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
using(var writer = new StreamWriter(fs))
    writer.Write(....);

如果文件之前包含文本并且新写入的文本比文件中已有的内容短,我如何确保文件中过时的尾随内容被截断?

请注意,在这种情况下,不能以截断模式打开文件。当我收到FileStream 对象时,该文件已经打开。上面的代码只是为了说明流的属性。

编辑

扩展下面的答案,解决方案是:

var fs = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
using(var writer = new StreamWriter(fs))

    writer.Write(....);
    writer.Flush();
    fs.SetLength(fs.Position);

【问题讨论】:

答案/解决方案代码在我看来是错误的:在调用 writer.Flush 或 writer.Dipose() 之后读取 fs.Position 之前不会给你真正的字节数.您很幸运,因为 Stream 在写入时会自动扩展,但是由于 2 次长度调整适用于 1 次写入,您的文件可能会不必要地碎片化。 【参考方案1】:

你可以试试writer.BaseStream.SetLength(writer.BaseStream.Position),虽然我不确定它的效果如何。

对于 FileStream,我认为应该将文件截断到当前位置。

【讨论】:

【参考方案2】:

使用SetLength 设置文件的新长度 - 文件应该被截断。

有关相关问题,请参阅 this answer。

【讨论】:

刚刚在您发布它的同时找到了答案。干杯:)【参考方案3】:

如果文件超过 1 MB,此代码将截断部分日志文件。

using (FileStream fs = File.Open("C:\\LogFile.txt", FileMode.OpenOrCreate))
        
            int OneMB = 1000000;

            fs.Seek(0, SeekOrigin.Begin);
            if (fs.Length > OneMB)
             
                int fileByte = 1;
                fs.Position  = fs.Seek(fs.Length / 2, SeekOrigin.Begin);
                List<byte> bytes = new List<byte>();

                while (fileByte > 0)
                
                   fileByte = fs.ReadByte();
                   bytes.Add((byte)fileByte);
                

                fs.SetLength(0);
                fs.Position = 0;
                fs.Write(bytes.ToArray(), 0, bytes.Count());

                fs.Seek(0, SeekOrigin.End);
                var stringBytes =  UTF8Encoding.ASCII.GetBytes($"Test1" + Environment.NewLine);
                fs.Write(stringBytes, 0, stringBytes.Length);  
            
            else
            
                fs.Seek(0, SeekOrigin.End);
                var stringBytes = UTF8Encoding.ASCII.GetBytes($"Test2" + Environment.NewLine);
                fs.Write(stringBytes, 0, stringBytes.Length); 
            

            fs.Flush();
        
    

【讨论】:

以上是关于FileStream 和 StreamWriter - 如何在写入后截断文件的其余部分?的主要内容,如果未能解决你的问题,请参考以下文章

IO 101:TextWriter、FileStream 和 StreamWriter 之间的主要区别是啥?

C#中FileStream和StreamWriter/StreamReader的区别

FileStream 和 StreamWriter - 如何在写入后截断文件的其余部分?

StreamReader和StreamWriter说明

文件流读写大文件移动 FileStream StreamWriter

C# 使用从 FileStream 创建的 StreamWriter 覆盖文件