Wątek przeniesiony 2014-02-04 16:22 z C# i .NET przez somekind.

Program nie działa prawidłowo przy tworzeniu archiwów większych niż 100MB

0

Witam, mam problem z programem http://www.codeproject.com/Articles/25453/Automating-Multipart-Zip-File-Creation program kompiluje się bez błędów ale nie dzała jak trzeba. Jak chcę stworzyć archiwa większę niż 100MB to program zawsze tworzy archiwa o rozmiarze 94.2-94.9MB. Jak chcę mniejszę niż 100MB to program ignoruje limit i tworzy tylko jedn plik zip.

Kod programu, w załączniku całość.

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.Collections;
/* Logging */
using NLog;
/* SharpZipLib */
using ICSharpCode.SharpZipLib.Zip;

/*
1 Byte = 8 Bit
1 Kilobyte = 1024 Bytes
1 Megabyte = 1048576 Bytes
1 Gigabyte = 1073741824 Bytes
*/
namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        private static Logger logger = LogManager.GetCurrentClassLogger();

        private long totalFileSize = 0L; /* In bytes */
        private long totalNumberFilesSelected = 0L; /* Total number of files selected */
        private int partitionSize; /* In MegaBytes */
        private int partitionSizeInBytes = 100000000; /* defaulted to 100 MB */
        private int compressionLevel = 9; /* defaults to 9 (best) */
        private String saveFileBase = ""; /* Zip file to save as */
        private ArrayList fileInfoList;
        private ArrayList fileIndices = new ArrayList();

        /// <summary>
        /// Constructor
        /// </summary>
        public Form1()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Computes the total number of archives
        /// </summary>
        /// <returns></returns>
        private int computeNumberOfArchives()
        {
            int totalNumberOfArchives = 0;
            logger.Debug("partition size = " + this.partitionSize);
            logger.Debug("partition size in bytes = " + this.partitionSizeInBytes);
            logger.Debug("total file size = " + this.totalFileSize);
            if (this.partitionSize <= 0 || this.partitionSizeInBytes <= 0 || this.totalFileSize <= 0)
                MessageBox.Show("No input to the system!", "User has to enter partition size or select the files to be archived!!", MessageBoxButtons.OK, MessageBoxIcon.Error);
            else
            {
                /* Convert from MB to bytes */
                //this.partitionSizeInBytes = this.partitionSize * 1048576;

                /* 1 MB = 1048576 Bytes */
                logger.Debug("totalFileSize = " + totalFileSize);
                double totalFileSizeInMB = (double)(totalFileSize) / (double)(1048576.0);
                logger.Debug("totalFileSizeInMB = " + totalFileSizeInMB + " partition size = " + partitionSize);

                if (totalFileSizeInMB > 0)
                {
                    if (totalFileSizeInMB < partitionSize)
                        totalNumberOfArchives = 1;
                    else totalNumberOfArchives = (int)Math.Ceiling((double)(totalFileSizeInMB) / (double)(partitionSize));
                }
                else
                {
                    MessageBox.Show("You must select the files to be archived", "User has to select the files to be archived!!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                }
                logger.Debug("totalNumberOfArchives = " + totalNumberOfArchives);
            }
            return (totalNumberOfArchives);
        }

        /// <summary>
        /// Does the actual zip compression of the files
        /// </summary>
        /// <param name="callback"></param>
        /// <param name="s"></param>
        /// <param name="start"></param>
        /// <param name="finish"></param>
        /// <param name="buffer"></param>
        private void doZip(IProgressCallback callback, ZipOutputStream s, int start, int finish, byte[] buffer)
        {
            for (int j = start; j < finish; j++)
            {
                FileInfoItem fii = (FileInfoItem)fileInfoList[j];

                callback.SetText(String.Format("Processing file: {0}", fii.FileName));
                callback.StepTo(j);

                ZipEntry entry = new ZipEntry(fii.FileName);
                entry.DateTime = DateTime.Now;
                s.PutNextEntry(entry);
                FileStream fs = File.OpenRead(fii.FileName);

                if (callback.IsAborting)
                {
                    return;
                }

                // Using a fixed size buffer here makes no noticeable difference for output
                // but keeps a lid on memory usage.
                int sourceBytes;
                do
                {
                    sourceBytes = fs.Read(buffer, 0, buffer.Length);
                    s.Write(buffer, 0, sourceBytes);
                } while (sourceBytes > 0);
                System.Threading.Thread.Sleep(100);
                fs.Close();
                if (callback.IsAborting)
                {
                    return;
                }
            }
        }

        /// <summary>
        /// Callback 
        /// </summary>
        /// <param name="status"></param>
        private void createZipArchive(object status)
        {
            IProgressCallback callback = status as IProgressCallback;

            /* if empty generate random string */
            if (this.saveFileBase == "") this.saveFileBase = Guid.NewGuid().ToString();

            try
            {
                int start = 0;
                int totalNumberOfArchives = this.computeNumberOfArchives();
               
                if (totalNumberOfArchives == 1)
                {
                    ZipOutputStream s = new ZipOutputStream(File.Create(saveFileBase + ".zip"));
                    s.SetLevel(this.compressionLevel);
                    
                    callback.Begin(0, fileInfoList.Count);

                    byte[] buffer = new byte[4096];
                    this.doZip(callback, s, 0, fileInfoList.Count, buffer);
                    // Finish is important to ensure trailing information for a Zip file is appended.  Without this
                    // the created file would be invalid.
                    s.Finish();

                    // Close is important to wrap things up and unlock the file.
                    s.Close();
                }
                else
                {
                    callback.Begin(0, (int)this.totalNumberFilesSelected);
                    for (int i = 0; i < totalNumberOfArchives; i++)
                    {
                        int n;
                        String tmpFile = saveFileBase + "_" + i + ".zip";
                        logger.Debug("tmpFile = " + tmpFile);
                        //File f = File.Create(saveFileBase + "_" + i + ".zip");
                        n = i + 1;
                        ZipOutputStream s = new ZipOutputStream(File.Create(saveFileBase + "-" + n + ".zip"));
                        s.SetLevel(this.compressionLevel);
                        byte[] buffer = new byte[4096];
                        logger.Debug("fileIndices count = " + fileIndices.Count);
                        if (fileIndices.Count > 0)
                        {
                            int finish = (int)fileIndices[i];
                            //callback.Begin(0, (int)this.totalNumberFilesSelected);

                            doZip(callback, s, start, finish, buffer);
                            logger.Debug("start = " + start + " finish = " + finish + " i = " + i);
                            
                            start = finish;
                            // Finish/Close arent needed strictly as the using statement does this automatically

                            // Finish is important to ensure trailing information for a Zip file is appended.  Without this
                            // the created file would be invalid.
                            s.Finish();

                            // Close is important to wrap things up and unlock the file.
                            s.Close();
                        }
                        else
                        {

                        }
                    }
                }

            }
            catch (System.Threading.ThreadAbortException e)
            {
                logger.Error("Thread abort exception: " + e.Message);
            }
            catch (System.Threading.ThreadInterruptedException e)
            {
                logger.Error("Thread interrupted exception: " + e.Message);
            }
            catch (Exception ex)
            {
                logger.Error("Exception during processing: " + ex.Message);
                // No need to rethrow the exception as for our purposes its handled.
            }
            finally
            {
                if (callback != null)
                {
                    logger.Debug("Ending callback ....");
                    callback.End();
                }
            }
        }

        ///       
        /// <summary>
        /// About Dialog Box
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// 
        private void aboutZipMakerToolStripMenuItem_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Zip Maker (c) Adelene Ng 2008", "About Zip Maker", MessageBoxButtons.OK);
        }

        /// <summary>
        /// Zip button clicked; perform the Zip operation
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            if (this.radioButton1.Checked)
            {
                this.partitionSize = 100;
                this.partitionSizeInBytes = 104857600;
            }
            if (this.radioButton2.Checked)
            {
                this.partitionSize = 500;
                this.partitionSizeInBytes = 500000000;
            }
            if (this.radioButton3.Checked)
            {
                this.partitionSize = 1000;
                this.partitionSizeInBytes = 1000000000;
            }
            if (this.radioButton4.Checked)
            {
                if (this.textBox2.Text == "")
                    MessageBox.Show("You must enter a value", "User specified Partition Size cannot be empty!!", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                else
                {
                    this.partitionSize = Int32.Parse(this.textBox2.Text);
                    double tmp = Double.Parse(this.textBox2.Text) * 1000000;
                    this.partitionSizeInBytes = (int)Math.Floor((double)tmp);
                }
            }
            /* if (this.saveFileBase != null)
                this.createZipArchive();
             */
            
            ProgressWindow progress = new ProgressWindow();
            progress.Text = "Work";
            System.Threading.ThreadPool.QueueUserWorkItem(new System.Threading.WaitCallback(createZipArchive), progress);
            progress.ShowDialog();            
        }

        /// <summary>
        /// Browse Button Clicked; brings up OpenFileDialog
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button3_Click(object sender, EventArgs e)
        {
            // create an open file dialog
            OpenFileDialog dlgOpen = new OpenFileDialog();

            // set properties for the dialog
            dlgOpen.Title = "Select one or more files";
            dlgOpen.ShowReadOnly = true;
            dlgOpen.Multiselect = true;

            // display the dialog and return results
            if (dlgOpen.ShowDialog() == DialogResult.OK)
            {
                fileInfoList = new ArrayList();
                //MessageBox.Show(Directory.GetCurrentDirectory());
                //String tmp = "";
                long runningTotal = 0;
                int i = 0, finish = 0;
                totalNumberFilesSelected = dlgOpen.FileNames.LongLength;
                logger.Debug("Total number of files selected: " + totalNumberFilesSelected);
                foreach (string s in dlgOpen.FileNames)
                {
                    FileInfoItem fii = new FileInfoItem();
                    FileInfo fi = new FileInfo(s);
                    fii.FileName = s;
                    fii.FileSize = fi.Length; /* length in bytes */
                    fii.Directory = fi.DirectoryName;
                    fileInfoList.Add(fii);
                    logger.Debug("Filename = " + s);
                    logger.Debug("Directory = " + fi.DirectoryName);
                    logger.Debug("File size = " + fi.Length);
                    totalFileSize += fi.Length;

                    i++;
                    logger.Debug("partitionSizeInBytes = " + partitionSizeInBytes);
                    if (runningTotal + fi.Length + 1000000 < partitionSizeInBytes)
                    {
                        runningTotal += fi.Length;
                        finish = i;
                        logger.Debug("1: Running total = " + runningTotal + " finish = " + finish);
                    }
                    else
                    {
                        logger.Debug("2: Running total = " + runningTotal + " finish = " + finish);
                        finish = i - 1;
                        logger.Debug("Finish = " + finish);
                        fileIndices.Add(finish);
                        runningTotal = 0;
                    }
                    this.listBox1.Items.Add(s);
                    //tmp += s;
                }
                // remaining files
                if (runningTotal > 0)
                {
                    fileIndices.Add(finish);
                }
                logger.Debug("3: Running total = " + runningTotal + " finish = " + finish + " i = " + i);

                //MessageBox.Show(tmp);
                //logger.Debug("No of archives = " + computeNumberOfArchives());
            }
        }

        /// <summary>
        /// Save As Button Clicked, bring up SaveAs Dialog
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button4_Click(object sender, EventArgs e)
        {
           SaveFileDialog saveDlg = new SaveFileDialog();
           DialogResult dialogResult = saveDlg.ShowDialog();
           if (dialogResult == DialogResult.OK)
           {
               logger.Debug("Save button pressed!!");
               if (saveDlg.FileName != null)
               {
                   this.saveFileBase = saveDlg.FileName;
                   logger.Debug("Specified file not empty and is: " + this.saveFileBase);
               }
               else
               {
                   /* Generates a random string */
                   /* http://www.kivela.be/index.php/2007/06/19/how-to-generate-a-random-string-in-c-20/ */
                   this.saveFileBase = Guid.NewGuid().ToString();
                   logger.Debug("Specified file empty and is: " + this.saveFileBase);
               }
           }
           else if (dialogResult == DialogResult.Cancel)
           {
               logger.Debug("Cancel button pressed!");
               this.saveFileBase = Guid.NewGuid().ToString();
           }
           logger.Debug("saveFileBase = " + this.saveFileBase);
        }

        /// <summary>
        /// Quit button clicked
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button2_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("Really Quit?", "Exit", MessageBoxButtons.OKCancel) == DialogResult.OK)
            {
                Application.Exit();
            }
        }

        /// <summary>
        /// To select compression level; ranges from 0 - 9; the best being 9
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.compressionLevel = Int32.Parse(this.comboBox1.Text);
            logger.Debug("Compression Level = " + this.compressionLevel);
        }

        /// <summary>
        /// User keys in the file splitting size
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void textBox2_TextChanged(object sender, EventArgs e)
        {
            this.partitionSize = Int32.Parse(this.textBox2.Text);
            logger.Debug("Partition Size = " + this.partitionSize);
        }
    }
}
1

100000000 bitów to nie jest 100MB

0

To wiem, ale program ignoruje jakiekolwiek limity i zawsze tworzy archiwa o rozmiarze 94.2-94.9MB.

1 użytkowników online, w tym zalogowanych: 0, gości: 1