简体   繁体   English

在 C# 中创建一个随机文件

[英]Creating a Random File in C#

I am creating a file of a specified size - I don't care what data is in it, although random would be nice.我正在创建一个指定大小的文件 - 我不在乎里面有什么数据,尽管随机会很好。 Currently I am doing this:目前我正在这样做:

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

This isn't efficient or even the right way to go about it.这不是有效的,甚至不是正确的方法。 Any higher performance solutions?任何更高性能的解决方案?

Thanks for all the answers.感谢所有的答案。

Edit编辑

Ran some tests on the following methods for a 2Gb File (time in ms):对 2Gb 文件的以下方法进行了一些测试(时间以毫秒为单位):

Method 1: Jon Skeet方法 1:乔恩·斯基特

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

N/A - Out of Memory Exception for 2Gb File不适用 - 2Gb 文件的内存不足异常

Method 2: Jon Skeet方法 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 @1K - 45,868、23,283、23,346

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

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

Method 3 - Hans Passant (Super Fast but data isn't random)方法 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 etc. 257, 287, 3, 3, 2, 3 等

Well, a very simple solution:嗯,一个非常简单的解决方案:

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

A slightly more memory efficient version :)内存效率更高的版本:)

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

However, if you do this several times in very quick succession creating a new instance of Random each time, you may get duplicate data.但是,如果你在非常快速连续做数次创造了一个新的实例Random每一次,你可能会得到重复的数据。 See my article on randomness for more information - you could avoid this using System.Security.Cryptography.RandomNumberGenerator ... or by reusing the same instance of Random multiple times - with the caveat that it's not thread-safe.有关更多信息,请参阅我关于随机性的文章- 您可以使用System.Security.Cryptography.RandomNumberGenerator ... 或通过多次重用同一个Random实例来避免这种情况 - 但要注意它不是线程安全的。

There's no faster way then taking advantage of the sparse file support built into NTFS, the file system for Windows used on hard disks.没有比利用 NTFS(硬盘上使用的 Windows 文件系统)中内置的稀疏文件支持更快的方法了。 This code create a one gigabyte file in a fraction of a second:此代码在几分之一秒内创建了一个 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);
        }
    }
}

When read, the file contains only zeros.读取时,文件只包含零。

You can use this following class created by me for generate random strings您可以使用我创建的以下类来生成随机字符串

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

    }

}

for using用于使用

 int length = 10;
        string randomString = randomStringGenerator.Generate(length);

The efficient way to create a large file:创建大文件的有效方法:

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

However this file will be empty (except for the "test" at the end).然而,这个文件将为空(除了最后的“测试”)。 Not clear what is it exactly you are trying to do -- large file with data, or just large file.不清楚您到底要做什么 - 带有数据的大文件,或者只是大文件。 You can modify this to sparsely write some data in the file too, but without filling it up completely.您也可以修改它以在文件中稀疏地写入一些数据,但不要完全填满它。 If you do want the entire file filled with random data, then the only way I can think of is using Random bytes from Jon above.如果您确实希望用随机数据填充整个文件,那么我能想到的唯一方法是使用上面 Jon 的随机字节。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM