
Introduction
Everybody needs at least twice a file splitter utility. One day I created my own just to do the things to be done :), and then I realized that I could make it run much faster (the FileSPlitter v0.1 runs @ 1~2bytes/hour ^_^), so I inserted some multithreading, some event handling, enlarged the cache used, and of course, rewrote the split and merge methods. Now, it's quite fast: up to 20 Mb/s.
Note
The file splitter is now in a separate class, exposing different commented constructors, methods, and properties. It is disposable and gives the speed of the processing.
Using the code
Just instantiate the FileSplitter
, manage its events, and begin processing.
FileSplitter.Splitter fs = new FileSplitter.Splitter(dlgOpen.FileName,
dlgSaveTo.SelectedPath, CacheSize, SizeLimit);
fs.SplitDone += new EventHandler(fs_SplitDone);
fs.partialSplitDone += new EventHandler(fs_partialSplitDone);
fs.SplitError += new EventHandler(fs_SplitError);
fs.BeginSplit();
The Split
method is private
to the FileSplitter
class:
private void Split()
{
if (m_CacheSize > m_SizeLimit)
m_CacheSize = (uint)m_SizeLimit;
byte[] cBuffer = new byte[m_CacheSize];
int nCounter = 0;
m_fsIn = new FileStream(m_FileName, FileMode.Open, FileAccess.Read);
m_bReader = new BinaryReader(m_fsIn);
if (!Directory.Exists(m_OutDir))
Directory.CreateDirectory(m_OutDir);
else
{
Directory.Delete(m_OutDir, true);
Directory.CreateDirectory(m_OutDir);
}
int reads = 0;
try
{
do
{
m_fsOut = new FileStream(m_OutDir + "\\" +
nCounter.ToString() + ".part", FileMode.Create);
do
{
if ((m_fsIn.Length - m_fsIn.Position) < cBuffer.Length)
cBuffer = new byte[m_fsIn.Length - m_fsIn.Position];
reads = m_bReader.Read(cBuffer, 0, cBuffer.Length);
m_bWriter = new BinaryWriter(m_fsOut);
m_bWriter.Write(cBuffer, 0, reads);
m_Written += reads;// = fsIn.Position;
m_Progress = (uint)((float)m_Written * 100 / (float)m_FileSize);
OnPartialSplitDone(EventArgs.Empty);
} while ((m_fsOut.Position < m_SizeLimit) &&
(m_fsIn.Position < m_FileSize));
m_bWriter.BaseStream.Close();
m_Written = m_fsIn.Position;
nCounter++;
m_Progress = (uint)((float)m_Written * 100 / (float)m_FileSize);
OnPartialSplitDone(EventArgs.Empty);
} while ((m_fsIn.Position < m_fsIn.Length));
m_bReader.BaseStream.Close();
OnSplitDone(EventArgs.Empty);
}
catch (Exception e)
{
m_SplitErrorMessage = e.Message;
OnError(EventArgs.Empty);
abort();
}
GC.Collect();
}
.
.
.
public void BeginMerge()
{
m_tdMerger = new Thread(new ThreadStart(merge));
m_tdMerger.Priority = ThreadPriority.AboveNormal;
m_tdMerger.IsBackground = false;
m_tdMerger.Name = "Merging";
m_TimeStart = DateTime.Now;
m_tdMerger.Start();
}
Methods
public FileSplitter(string FileName, string DestinationFolder, int CacheSize, int SizeLimit)
: Fully qualified constructor - Splitting.
public FileSplitter(string FileName, string DestinationFolder, int SizeLimit)
: Constructor with default cache - Splitting.
public FileSplitter(string SourceFolder, int CacheSize)
: Fully qualified constructor - Merging.
public FileSplitter(string SourceFolder)
: Constructor with default cache - Merging.
public void Dispose()
: Disposes the class instance.
public void BeginMerge()
: Begins the merging thread.
public void BeginSplit()
: Begins the splitting thread.
Events
public event EventHandler partialCopyDone
: Triggered when a partial processing is done.
public event EventHandler CopyDone;
: Triggered when processing is done.
public event EventHandler Error;
: Triggered when an error occurs.
Properties
public string ErrorMessage
: Last error message
public int Progress
: Percentage of the entire progress (nice to use with a progress bar).
public long TotalDone
: Total size processed.
History
- v2.1: Final version, with real classes, events, and multithreading.
- V2.0: Events, multithreading, nicer and smoother.
- v0.1: The beginning.