Zip files in C# in batches - c#

I am using Zip Archive method to zip files in a folder. However, there is a requirement to read max 10 files from a folder at a particular time and zip it. If there are a large number of files say 100, then 10 zip folders need to be created using C#.
How do I achieve this?
I have tried this in Windows forms -
private void btnZip_Click(object sender, EventArgs e) {
string FolderPathToZip = txtFolderPath.Text.Trim();
//To create unique file name with date and time with nanoseconds.
string ZipFileName = "D:\\backup\\bak-" + DateTime.Now.ToString("ddMMyyyy-HHmmssfffff") + ".zip";
try {
//To check whether D:\Backup folder exists or not.
//If not exists this will create a BACKUP folder.
if (Directory.Exists("D:\\backup")) {} else {
Directory.CreateDirectory("D:\\backup");
}
//TO create a zip file.
ZipFile.CreateFromDirectory(FolderPathToZip, ZipFileName);
} catch (Exception) {
//If system throw any exception message box will display "SOME ERROR"
MessageBox.Show("Some Error");
}
//Display successfully created message to the user.
MessageBox.Show("Zip Filename : " + ZipFileName + " Created Successfully");
}

Psuedo Code:
Create a DirectoryInfo object for the Path where files exists
Use DirectoryInfo.GetFiles() to get the list of all files (*current)
In a loop (i=0; 10*i<fileList.Count; i++) do the following
subset = fileList.Skip(10 * i).Take(10);
Loop over this subset and create the Zip Archive
Be Happy :)

Related

How to search for a file extension (.xls) and change it's name? C#

