Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何将文件截断到一定大小,但保留结尾部分?_C#_.net_Text Files - Fatal编程技术网

C# 如何将文件截断到一定大小,但保留结尾部分?

C# 如何将文件截断到一定大小,但保留结尾部分?,c#,.net,text-files,C#,.net,Text Files,我有一个随时间追加的文本文件,我希望定期将其截断到一定大小,例如10MB,但保留最后10MB而不是第一个10MB 有什么聪明的方法可以做到这一点吗?我猜我应该找到正确的点,从那里读入一个新文件,删除旧文件,并将新文件重命名为旧名称。有更好的想法或示例代码吗?理想情况下,我不会将整个文件读入内存,因为文件可能很大 请不要对使用Log4Net等提出任何建议。在写入之前,您不需要阅读整个文件,尤其是在写入其他文件时。你可以分块工作;读一点,写一点,读多一点,再写一次。事实上,所有I/O都是这样完成的。

我有一个随时间追加的文本文件,我希望定期将其截断到一定大小,例如10MB,但保留最后10MB而不是第一个10MB

有什么聪明的方法可以做到这一点吗?我猜我应该找到正确的点,从那里读入一个新文件,删除旧文件,并将新文件重命名为旧名称。有更好的想法或示例代码吗?理想情况下,我不会将整个文件读入内存,因为文件可能很大


请不要对使用Log4Net等提出任何建议。

在写入之前,您不需要阅读整个文件,尤其是在写入其他文件时。你可以分块工作;读一点,写一点,读多一点,再写一次。事实上,所有I/O都是这样完成的。尤其是对于较大的文件,您永远不想同时读取它们


但您提出的是从文件开头删除数据的唯一方法。你必须重写它

您可以将文件读入二进制流,然后使用seek方法检索最后10MB的数据并将其加载到内存中。然后将该流保存到新文件中并删除旧文件。文本数据可能会被截断,因此您必须决定这是否是不可接受的

在这里查看Seek方法的示例:


如果您不介意将最后10MB的数据读入内存,那么这应该可以:

using(MemoryStream ms = new MemoryStream(10 * 1024 * 1024)) {
    using(FileStream s = new FileStream("yourFile.txt", FileMode.Open, FileAccess.ReadWrite)) {
        s.Seek(-10 * 1024 * 1024, SeekOrigin.End);
        s.CopyTo(ms);
        s.SetLength(10 * 1024 * 1024);
        s.Position = 0;
        ms.Position = 0; // Begin from the start of the memory stream
        ms.CopyTo(s);
    }
}

我从“false”开始测试解决方案,但它对我不起作用,它会修剪文件,但保留文件的开头,而不是结尾

我怀疑
CopyTo
复制了整个流,而不是从流位置开始。以下是我是如何做到这一点的:

int trimSize = 10 * 1024 * 1024;
using (MemoryStream ms = new MemoryStream(trimSize))
{
    using (FileStream s = new FileStream(logFilename, FileMode.Open, FileAccess.ReadWrite))
    {
        s.Seek(-trimSize, SeekOrigin.End);

        byte[] bytes = new byte[trimSize];
        s.Read(bytes, 0, trimSize);
        ms.Write(bytes, 0, trimSize);

        ms.Position = 0;
        s.SetLength(trimSize);
        s.Position = 0;
        ms.CopyTo(s);
    }
}

是的,minitech提供的代码示例可能是我的porposition的一个实现:)+1在最终CopyTo()之前可能还需要一个ms.Position=0(我使用了另一个文件流而不是MemoryStream)@minitech您的代码似乎只在.NET 4.0以上运行。我在.NET3.5项目中编写代码时发现了这一点。@Alex:它在.NET3.5下做什么?我认为我没有使用任何4.0特定的功能…在执行此操作之前,您还需要确保文件(“yourFile.txt”)的长度超过10 MB。否则,您将得到一个异常,告诉您正在尝试寻找一个负面位置。我在我的环境中确认了这一点(Win8.1 Pro,WMC 64位,.NET 4.6.1,C#)。在我的特殊情况下,
ms.CopyTo
不能正常工作。使用
fs.Write(ms.GetBuffer(),0,trimSize)更改它(我正在使用解决方案)+1.指出问题(: