在C#中创建随机文件
我正在创建一个指定大小的文件 – 我不关心它中的数据,虽然随机会很好。 目前我这样做:
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文件的以下方法进行一些测试(以ms为单位的时间):
方法1:Jon Skeet
byte[] data = new byte[sizeInMb * 1024 * 1024]; Random rng = new Random(); rng.NextBytes(data); File.WriteAllBytes(fileName, data);
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); } }
@ 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等
嗯,一个非常简单的解决方案
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
实例 - 但需要注意的是它不是线程安全的。
没有更快的方法可以利用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); } } }
读取时,该文件仅包含零。
您可以使用我创建的以下类来生成随机字符串
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);
创建大文件的有效方法:
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上面的随机字节。
改进之处在于用数据填充所需大小的缓冲区并立即将其全部刷新。