The product I'm using is a Beijer HMI, currently i can generate a report and save it to a known location (my desktop - C:\Users\mrdav\Desktop).
I need to be able to search on my desktop for a file extension .xls and change its name.
When the report is generated by the HMI, it uses the date and time which means when the file is generated the name will be different every time.
On the press of a button i need to search my desktop for the .xls file and change its name to a variable.
// This is my variable with my program
string NewName = Globals.Tags.Tag1.Value;
The code that is generated needs to sit within the below example.
public partial class Screen1
{
void Button1_Click(System.Object sender, System.EventArgs e)
{
// Code to be added here...
}
}
Hopefully someone can help, I’m using windows compact framework so limited on functionality.
Any questions please let me know.
Thanks in advance,
Dave
Here is an example how you can do that:
DirectoryInfo dir = new DirectoryInfo(sExportPath);
FileInfo[] Files = dir.GetFiles("*.csv");
foreach(FileInfo file in Files )
{
// rename file
System.IO.File.Move(file.FullName, GenerateNewFileName());
}
//elsewhere in the class
private string GenerateNewFileName()
{
//here is where you implement creating or getting the filename that you want your file to be renamed to. An example might look like the below
string serialNumber = GetSerialNumber(); //Get the serial number that you talked about in the question. I've made it a string, but it could be an int (it should be a string)
return Path.ChangeExtension(serialNumber,".xls"); //to use path you will need a using statement at the top of your class file 'using System.IO'
}
This seems to work...but i know its not as tidy as it could be.
Any suggestions?
Thanks to all that helped, got there in the end!
void Button_Click(System.Object sender, System.EventArgs e)
{
try
{
// Location for new file
string NewFileName = #"c:\users\mrdav\desktop\testfolder\";
// Add varibale name to new file
NewFileName += Globals.Tags.Tag1.Value;
// add .xls extention to new file
NewFileName += ".xls";
//show new file name to check all ok
MessageBox.Show (NewFileName);
//search for .xls in known directory
DirectoryInfo di = new DirectoryInfo(#"c:\users\mrdav\desktop");
FileInfo[] Files = di.GetFiles("*.xls");
// if files exist with .xls extention
foreach(FileInfo file in Files )
{
// show full file name
MessageBox.Show (file.FullName);
//rename old file to new file name and move to new folder
File.Move(file.FullName, NewFileName);
}
}
catch (Exception ex)
{
MessageBox.Show (ex.ToString());
}
}

Unzip not replacing file

I have a problem with a zip file replacing an existing file. I have looked at other examples on here and I still can't seem to figure it out...
I have a loop that writes some stats of the file extracted into a textbox. I think that its this line:
if (!System.IO.File.Exists(fileUnzipFullName))
My Code:
public void UnzipFileNew()
{
richTextBox1.AppendText("\r\n" + "EXTRACTING!");
String rootpath = Environment.CurrentDirectory;
//This stores the path where the file should be unzipped to,
//including any subfolders that the file was originally in.
string fileUnzipFullPath;
//This is the full name of the destination file including
//the path
string fileUnzipFullName;
//Opens the zip file up to be read
using (ZipArchive archive = ZipFile.OpenRead(#"update.zip"))
{
//Loops through each file in the zip file
foreach (ZipArchiveEntry file in archive.Entries)
{
//Outputs file information to the Textbox
richTextBox1.AppendText("\r\n");
richTextBox1.AppendText("File Name: "+ file.Name);
richTextBox1.AppendText("\r\n");
richTextBox1.AppendText("File Size: bytes "+ file.Length);
richTextBox1.AppendText("\r\n");
richTextBox1.AppendText("Compression Ratio: "+ ((double)file.CompressedLength / file.Length).ToString("0.0%"));
richTextBox1.AppendText("\r\n");
//Identifies the destination file name and path
fileUnzipFullName = Path.Combine(rootpath, file.FullName); //fileUnzipFullName = Path.Combine(#"Example\", file.FullName);
//Extracts
if (!System.IO.File.Exists(fileUnzipFullName))
{
fileUnzipFullPath = Path.GetDirectoryName(fileUnzipFullName);
//Creates the directory if it doesn't exist
Directory.CreateDirectory(fileUnzipFullPath);
//Extracts the file to (potentially new) path
file.ExtractToFile(fileUnzipFullName);
}
}
}
}
if (!System.IO.File.Exists(fileUnzipFullName)) will indeed prevent you even trying to extract the file if it already exists. So you will need to remove this or change it as per your use case.
Additionally, the ExtractToFile method will throw an IOException if the file already exists as you are using it. Fortunately, MSDN reveals that there is an overload with a boolean flag for overwriting:
public static void ExtractToFile(
this ZipArchiveEntry source,
string destinationFileName,
bool overwrite
)
So instead of
file.ExtractToFile(fileUnzipFullName);
use
file.ExtractToFile(fileUnzipFullName, true);
Using your code, this will indiscriminately overwrite all files with the ones extracted from the zip:
//Extracts
//if (!System.IO.File.Exists(fileUnzipFullName))
//{
fileUnzipFullPath = Path.GetDirectoryName(fileUnzipFullName);
//Creates the directory if it doesn't exist
Directory.CreateDirectory(fileUnzipFullPath);
//Extracts the file to (potentially new) path
file.ExtractToFile(fileUnzipFullName, true);
//}

IOException file already exists C#

private void btn_Backup_Click(object sender, EventArgs e)
{
List<DirectoryInfo> SourceDir = this.lbox_Sources.Items.Cast<DirectoryInfo>().ToList();
string TargetDir = this.tbox_Target.Text;
foreach (DirectoryInfo directory in SourceDir)
{
foreach (var file in directory.GetFiles())
if (this.checkbox_zipfiles.Checked == true)
{
System.IO.Compression.ZipFile.CreateFromDirectory(directory.FullName, TargetDir + #"\test.zip");
}
else
{
Microsoft.VisualBasic.FileIO.FileSystem.CopyDirectory(directory.FullName, TargetDir, true);
}
}
}
I'm creating a backup application and when I try to zip the files I need to backup it says: "The file 'C:\Users\Lada1208\Desktop\test\test.zip' already exists."
even thought the folder is empty before so it's trying to create the test.zip file two times for some reason. Any idea why?
As pointed out by s.m. in the comment above, the call to ZipFile.CreateFromDirectory() will attempt to create a zip file with the same location and file name for all the source directories.
If the intention is to create a single archive containing files from all the source directories, then the Zipfile.CreateFromDirectory() "shortcut" method cannot be used. Instead, you need to call ZipFile.Open(), get a ZipArchive object and use its CreateEntry() method to add every file individually.

Get progress for saving a zip file in C#?

I have this method below, which when the user clicks the button, the program gets a list of files from a path, and zips them to a location (as long as the paths exist)
I have tested it, and it works well for small folders. When I get over 1gb, the gui was freezing. As a result, I started a new thread to stop that from happening. I tried various ways of getting the progress to display, but I get nothing.
If I manually close the program several minutes in, I get a various size temp file depending on how long I wait, so I know that it is writing the file, I just cant figure out how to tell the progress to show the user.
Any ideas?
Here is my method:
private void btnSyncJobs_Click(object sender, EventArgs e)
{
string startPath = #"J:\TV\Game Of Thrones";
string zipPath = #"j:\result.zip";
string sendPath = #"j:\";
if (Directory.Exists(startPath) && Directory.Exists(sendPath))
{
//MessageBox.Show("Correct","These 2 paths exist.");
if (File.Exists(zipPath))
{
File.Delete(zipPath); //delete existing file in order to save the new one
}
String[] allfiles = System.IO.Directory.GetFiles(startPath, "*.*", System.IO.SearchOption.AllDirectories);
int fileCount = allfiles.Length;
int filesAdded = 0;
double percentComplete = 0.00;
string fileCountString = Convert.ToString(fileCount);
MessageBox.Show("There are " + fileCountString + " files.","Count Notice.");
//create the new zip file
//ZipFile.CreateFromDirectory(startPath, zipPath, CompressionLevel.Fastest, true);
Task.Factory.StartNew(() =>
{
using (ZipFile zip = new ZipFile())
{
if (chkPassword.Checked)
{
zip.Password = txtPassword.Text;
}
foreach (string s in allfiles)
{
zip.AddItem(s);
//filesAdded++;//increment the count of files added
//percentComplete = filesAdded / fileCount;
//string percentLabel = filesAdded + " of "+ fileCount + " completed.";
//lblSyncJobsStatus.Text = percentLabel;
}
zip.Save(zipPath);
}
});
lblSyncJobsStatus.Text = "Completed successfully.";
}
else
{
MessageBox.Show("Error: One or more network drives are not attached.","Error");
lblSyncJobsStatus.Text = "Did not complete successfully.\n Please contact tech support.";
}
}
Just a note- I was testing in my tv folder to test on larger file sizes.
The line '//lblSyncJobsStatus.Text = percentLabel;' had to be commented out, because it can't update a value started in another thread. Even before that, I noticed that it was at 100% before the file was being written.
The ZipFile class does not appear to offer any events or callback opportunities to report progress.
If you're open to using the open source 7-Zip library instead (and the SevenZipSharp .NET wrapper), it looks like it provides a callback for reporting progress.
https://sevenzipsharp.codeplex.com/SourceControl/latest#SevenZip/ArchiveUpdateCallback.cs

C# - Saving a '.txt' File to the Project Root

I have written some code which requires me to save a text file. However, I need to get it to save to my project root so anyone can access it, not just me.
Here's the method in question:
private void saveFileToolStripMenuItem_Click(object sender, EventArgs e)
{
try
{
string fileName = Microsoft.VisualBasic.Interaction.InputBox("Please enter a save file name.", "Save Game");
if (fileName.Equals(""))
{
MessageBox.Show("Please enter a valid save file name.");
}
else
{
fileName = String.Concat(fileName, ".gls");
MessageBox.Show("Saving to " + fileName);
System.IO.File.WriteAllText(saveScene.ToString(), AppDomain.CurrentDomain.BaseDirectory + #"\" + fileName);
}
}
catch (Exception f)
{
System.Diagnostics.Debug.Write(f);
}
}
Many people told me that using AppDomain.CurrentDomain.BaseDirectory would contain the dynamic location of where the app was stored. However, when I execute this, nothing happens and no file is created.
Is there another way of doing this, or am I just using it completely wrong?
File.WriteAllText requires two parameters:
The first one is the FileName and the second is the content to write
File.WriteAllText(AppDomain.CurrentDomain.BaseDirectory + #"\" + fileName,
saveScene.ToString());
Keep in mind however that writing to the current folder could be problematic if the user running your application has no write permission for the folder. (And in latest OS writing to the Program Files is very limited). If it is possible, change this location to the ones defined in Environment.SpecialFolder enum
I wish also to suggest using the System.IO.Path class when you need to build paths and not a string concatenation where you use the very 'OS specific' constant "\" to separate paths.
In your example I would write
string destPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory,fileName);
File.WriteAllText(destPath, saveScene.ToString());
no need for the extra + #"\" just do:
AppDomain.CurrentDomain.BaseDirectory + fileName
and replace the parameters
saveScene.ToString()
and
AppDomain.CurrentDomain.BaseDirectory + fileName
your code should be:
private void saveFileToolStripMenuItem_Click(object sender, EventArgs e)
{
try
{
string fileName = Microsoft.VisualBasic.Interaction.InputBox("Please enter a save file name.", "Save Game");
if (fileName.Equals(""))
{
MessageBox.Show("Please enter a valid save file name.");
}
else
{
fileName = String.Concat(fileName, ".gls");
MessageBox.Show("Saving to " + fileName);
System.IO.File.WriteAllText(AppDomain.CurrentDomain.BaseDirectory + fileName, saveScene.ToString());
}
}
catch (Exception f)
{
System.Diagnostics.Debug.Write(f);
}
}
you can read on File.WriteAllText here:
Parameters
path Type: System.String
The file to write to.
contents Type: System.String
The string to write to the file.
Instead of using AppDomain.CurrentDomain.BaseDirectory you can just do it this way:
File.WriteLine("data\\Mytxt.txt", "Success!");
When you don't add anything, the basedirectory is automatically assumed.

Categories

Resources