Click here to Skip to main content
15,889,931 members
Articles / Programming Languages / C#
Article

The FileSplitter reLoaded

Rate me:
Please Sign up or sign in to vote.
4.46/5 (13 votes)
11 Aug 2008GPL31 min read 45.6K   632   47   9
Utilty to quickly split and merge files.

Sample Image - TheFileSplitterv2Processing.jpg

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.

C#
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:

C#
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.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


Written By
Chief Technology Officer
Morocco Morocco
in his studies, erratum discovered c/c++.he appreciated it.
when he met oracle products, in his job, he fell in love.
he uses c# .net & ms sql.

he created a "f.r.i.e.n.d.s" like soap movie, melting all of the above.
went back in the university.
after he took courses of artificial vision & imagery, he finished his studies with a successful license plate recognition project.

Comments and Discussions

 
QuestionMaximum file size Pin
brainchen10-Nov-12 18:42
brainchen10-Nov-12 18:42 
QuestionGreat little dll file Pin
rspercy652-Oct-11 12:31
rspercy652-Oct-11 12:31 
NewsNew VERSION Pin
eRRaTuM11-Aug-08 1:26
eRRaTuM11-Aug-08 1:26 
GeneralFeedback/bugs Pin
Sander van Driel4-Apr-06 0:30
Sander van Driel4-Apr-06 0:30 
G'day!

I've played around with your FileSplitter, and found that the splitting and merging mechanism works fine and pretty quick. However, I stumbled upon a number of bugs. In fact, only after a number of times I managed to split a file (in VS2005, with debug mode enabled). I'll enumerate the bugs for your convenience:

1) The program crashes when you type a filename into the 'Source File' textbox and then hit 'Split'. This is because you use the Filename property of the dialogbox, instead of the value of txtFileName.Text.

2) Same for the destination path.

3) Probably due to the NTFS filesystem, it is not possible to create the split dir with the same name as the original file (when in the same dir). When I want to split the file C:\file.dat into the output directory C:\, the program crashes because it wants to create the directory C:\file.dat\. You should probably use another way of naming the directory.

4) You are trying to update UI elements from a worker thread. This happens in fs_partialMergeDone, fs_mergeDone, fs_partialCopyDone and fs_CopyDone. Try calling Invoke() on the Form for this occasion. *Most* of the time this will not cause a crash, but if the user has a bad day, the application will appear to stall for no reason.

greets,

Sander

P.S. Do not take this as debunking, I'm just giving some constructive criticism Smile | :)
GeneralRe: Feedback/bugs Pin
MikePEQ5-Apr-06 10:44
MikePEQ5-Apr-06 10:44 
AnswerRe: Feedback/bugs Pin
eRRaTuM10-Apr-06 2:20
eRRaTuM10-Apr-06 2:20 
AnswerRe: Feedback/bugs Pin
eRRaTuM10-Apr-06 1:36
eRRaTuM10-Apr-06 1:36 
GeneralRe: Feedback/bugs Pin
Sander van Driel10-Apr-06 2:23
Sander van Driel10-Apr-06 2:23 
GeneralRe: Feedback/bugs Pin
eRRaTuM28-Jun-06 1:46
eRRaTuM28-Jun-06 1:46 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.