Last active
August 29, 2015 14:05
-
-
Save XoseLluis/dc80792bcbf48d502dde to your computer and use it in GitHub Desktop.
Copies a file in a non locking mode, so that other processes will be able to write to it while the copy is taking place. The copy can be canceled, and events are raised each time a certaing percentage of the copy is achieved.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// deploytonenyures.blogspot.com | |
// example of how to use of the FileCopyTaker class | |
// while running the copy, you can easily try to append lines to the file with just: echo myline >> file.txt | |
using System; | |
using System.IO; | |
using System.Collections.Generic; | |
using System.Threading; | |
using System.Web.Script.Serialization; | |
class DoCopy | |
{ | |
public static void Main(String[] args) | |
{ | |
Console.WriteLine("Program started"); | |
if (args.Length < 1){ | |
Console.WriteLine("Wrong Parameters: DoCopy.exe configEntry"); | |
System.Environment.Exit(1); | |
} | |
string configKey = args[0]; | |
string configStr = new StreamReader("DoCopy.json").ReadToEnd(); | |
JavaScriptSerializer configReader = new JavaScriptSerializer(); | |
Dictionary<string, string[]> config = configReader.Deserialize<Dictionary<string, string[]>>(configStr); | |
if (!config.ContainsKey(configKey)){ | |
Console.WriteLine("the key: " + configKey + " does not exist in the config file"); | |
System.Environment.Exit(1); | |
} | |
string sourceFilePath = config[configKey][0]; | |
string targetFilePath = config[configKey][1]; | |
FileCopyTaker copyTaker = new FileCopyTaker(sourceFilePath, targetFilePath, 20); | |
copyTaker.PercentageCopied += (o, e) => { | |
Console.WriteLine(e.PercentageDone + "% of " + e.TotalBytes + " copied"); | |
}; | |
AutoResetEvent waitHandle = new AutoResetEvent(false); | |
copyTaker.CopyDone += (o, e) => { | |
Console.WriteLine("Copy completed"); | |
waitHandle.Set(); | |
}; | |
Console.WriteLine("Copying: " + sourceFilePath + " to: " + targetFilePath); | |
Console.WriteLine("Press C to Cancel"); | |
copyTaker.DoCopy(); //it runs in a separate thread | |
//Wait for the copy to be complete or for the user to cancel it | |
bool cancel = false; | |
bool copyFinished = false; | |
while (!cancel && !copyFinished){ | |
copyFinished = waitHandle.WaitOne(100); | |
if (!copyFinished && Console.KeyAvailable){ | |
if (Console.ReadKey().Key == ConsoleKey.C){ | |
cancel = true; | |
Console.WriteLine(); | |
copyTaker.Cancel(); | |
} | |
} | |
} | |
Console.WriteLine("Program finished"); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// deploytonenyures.blogspot.com | |
// copies a file in a non locking mode, so that other processes will be able to write to it while the copy is taking place. | |
// the copy can be canceled, and events are raised each time a certaing percentage of the copy is achieved. | |
using System; | |
using System.IO; | |
using System.Threading; | |
class CopyEventArgs: EventArgs | |
{ | |
public int PercentageDone {get; private set;} | |
//this is the total Bytes that have to be copied (that is, the file of the size) | |
public long TotalBytes {get; private set;} | |
public CopyEventArgs(int percentageDone, long totalBytes) | |
{ | |
this.PercentageDone = percentageDone; | |
this.TotalBytes = totalBytes; | |
} | |
} | |
class FileCopyTaker | |
{ | |
public event EventHandler<CopyEventArgs> PercentageCopied; | |
public event EventHandler<EventArgs> CopyDone; | |
public event EventHandler<EventArgs> CancelDone; | |
private string sourceFilePath; | |
private string targetFilePath; | |
private int blockSize = 0x10000; | |
//each time this percentage is copied, raise the PercentageCopied event | |
private int percentageToNotify; | |
private bool cancel = false; | |
public FileCopyTaker(string sourceFilePath, string targetFilePath, int percentageToNotify) | |
{ | |
this.sourceFilePath = sourceFilePath; | |
this.targetFilePath = targetFilePath; | |
this.percentageToNotify = (percentageToNotify > 0 && percentageToNotify < 100) ? percentageToNotify : 20; | |
this.PercentageCopied += (o, e) => {}; | |
this.CopyDone += (o, e) => {}; | |
this.CancelDone += (o, e) => {}; | |
} | |
// public void Pause() | |
// { | |
// | |
// } | |
// public void Continue() | |
// { | |
// | |
// } | |
// | |
// public void Stop() | |
// { | |
// | |
// } | |
public void Cancel() | |
{ | |
this.cancel = true; | |
} | |
public void DoCopy() | |
{ | |
new Thread(() => { | |
int totalPercentageCopied = 0; | |
long sourceSize = new FileInfo(this.sourceFilePath).Length; | |
long bytesPerPercentageStep = sourceSize / (100/this.percentageToNotify); | |
long bytesCopiedForCurrentPercentageStep = 0; | |
using(var inputFile = new FileStream(this.sourceFilePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)){ | |
using (var outputFile = new FileStream(this.targetFilePath, FileMode.Create)){ | |
var buffer = new byte[blockSize]; | |
int bytesRead; | |
while (!this.cancel && (bytesRead = inputFile.Read(buffer, 0, buffer.Length)) > 0){ | |
outputFile.Write(buffer, 0, bytesRead); | |
//Thread.Sleep(100); //test, simulate latency | |
bytesCopiedForCurrentPercentageStep += this.blockSize; | |
if (bytesCopiedForCurrentPercentageStep >= bytesPerPercentageStep){ | |
totalPercentageCopied += this.percentageToNotify; | |
this.PercentageCopied(this, new CopyEventArgs(totalPercentageCopied, sourceSize)); | |
bytesCopiedForCurrentPercentageStep = 0; | |
} | |
} | |
if (!this.cancel){ | |
this.CopyDone(this, new CopyEventArgs(100, sourceSize)); | |
} | |
} | |
} | |
//do this outside the "using" so the FileStream has already been closed | |
if (this.cancel){ | |
File.Delete(this.targetFilePath); | |
this.CancelDone(this, new CopyEventArgs(totalPercentageCopied, sourceSize)); | |
} | |
}).Start(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment