最稳方式是用filestream配合random.nextbytes直接写入随机字节,禁用缓冲或设大缓冲(如64kb),避免字符串分配与编码开销,适用于纯占位测试文件。

用 FileStream 配合 Random.NextBytes 写入二进制数据最稳
直接写入随机字节比拼接字符串再编码快得多,避免字符串分配、编码转换和 GC 压力。适用于需要纯占位、不关心内容语义的测试文件(如压力测试磁盘 I/O、上传下载)。
关键点:
-
FileStream必须用FileMode.Create+FileAccess.Write,禁用缓冲(bufferSize = 0)或设为大块(如64 * 1024)能提升吞吐 -
Random.NextBytes生成的是byte[],直接写入,不经过任何中间字符串 - 别用
File.WriteAllText或StreamWriter——它们默认 UTF-8 BOM + 编码开销,1GB 文件可能慢 3–5 倍
var sizeInBytes = 1L << 30; // 1 GB
using var fs = new FileStream("test.bin", FileMode.Create, FileAccess.Write, FileShare.None, 64 * 1024, FileOptions.WriteThrough);
var buffer = new byte[64 * 1024];
var rand = new Random();
long written = 0;
while (written < sizeInBytes)
{
rand.NextBytes(buffer);
int toWrite = (int)Math.Min(buffer.Length, sizeInBytes - written);
fs.Write(buffer, 0, toWrite);
written += toWrite;
}要生成可读文本内容?用 Span<char></char> + RNGCryptoServiceProvider 更安全且可控
如果测试场景要求“看起来像日志”或“含字母数字”,又不想被 Random 的可预测性坑(比如并发多次调用产生重复序列),就该换加密级随机源,并绕过 string 分配。
常见错误:用 new string(...) 拼 10MB 日志行——瞬间触发大对象堆分配和 GC 暂停。
-
RNGCryptoServiceProvider(.NET 6+ 推荐RandomNumberGenerator)保证不可预测性 -
Span<char></char>在栈上操作字符数组,避免堆分配 - 字符集用
"abcdefghijklmnopqrstuvwxyz0123456789"这类固定池,查表比Next(0, 36)更快
var chars = "abcdefghijklmnopqrstuvwxyz0123456789".AsSpan();
var buffer = stackalloc char[8192];
using var rng = RandomNumberGenerator.Create();
for (long i = 0; i < lineCount; i++)
{
for (int j = 0; j < buffer.Length; j++)
{
var b = new byte[1];
rng.GetBytes(b);
buffer[j] = chars[b[0] % chars.Length];
}
// 直接 Write(Encoding.UTF8.GetBytes(buffer)) 或用 StreamWriter with leaveOpen=true 复用流
}超大文件(>10GB)注意 FileOptions.LargeFile 和稀疏文件支持
Windows 上创建几十 GB 文件时,默认行为会真正写满所有块,耗时长且填满磁盘。若只是占位、后续才填充,启用稀疏文件更高效。
- 先用
FileStream创建文件,调用SetLength扩容,再用DeviceIoControl(P/Invoke)标记为稀疏(仅 Windows) - .NET 6+ 可直接用
FileOptions.LargeFile提示系统优化缓存策略,但不等价于稀疏 - Linux/macOS 无原生稀疏标记,但
truncate命令(或FileStream.SetLength)本身就会创建空洞文件
注意:SetLength 后不写入任何数据,文件在磁盘上实际占用接近 0 字节——但某些测试工具(如 du -h)会显示逻辑大小,ls -l 显示的是 apparent size。
别忽略 FileOptions.WriteThrough 和 FileOptions.SequentialScan
这两个标志对性能影响明显,但文档里藏得深,容易被跳过。
-
FileOptions.WriteThrough绕过系统页缓存,直接落盘(适合测真实磁盘写速),否则Write调用返回时数据可能还在内存中 -
FileOptions.SequentialScan告诉 OS 你将顺序读写,让预读/缓存策略更激进(尤其在反复生成多个大文件时) - 混用
WriteThrough和小 buffer(如 4KB)会导致大量短 I/O,反而拖慢——buffer 至少 64KB 起步才合理
真正卡住的往往不是算法,而是没关缓存或 buffer 太小;实测中,同样 5GB 文件,buffer 4KB vs 1MB + WriteThrough,耗时差 7 倍以上。










