File Splitting application

Pho3nix

The Legend
Joined
Jul 31, 2009
Messages
32,827
Reaction score
3,033
Location
On the toilet
Hi guys, was given the task of making a file splitting application. Now below is the code I have managed to scramble to use but I need it to split the files into files of 10megs and any remainder.
Here is my code
Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Threading;

namespace Merge_Split_App
{


    public partial class Form1 : Form
    {
        public FileStream FS;
            string mergeFolder;

        public Form1()
        {
            InitializeComponent();
        }

        List<string> Packets = new List<string>();
        //Merged file is stored in drive
        string SaveFileFolder = @"c:\";

        private void btn_browse_Click(object sender, EventArgs e)
        {
                     openFileDialog1.ShowDialog();
                    txt_browse.Text = openFileDialog1.FileName;
        }

        public bool SplitFile(string SourceFile, int nNoofFiles)
            {
                bool split = false;
                try
                        {
                            FileStream fs = new FileStream(SourceFile, FileMode.Open, FileAccess.Read);
                            int SizeofEachFile = (int)Math.Ceiling((double)fs.Length / nNoofFiles);

                        for (int i = 0; i < nNoofFiles; i++)
                                {
                                    string baseFileName = Path.GetFileNameWithoutExtension(SourceFile);
                                    string Extension = Path.GetExtension(SourceFile);

                            FileStream outputFile = new FileStream(Path.GetDirectoryName(SourceFile) + "\\" + baseFileName + "." +
                                i.ToString().PadLeft(5, Convert.ToChar("0")) + Extension + ".tmp", FileMode.Create, FileAccess.Write);

                            mergeFolder = Path.GetDirectoryName(SourceFile);

                            int bytesRead = 0;
                            byte[] buffer = new byte[SizeofEachFile];

                        if ((bytesRead = fs.Read(buffer, 0, SizeofEachFile)) > 0)
                            {
                                outputFile.Write(buffer, 0, bytesRead);
                                //outp.Write(buffer, 0, BytesRead);

                                string packet = baseFileName + "." + i.ToString().PadLeft(3, Convert.ToChar("0")) + Extension.ToString();
                                Packets.Add(packet);
                            }

                                outputFile.Close();

                    }
                fs.Close();
                }
            catch (Exception Ex)
            {
                throw new ArgumentException(Ex.Message);
            }

            return split;
        } 
        private void button1_Click(object sender, EventArgs e)
        {
            SplitFile(txt_browse.Text, Convert.ToInt32(5));
            list1.Items.Add(Packets[0].ToString());
            list1.Items.Add(Packets[1].ToString());
            list1.Items.Add(Packets[2].ToString());
            list1.Items.Add(Packets[3].ToString());
            list1.Items.Add(Packets[4].ToString());

        }

                    
        }
    }
 
Yay game...
Code:
namespace MergeSplit
{
    using System;
    using System.Diagnostics;
    using System.IO;
   
    public class Program
    {
        public static void Main(string[] args)
        {
            var mySplitter = new FileSplitter();

            // Equal chunks, except maybe the last part 
            ////mySplitter.SplitFile(
            ////    new FileSplitOptions
            ////    {
            ////        SourceFile = new FileInfo(@"c:\test.file"), /* 2GB file */
            ////        DestinationDirectory = new DirectoryInfo(@"c:\splittest"),
            ////        SplitType = SplitTypes.Files,
            ////        NumberOfFiles = 9
            ////    });

            // Specific size, except maybe the last part 
            ////mySplitter.SplitFile(
            ////    new FileSplitOptions
            ////    {
            ////        SourceFile = new FileInfo(@"c:\test.file"), /* 2GB file */
            ////        DestinationDirectory = new DirectoryInfo(@"c:\splittest"),
            ////        SplitType = SplitTypes.Size,
            ////        SplitSize = 50000000, /* just under 50MB, depending how you calculate it :) */                    
            ////    });
        }
    }

    public enum SplitTypes
    {
        Files,
        Size
    }

    public class FileSplitOptions
    {
        public FileInfo SourceFile { get; set; }

        public DirectoryInfo DestinationDirectory { get; set; }

        public SplitTypes SplitType { get; set; }

        public int NumberOfFiles { get; set; }

        // In bytes
        public int SplitSize { get; set; }
    }

