File.Copy VS. Manual Filestream.Write for Copying File

File.Copy vs. Manual FileStream.Write For Copying File

File.Copy was build around CopyFile Win32 function and this function takes lot of attention from MS crew (remember this Vista-related threads about slow copy performance).

Several clues to improve performance of your method:

  1. Like many said earlier remove Flush method from your cycle. You do not need it at all.
  2. Increasing buffer may help, but only on file-to-file operations, for network shares, or ftp servers this will slow down instead. 60 * 1024 is ideal for network shares, at least before vista. for ftp 32k will be enough in most cases.
  3. Help os by providing your caching strategy (in your case sequential reading and writing), use FileStream constructor override with FileOptions parameter (SequentalScan).
  4. You can speed up copying by using asynchronous pattern (especially useful for network-to-file cases), but do not use threads for this, instead use overlapped io (BeginRead, EndRead, BeginWrite, EndWrite in .net), and do not forget set Asynchronous option in FileStream constructor (see FileOptions)

Example of asynchronous copy pattern:

int Readed = 0;
IAsyncResult ReadResult;
IAsyncResult WriteResult;

ReadResult = sourceStream.BeginRead(ActiveBuffer, 0, ActiveBuffer.Length, null, null);
do
{
Readed = sourceStream.EndRead(ReadResult);

WriteResult = destStream.BeginWrite(ActiveBuffer, 0, Readed, null, null);
WriteBuffer = ActiveBuffer;

if (Readed > 0)
{
ReadResult = sourceStream.BeginRead(BackBuffer, 0, BackBuffer.Length, null, null);
BackBuffer = Interlocked.Exchange(ref ActiveBuffer, BackBuffer);
}

destStream.EndWrite(WriteResult);
}
while (Readed > 0);

Are there any difference in using File.Copy to move a file or to write a stream to the location?

File.Copy simply encapsulates the usage of streams, etc. No difference at all.

File.Copy versus read and write in C#

As you can see with Reflector, File.Copy use native windows methods to create a duplicate. I think it will be faster that read bytes from one stream and write to another one.

public static void Copy(string sourceFileName, string destFileName)
{
if (sourceFileName == null)
{
throw new ArgumentNullException("sourceFileName", Environment.GetResourceString("ArgumentNull_FileName"));
}
if (destFileName == null)
{
throw new ArgumentNullException("destFileName", Environment.GetResourceString("ArgumentNull_FileName"));
}
if (sourceFileName.Length == 0)
{
throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "sourceFileName");
}
if (destFileName.Length == 0)
{
throw new ArgumentException(Environment.GetResourceString("Argument_EmptyFileName"), "destFileName");
}
InternalCopy(sourceFileName, destFileName, false, true);
}

And content of InternalCopy method is:

[SecuritySafeCritical]
internal static string InternalCopy(string sourceFileName, string destFileName, bool overwrite, bool checkHost)
{
string fullPathInternal = Path.GetFullPathInternal(sourceFileName);
string dst = Path.GetFullPathInternal(destFileName);
new FileIOPermission(FileIOPermissionAccess.Read, new string[] { fullPathInternal }, false, false).Demand();
new FileIOPermission(FileIOPermissionAccess.Write, new string[] { dst }, false, false).Demand();
if (!Win32Native.CopyFile(fullPathInternal, dst, !overwrite))
{
int errorCode = Marshal.GetLastWin32Error();
string maybeFullPath = destFileName;
if (errorCode != 80)
{
using (SafeFileHandle handle = Win32Native.UnsafeCreateFile(fullPathInternal, -2147483648, FileShare.Read, null, FileMode.Open, 0, IntPtr.Zero))
{
if (handle.IsInvalid)
{
maybeFullPath = sourceFileName;
}
}
if ((errorCode == 5) && Directory.InternalExists(dst))
{
throw new IOException(Environment.GetResourceString("Arg_FileIsDirectory_Name", new object[] { destFileName }), 5, dst);
}
}
__Error.WinIOError(errorCode, maybeFullPath);
}
return dst;
}

How to use filestream for copying files in c#

for copying i used below code :-

 public static void Copy(string inputFilePath, string outputFilePath)
{
int bufferSize = 1024 * 1024;

using (FileStream fileStream = new FileStream(outputFilePath, FileMode.OpenOrCreate, FileAccess.Write,FileShare.ReadWrite))
//using (FileStream fs = File.Open(<file-path>, FileMode.Open, FileAccess.Read, FileShare.Read))
{
FileStream fs = new FileStream(inputFilePath, FileMode.Open, FileAccess.ReadWrite);
fileStream.SetLength(fs.Length);
int bytesRead = -1;
byte[] bytes = new byte[bufferSize];

while ((bytesRead = fs.Read(bytes, 0, bufferSize)) > 0)
{
fileStream.Write(bytes, 0, bytesRead);
}
}
}

Performance wise: File.Copy vs File.WriteAllText function in C#?

If the file is relatively small it is likely to remain cached in Windows disk cache, so the performance difference will be small, or it might even be that File.Copy() is faster (since Windows will know that the data is the same, and File.Copy() calls a Windows API that is extremely optimised).

If you really care, you should instrument it and time things, although the timings are likely to be completely skewed because of Windows file caching.

One thing that might be important to you though: If you use File.Copy() the file attributes including Creation Time will be copied. If you programatically create all the files, the Creation Time is likely to be different between the files.

If this is important to you, you might want to programatically set the the file attributes after the copy so that they are the same for all files.

Personally, I'd use File.Copy().

Is C# File.Copy close to the same thing as copying a file via explorer in terms of performance?

As you can see in the reference source, the File.Copy method internally uses a native Win32 call, specifically CopyFile (from here in the reference source).

The performance should be more or less the same as Windows Explorer. There is just a little overhead, but that wouldn't do anything in the actual copying.

File.Copy a file created in memory

Use File.WriteAllBytes to create a new file (or overwrite an existing file) from a byte array:

File.WriteAllBytes(fileName, bytes);

Note that a MemoryStream (what you created) really isn't a "file", so File.Copy can't be used.



Related Topics



Leave a reply



Submit