28

我正在创建一个指定大小的文件——我不在乎里面有什么数据,虽然随机会很好。目前我正在这样做:

        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();
            }
        }

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

感谢所有的答案。

编辑

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

方法1:乔恩·斯基特

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

不适用 - 2Gb 文件的内存不足异常

方法 2:乔恩·斯基特

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);
    }
}

@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);
}

257、287、3、3、2、3 等

4

5 回答 5

44

好吧,一个非常简单的解决方案:

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

内存效率稍高的版本:)

// 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);
    }
}

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

于 2010-12-13T18:31:03.740 回答
14

没有比利用 NTFS 内置的稀疏文件支持更快的方法了,NTFS 是硬盘上使用的 Windows 文件系统。此代码在几分之一秒内创建一个 1 GB 的文件:

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);
        }
    }
}

读取时,文件仅包含零。

于 2010-12-13T18:55:38.863 回答
0

创建大文件的有效方法:

    FileStream fs = new FileStream(@"C:\temp\out.dat", FileMode.Create);
    fs.Seek(1024 * 6, SeekOrigin.Begin);
    System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
    fs.Write(encoding.GetBytes("test"), 0, 4);
    fs.Close();

然而,这个文件将是空的(除了最后的“测试”)。不清楚您到底要做什么——带有数据的大文件,或者只是大文件。您可以修改它以在文件中稀疏地写入一些数据,但不会完全填充它。如果您确实希望整个文件充满随机数据,那么我能想到的唯一方法是使用上面 Jon 的随机字节。

于 2010-12-13T18:50:41.733 回答
0

您可以使用我创建的以下类来生成随机字符串

using System;
using System.Text;

public class RandomStringGenerator
{
    readonly Random random;

    public RandomStringGenerator()
    {
        random = new Random();
    }
    public string Generate(int length)
    {
        if (length < 0)
        {
            throw new ArgumentOutOfRangeException("length");
        }
        var stringBuilder = new StringBuilder();

        for (int i = 0; i < length; i++)
        {
            char ch = (char)random.Next(0,255 );
            stringBuilder.Append(ch);
        }

        return stringBuilder.ToString();

    }

}

用于使用

 int length = 10;
        string randomString = randomStringGenerator.Generate(length);
于 2010-12-13T18:36:14.273 回答
-1

一种改进是用数据填充所需大小的缓冲区并一次将其全部刷新。

于 2010-12-13T18:32:30.597 回答