    public class FileSplitter
    {
        public bool SplitFile(FileSplitOptions splitOptions)
        {
            if ((splitOptions.SplitType == SplitTypes.Files) && (splitOptions.NumberOfFiles <= 0))
            {
                throw new ArgumentException();
            }

            if ((splitOptions.SplitType == SplitTypes.Size) && (splitOptions.SplitSize <= 0))
            {
                throw new ArgumentException();
            }

            if ((splitOptions.SplitType == SplitTypes.Files) && ((splitOptions.SourceFile.Length / splitOptions.NumberOfFiles) + 1 > Int32.MaxValue))
            {
                // This gets more complicated if you want to split into chuncks greater than In32.MaxValue,
                // infact I doubt it will work even close to that value
                throw new ArgumentException();
            }

            if (!splitOptions.SourceFile.Exists)
            {
                throw new ArgumentException();
            }
                        
            if (!splitOptions.DestinationDirectory.Exists)
            {
                // You may also want to check that the directory is empty.
                Directory.CreateDirectory(splitOptions.DestinationDirectory.FullName);
            }
                        
            try
            {
                using (var fs = new FileStream(splitOptions.SourceFile.FullName, FileMode.Open, FileAccess.Read))
                {                    
                    int bytesPerSplit;
                    if (splitOptions.SplitType == SplitTypes.Files)
                    {
                        bytesPerSplit = DivRoundUp(splitOptions.SourceFile.Length, splitOptions.NumberOfFiles);                        
                    }
                    else
                    {
                        bytesPerSplit = splitOptions.SplitSize;                        
                    }

                    Debug.WriteLine(string.Format("Bytes per split: {0}", bytesPerSplit));
                    
                    var buffer = new byte[bytesPerSplit];
                    var count = 0;
                    var bytesRemaining = splitOptions.SourceFile.Length;
                    while (bytesRemaining > 0)
                    {
                        int bytesRead = fs.Read(buffer, 0, bytesPerSplit);
                        Debug.WriteLine(string.Format("Current Split: {0}, Bytes read: {1}", count, bytesRead));

                        if (bytesRead > 0)
                        {
                            var splitFileName = string.Format("{0}.part{1:000}", splitOptions.SourceFile.Name, count++);                            
                            var splitFileFullName = Path.Combine(
                                splitOptions.DestinationDirectory.FullName,
                                splitFileName);

                            using (var outStream = new FileStream(splitFileFullName, FileMode.Create, FileAccess.Write))
                            {
                                Debug.WriteLine(string.Format("Writing {0}...", splitFileName));
                                outStream.Write(buffer, 0, bytesRead);                                
                            }

                            bytesRemaining -= bytesRead;
                            Debug.WriteLine(string.Format("Bytes remaining {0}", bytesRemaining));
                        }
                    }                    
                }
            }
            catch (Exception)
            {
                // Better error handling here
                return false;                
            }

            return true;
        }

        // Taken from: 
        // http://stackoverflow.com/questions/921180/how-can-i-ensure-that-a-division-of-integers-is-always-rounded-up
        // with modifications
        private static int DivRoundUp(long dividend, long divisor)
        {
            if (divisor == 0)
            {
                throw new ArgumentException();
            }

            if ((divisor == -1) && (dividend == Int64.MinValue))
            {
                throw new ArgumentException();
            }

            long longRoundedTowardsZeroQuotient = dividend / divisor;

            if (longRoundedTowardsZeroQuotient > Int32.MaxValue)
            {
                throw new ArgumentException();
            }

            int roundedTowardsZeroQuotient = (int)(dividend / divisor);
            bool dividedEvenly = (dividend % divisor) == 0;
            if (dividedEvenly) 
            {
                return roundedTowardsZeroQuotient;
            }

            // At this point we know that divisor was not zero 
            // (because we would have thrown) and we know that 
            // dividend was not zero (because there would have been no remainder)
            // Therefore both are non-zero.  Either they are of the same sign, 
            // or opposite signs. If they're of opposite sign then we rounded 
            // UP towards zero so we're done. If they're of the same sign then 
            // we rounded DOWN towards zero, so we need to add one.
            bool wasRoundedDown = ((divisor > 0) == (dividend > 0));
            if (wasRoundedDown) 
            {
                return roundedTowardsZeroQuotient + 1;
            }
            else
            {
                return roundedTowardsZeroQuotient;
            }
        }
    }
}

I didn't bother with combining them back together.
 
^ what he said :), thanks dequadin. Was stuck for a long time on that lol. My lead just wanted me to start learning about threading :) Hope I'm making sense.
 
I've done something like this in the form of an upload tool... when uploading a file to a server, you can't send the whole file, you have to buffer it.... would send the file in packets of say 20KB a piece.... was fun figuring out that you had to do that :p
 
lmao that exaxtly what I need to do. Hint's or tricks would be greatly appreciated :)

Basically the pseudocode to my upload file would be like this:
Code:
Read file into memory
While(currentlocationpointer<file.size)
buffertosend = buffer(buffersize)
send(buffertosend)

In your case you will have
Code:
read file into memory
integer: filecounter
While(currentlocationpointer<file.size)
{  
 newfile_filecounter.format = buffer(buffersize)
fetch next piece of file
}

Bit dirty but you should get the idea.
 
Will give it a try later on today, but I need it to stream into media player. This looks like it's going to be alot of fun :whistle:
 
Last edited:
Top
Sign up to the MyBroadband newsletter
X