Reputation:
I was trying to copy a 5 GB ISO file onto a 32 GB flash drive with 29 GB of free space.
Windows 7 refused to let me drag-and-drop the file onto the flash drive, reporting the file was too large for the destination file system.
I eventually learned this was because the drive was formatted as FAT32 instead of NTFS, but not before I wrote this routine to copy the file over:
private void copyFile(string from, string to) {
bool ok = true;
using (StreamReader sr = new StreamReader(from, true)) {
using (StreamWriter sw = new StreamWriter(to, false, sr.CurrentEncoding)) {
int FOUR_K = 4048;
char[] buf = new char[FOUR_K];
try {
while (-1 < sr.Peek()) {
int len = sr.Read(buf, 0, FOUR_K);
sw.Write(buf, 0, len);
sw.Flush();
}
}
catch (Exception err) {
ok = false;
throw err;
}
}
}
if (ok) {
Console.WriteLine("Done!");
}
}
I let it run for about an hour, and it only got to 270 MB in file size.
What's going on?
What in my code is causing my file to take so long?
Is it my choice of the FOUR_K
variable size?
[UPDATE]
I have two ISO files: Win8-32bit at ~3 GB and Win8-64bit-Developer at ~5 GB. Using drag-and-drop, Windows Explorer copied the 3 GB file to my 32 GB flash drive in about three minutes.
Using Marc Gravell's technique, I went at this yet again:
[STAThread]
static void Main(string[] args) {
using (OpenFileDialog dlg = new OpenFileDialog()) {
dlg.Title = "Select File";
if (dlg.ShowDialog() == DialogResult.OK) {
using (FolderBrowserDialog fdg = new FolderBrowserDialog()) {
fdg.Description = "Select Destination";
if (fdg.ShowDialog() == DialogResult.OK) {
DateTime start = DateTime.Now;
Console.WriteLine("Started at {0:g}.\nWorking...", start);
using (FileStream fin = File.Open(dlg.FileName, FileMode.Open)) {
using (FileStream fout = new FileStream(Path.Combine(fdg.SelectedPath, dlg.SafeFileName), FileMode.Create)) {
try {
fin.CopyTo(fout);
} catch (Exception err) {
Console.WriteLine("An Error Occurred:");
Console.WriteLine(err.Message);
}
}
}
DateTime end = DateTime.Now;
TimeSpan span = (end - start);
Console.WriteLine("Process Ended at {0}.\nThe total minutes passed = {1}.", end, span.TotalMinutes);
Console.WriteLine("Press Any Key.");
Console.ReadKey();
}
}
}
}
}
Using the FileStream
instances above, the program ran for about 8 hours, copied exactly 4,194,300 KB
and then threw an Out Of Memory Exception.
Upvotes: 3
Views: 3938
Reputation: 28338
I suspect it's the Flush
call every time.
If you are using .NET 4, Stream now has a CopyTo
method:
using (var input = File.OpenRead(fromFile))
{
using (var output = File.OpenWrite(toFile))
{
input.CopyTo(output);
}
}
Upvotes: 3
Reputation: 25397
If you are trying to copy a binary file, why do you use StreamReader/StreamWriter
? Try something like this:
using (FileStream source = File.Open(@"c:\Source\data.iso", FileMode.Open))
{
FileStream destination = new FileStream(@"F:\Desitnation\data.iso",FileMode.OpenOrCreate));
source.CopyTo(destination);
destination.Close();
}
Upvotes: 2
Reputation: 1064254
I don't know about the performance issue (sounds very odd), but there's no reason the use a StreamReader
/ StreamWriter
here at all, since you could just copy at the binary level. Indeed, an ISO image is not text, so reading it into char
data is very likely to corrupt things. For info, even if you don't want to use File.Copy
, all you need here is:
using(var inFile = File.OpenRead(source))
using(var outFile = File.Create(destination))
{
inFile.CopyTo(outFile);
}
To get 270k in an hour you need to try hard (unless the IO is basically dead); my guess is it threw an error somewhere.
Upvotes: 8