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);
}
}
}