与std::filesystem::resize_file在C ++中,可以改变一个文件的大小,而无需打开该文件。
C#中是否有类似的功能,允许在不打开文件的情况下更改文件的大小?
我认为将文件作为 FileStream 打开并以新大小再次保存会更慢。
使用FileStream.SetLength()将尽可能快。
它最终调用 Windows API 来设置文件的长度,与 std::filesystem::resize_file().
所以你只需要做这样的事情,它就会足够快:
using (var file = File.Open(myFilePath, FileMode.Open))
{
file.SetLength(myRequiredFileSize);
}
Run Code Online (Sandbox Code Playgroud)
FileStream.SetLength() 的实现是:
private void SetLengthCore(long value)
{
Contract.Assert(value >= 0, "value >= 0");
long origPos = _pos;
if (_exposedHandle)
VerifyOSHandlePosition();
if (_pos != value)
SeekCore(value, SeekOrigin.Begin);
if (!Win32Native.SetEndOfFile(_handle)) {
int hr = Marshal.GetLastWin32Error();
if (hr==__Error.ERROR_INVALID_PARAMETER)
throw new ArgumentOutOfRangeException("value", Environment.GetResourceString("ArgumentOutOfRange_FileLengthTooBig"));
__Error.WinIOError(hr, String.Empty);
}
// Return file pointer to where it was before setting length
if (origPos != value) {
if (origPos < value)
SeekCore(origPos, SeekOrigin.Begin);
else
SeekCore(0, SeekOrigin.End);
}
}
Run Code Online (Sandbox Code Playgroud)
(注意SeekCore()只是调用了 Windows APISetFilePointer()函数。)
这样做不会将文件读入内存。
此外,Windows API 函数SetEndOfFile()不会写入扩展区域,因此速度很快。文档说明If the file is extended, the contents of the file between the old end of the file and the new end of the file are not defined.- 这是由于数据未写入扩展区域造成的。
作为测试,我尝试了以下代码:
using System;
using System.Diagnostics;
using System.IO;
namespace Demo
{
public class Program
{
public static void Main()
{
string filename = @"e:\tmp\test.bin";
File.WriteAllBytes(filename, new byte[0]); // Create empty file.
var sw = Stopwatch.StartNew();
using (var file = File.Open(filename, FileMode.Open))
{
file.SetLength(1024*1024*1024);
}
Console.WriteLine(sw.Elapsed);
}
}
}
Run Code Online (Sandbox Code Playgroud)
我的 E:\ 驱动器是硬盘驱动器,而不是 SSD。
输出是: 00:00:00.0003574
因此,将文件扩展到 1GB 的时间不到一百秒。
| 归档时间: |
|
| 查看次数: |
119 次 |
| 最近记录: |