在C#中创建随机文件

Jas*_*son 22 c# performance createfile

我正在创建一个指定大小的文件 - 我不关心它中的数据,虽然随机会很好.目前我这样做:

        var sizeInMB = 3; // Up to many Gb
        using (FileStream stream = new FileStream(fileName, FileMode.Create))
        {
            using (BinaryWriter writer = new BinaryWriter(stream))
            {
                while (writer.BaseStream.Length <= sizeInMB * 1000000)
                {
                    writer.Write("a"); //This could be random. Also, larger strings improve performance obviously
                }
                writer.Close();
            }
        }
Run Code Online (Sandbox Code Playgroud)

这不是有效的,甚至是正确的方法.更高性能的解决方案?

感谢所有的答案.

编辑

对2Gb文件的以下方法进行一些测试(以ms为单位的时间):

方法1:Jon Skeet

byte[] data = new byte[sizeInMb * 1024 * 1024];
Random rng = new Random();
rng.NextBytes(data);
File.WriteAllBytes(fileName, data);
Run Code Online (Sandbox Code Playgroud)

N/A - 2Gb文件的内存不足

方法2:Jon Skeet

byte[] data = new byte[8192];
Random rng = new Random();
using (FileStream stream = File.OpenWrite(fileName))
{
    for (int i = 0; i < sizeInMB * 128; i++)
    {
         rng.NextBytes(data);
         stream.Write(data, 0, data.Length);
    }
}
Run Code Online (Sandbox Code Playgroud)

@ 1K - 45,868,23,283,23,346

@ 128K - 24,877,20,585,20,716

@ 8Kb - 30,426,22,936,22,936

方法3 - Hans Passant(超快但数据不是随机的)

using (var fs = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None))
{
    fs.SetLength(sizeInMB * 1024 * 1024);
}
Run Code Online (Sandbox Code Playgroud)

257,287,3,3,2,3等

Jon*_*eet 37

嗯,一个非常简单的解决方案

byte[] data = new byte[sizeInMb * 1024 * 1024];
Random rng = new Random();
rng.NextBytes(data);
File.WriteAllBytes(fileName, data);
Run Code Online (Sandbox Code Playgroud)

内存效率稍高的版本:)

// Note: block size must be a factor of 1MB to avoid rounding errors :)
const int blockSize = 1024 * 8;
const int blocksPerMb = (1024 * 1024) / blockSize;
byte[] data = new byte[blockSize];
Random rng = new Random();
using (FileStream stream = File.OpenWrite(fileName))
{
    // There 
    for (int i = 0; i < sizeInMb * blocksPerMb; i++)
    {
        rng.NextBytes(data);
        stream.Write(data, 0, data.Length);
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,如果您在非常快速的连续中多次执行此操作并创建Random每次的新实例,则可能会获得重复数据.有关更多信息,请参阅我的随机性文章 - 您可以使用System.Security.Cryptography.RandomNumberGenerator...或通过重复使用Random多次相同的实例来避免这种情况- 但需要注意的是它不是线程安全的.

  • @Ben:我会尽量避免使用128K,因为那样会在大型对象堆上使用。我会把它提高到8K :) (2认同)

Han*_*ant 13

没有更快的方法可以利用NTFS内置的稀疏文件支持,NTFS是用于硬盘的Windows文件系统.此代码在几分之一秒内创建一个千兆字节的文件:

using System;
using System.IO;

class Program {
    static void Main(string[] args) {
        using (var fs = new FileStream(@"c:\temp\onegigabyte.bin", FileMode.Create, FileAccess.Write, FileShare.None)) {
            fs.SetLength(1024 * 1024 * 1024);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

读取时,该文件仅包含零.