42

I want to create a huge dummy file say 1~2 GBs in matter of seconds. here is what I've written in C#:

file.writeallbytes("filename",new byte[a huge number]);

and another way with indicating the status, was like following:

long FSS = din.TotalFreeSpace;
long segments = FSS / 10000;
long last_seg = FSS % 10000;
BinaryWriter br = new BinaryWriter(fs);

for (long i = 0; i < segments; i++)
{
    br.Write(new byte[10000]);

    this.label2.Text = "segments write :" + i.ToString() + "\r\n" + "segments remain :" + ((segments-i)+1).ToString();
    Application.DoEvents();
}
br.Write(new byte[last_seg]);
this.label2.Text += "\r\nDone!";
br.Close();

where din is Disk Information object

well with these two approach it takes something like 2 or more minutes to write such a big but dummy file. Is there any other faster way for doing so?

Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
Vahid Hashemi
  • 5,182
  • 10
  • 58
  • 88
  • 3
    BinaryWriter is for writing POCOs to a file in a format that .NET can read back from, it's not what you'd expect from the name. – Chris S Dec 10 '09 at 13:53

5 Answers5

91

Simply create the file, seek to a suitably large offset, and write a single byte:

FileStream fs = new FileStream(@"c:\tmp\huge_dummy_file", FileMode.CreateNew);
fs.Seek(2048L * 1024 * 1024, SeekOrigin.Begin);
fs.WriteByte(0);
fs.Close();

This will yield a 2GB file with basically unpredictable contents, which should be fine for your purposes.

mdb
  • 52,000
  • 11
  • 64
  • 62
  • 3
    +1 for an intriguingly simple solution (assuming dummy contents is ok). – Abel Dec 10 '09 at 13:47
  • it will take same amount of time to write the dummy file into the cool/flash/ram disk (I almost forget to say that I'm using the removable storage). – Vahid Hashemi Dec 10 '09 at 14:07
  • 8
    The contents are not unpredictable: the file will be filled with zeros when you do the write. If that wasn't done, it would be a security issue. – RickNZ Dec 12 '09 at 12:11
  • 2
    @RickNZ: while this will indeed be the case for common file systems, it isn't an explicit part of the API contract, and won't be the case for some third-party network redirectors. – mdb Dec 12 '09 at 20:01
  • Regarding what the file will be filled with: In Windows NT and later versions, data added to the end of the file is set to zero. In Windows 98 or earlier versions, data added to the end of the file is not set to zero, which means that previously deleted data is visible to the stream. http://msdn.microsoft.com/en-us/library/system.io.filestream.seek(v=vs.110).aspx – lfalin Sep 29 '14 at 22:15
  • FYI, generated files this way crashes Firefox file upload. Do not know why. – Teoman shipahi Apr 07 '15 at 17:12
  • 4
    FYI this generates a file of size 2 GiB + 1 byte – PythonJin Nov 24 '15 at 22:02
  • For Android (with Xamarin). This (as well as the method with SetLength) does create a file entry on the disk. However, the OS does not take into account all that file size - so it actually does not occupy the space on disk. Eventually, I had to use slower method: https://stackoverflow.com/a/4432207/3507404 – Ingweland Nov 05 '21 at 10:02
76

If you don't care about the contents, then by far the fastest way I know of is this - it is practically instant:

private void CreateDummyFile(string fileName, long length)
{
    using (var fileStream = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None))
    {
        fileStream.SetLength(length);
    }
}
Rob Levine
  • 40,328
  • 13
  • 85
  • 111
  • 12
    Out of curiosity, tested `SetLength` and `Seek` + `WriteByte` approaches. With *Seek* it took 15 seconds for 512MB, with just *SetLength* it took about 1 second. In both cases, even after many tests, the files were filled with NULLs (as opposed to arbitrary data). Not sure if that's a clean disk or some optimized zero-padded create under the hood. – Abel Dec 10 '09 at 14:06
  • Good spot - very interesting. I can confirm the same on mine; I'd hazard a guess that it is unlikely to be a clean disk in my case (messy and full hard disk!) – Rob Levine Dec 10 '09 at 14:18
  • for me it takes longer than mdb's approach :-? – Vahid Hashemi Dec 10 '09 at 14:24
  • have you tried benchmarking both a several times, deleting the file after each test, to exclude the possible influence of the disk filling up or other factors? – Rob Levine Dec 10 '09 at 14:29
  • yeah with a stopwatch :D all three approaches (mine + yours + mdbs) they are in a same range . no significant difference :-? as I mentioned I need this for removable storage , all of my test is on removable storage. – Vahid Hashemi Dec 10 '09 at 18:21
  • This is what MSDN says on SetLength(): "If the stream is expanded, the contents of the stream between the old and the new length are undefined." https://msdn.microsoft.com/en-us/library/system.io.filestream.setlength(v=vs.110).aspx – Vincent Aug 13 '15 at 13:00
4

If you just need a FileStream, you could use FileStream.SetLength. That will get you a stream which is 2 GB long. Then you can write the final byte at an arbitrary position of your choice. But the contents will be undefined.

If you're trying to actually create a file on the disk, yes, you'll need to actually write its contents. And yes, hard disks are going to be slow; something like a 1 GB/min write speed isn't totally ridiculous. Sorry -- that's physics!

John Feminella
  • 303,634
  • 46
  • 339
  • 357
2

Why did you not use the BackgroundWorker class to achieve this, as you can pass anything into the method ReportProgress to indicate the status report. See the example below:

        private BackgroundWorker bgWorker;
        public Form1()
        {
            InitializeComponent();
            bgWorker = new BackgroundWorker();
            bgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork);
            bgWorker.ProgressChanged += new ProgressChangedEventHandler(bgWorker_ProgressChanged);
            bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted);
            bgWorker.RunWorkerAsync();
        }

        void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
           this.label2.Text = "Done";
        }

        void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
           MyStatus myProgressStatus = (MyStatus)e.UserState;
           this.label2.Text = string.Format("segments write : {0}" + Environment.Newline + "Segments Remain: {1}", myProgressStatus.iWritten, myProgressStatus.iRemaining);
        }

        void bgWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            long FSS = din.TotalFreeSpace;
                long segments = FSS / 10000;
                long last_seg = FSS % 10000;
                BinaryWriter br = new BinaryWriter(fs);

                for (long i = 0; i < segments; i++)
                {
                    br.Write(new byte[10000]);
bgWorker.ReportProgress(i.ToString(), new MyStatus(i, ((segments-i) + 1)));

                }
                br.Write(new byte[last_seg]);
                br.Close();
        }

public class MyStatus{
   public int iWritten;
   public int iRemaining;
   public MyStatus(int iWrit, int iRem){
     this.iWritten = iWrit;
     this.iRemaining = iRem;
   }
}
}

This is a rough draft...

Kiquenet
  • 14,494
  • 35
  • 148
  • 243
t0mm13b
  • 34,087
  • 8
  • 78
  • 110
0

I could be wrong but you will probably find that it's impossible to create a file that large that quickly as there will be a bottleneck in the I/O writing process.

However in your code above the Applciation.DoEvents will be slowing things down. Also any repainting of the screenthis.label2.Text = will cause a slight slow down.

Kane
  • 16,471
  • 11
  • 61
  • 86