I want to replace some files by adding them to a zip file. I mean after the zip is created, I should no longer see those files in the folder.
I'm able to zip files using dotNetZip's Library. But the orignal files are still there. Since I've already zipped them I no longer want them in that folder.
I tried deleting them(using file.delete) but I got an error that the files were being used by a program.
Here's what I wrote: //edited
var files = directory.GetFiles("*.csv", SearchOption.AllDirectories);
try
{
using (Ionic.Zip.ZipFile zip = new Ionic.Zip.ZipFile())
{
foreach (var file in files)
{
sendEmail.SendMailMessage(file.FullName);
// zip.AddFile(file.FullName);
}
// zip.Save(Path.Combine(filePath,dirDate, "logs.zip"));
}
foreach (var file in files)
{
File.Delete(file.FullName);
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
This might be silly but I'm really stuck. Please guide.
The error I get is :
System.IO.IOException: The process cannot access the file 'D:\***.csv' because it is being used by another process.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.File.InternalDelete(String path, Boolean checkHost)
at System.IO.File.Delete(String path)
at Program.Main(String[] args) in d:\Documents\\**
In your code you're not using any File.Delete() method - please always provide the code that creates the error.
However, most likely you're simply trying to delete the files within your using-block. When you add the files to your zip file they will be accessed and locked, so you can't delete him. Once the ZipFile object is released the files will be released too.
var files = directory.GetFiles("*.csv", SearchOption.AllDirectories);
using (Ionic.Zip.ZipFile zip = new Ionic.Zip.ZipFile())
{
foreach (var file in files)
{
zip.AddFile(file.FullName);
}
zip.Save(Path.Combine(filePath, dirDate, "logs.zip"));
}
// Outside of using block
foreach (var file in files)
{
File.Delete(file.FullName);
}
Related
I have the following lines of code that work for creating a zip using ZipFile.CreateFromDirectory(selectedFile, zipPath)
if (selectedFolder == string.Empty)
{
Console.WriteLine("Invalid folder, try again");
}
else
{
Console.WriteLine("\nSelect zipfile name: ");
var zipName = Console.ReadLine();
// Also available: extractToDirectory
var zipPath = #"C:\Users\User\Documents\Dev\" + zipName + ".zip";
ZipFile.CreateFromDirectory(selectedFolder, zipPath);
However, the following code which should for all intents and purposes do the same thing except for multiple files being archived into a single zip folder refuses to work:
public static void CreateZipFile(string folderToCreateZip, IEnumerable<string> files)
{
var zipPath = folderToCreateZip + "\\test6.zip";
// Create a new ZIP in this location
using (var zip = ZipFile.Open(zipPath, ZipArchiveMode.Create))
{
foreach (var file in files)
{
// Add entry for files
zip.CreateEntryFromFile(file, zipPath, CompressionLevel.Optimal);
}
}
// Dispose of zip object after files have been zipped
//zip.Dispose();
}
var zip == ZipArchive zip
I've tried disabling read-only mode on the folders where the zip should get created, but I don't think this matters since the prior function with CreateFromDirectory() works fine. I've also tried creating a ZIP on desktop, but I get the same error.
This is the exception I'm getting:
As a note, I noticed that it does initially create the zip despite this error, just that it cannot add anything to it unlike CreateFromDirectory() can due to the folder either being in use, no permissions to that area or the folder already existing. Is there a way I can get CreateEntryFromFile() working or an alternative that would work for multiple files?
I had the same problem. The solution was post the full path name at the destinationArchiveFileName parameter (and also a write alowed path). For example c:\my apps folder\my app\my temp\zipfile.zip
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.
ZipFile.CreateFromDirectory(source_dir, target_dir) will throw exception and stop the zipping when any file in the directory is being accessed. how can I make it do the zipping for the rest of the files ??
Killing the processes are not allowed, they are vital.
Thanks
Resolved:
Here is how I get this around.
Split the task into 2 phase.
(Note only use the Zipfile and ZipArchive from System.IO.Compression)
Step 1. create a dummy zip file; (this must not hit access issue)
Step 2. Scan and Add files to the dummy zip file
Additional: Keep the original directory hierarchy by adding folder into the dummy zip file
Here is the Step 2, only copy the file when hit exception.
private void UpdateBallFile(String source_dir, String target_zipfile)
{
using (ZipArchive archive = ZipFile.Open(target_zipfile + suffix, ZipArchiveMode.Update))
{
foreach (String subdir in Directory.GetDirectories(source_dir, "*.*", SearchOption.AllDirectories))
{
String relatedPath = subdir.Replace(source_dir, String.Empty);
String entry = relatedPath.Replace("\\", "/").Substring(1);
foreach (String file in Directory.GetFiles(subdir))
{
if (File.Exists(file))
{
FileInfo info = new FileInfo(file);
try
{
archive.CreateEntryFromFile(file, entry+"/"+info.Name);
}
catch
{
try
{
String copied_item = Path.Combine(#"c:\", info.Name);
File.Copy(file, copied_item, true);
archive.CreateEntryFromFile(copied_item, entry + "/" + info.Name);
File.Delete(copied_item);
}
catch (Exception ex)
{
UpdateLog(String.Format("Fails to zip: {0}, {1} ", file, ex.Message));
}
}
}
}
}
}
}
I am new to C# and this community, Please let me know if you have better idea.
Thanks
You can add each file to your zip by checking the accessibility, so you can code like this:
ZipFile myzip = new ZipFile("myzipFile");
foreach (string file in Directory.GetFiles(#"D:\sample"))
{
try
{
var stream = File.Open(file, FileMode.Open, FileAccess.ReadWrite, FileShare.None);
stream.Dispose();
myzip.AddFile(file);// add file to zip only if it is accessible. else it will throw some exception
//hence it wont added to the zipped folder.
}
catch
{ }
}
myzip.Save(#"D:\sample\myfile.zip");// this zip file contains only file that have access
Hope that this is actually you ware looking;
An easy solution would be preparing a kind of copy/temp folder in the User/AppData/Local directory, where all readable files are in. You will than zip this folder, because you can be sure that the data are not used. After the zip-process you have to delete the folder. Not the optimum but it should work. Another solution would be using some other zip component...
I have a number of zip files that contain .txt files nested in sub directories within the zip file. I am trying to extract the .txt files and output them to another directory, however I am getting an error 'Could not find a part of the path...' This error occurs at the 'entry.FullName' point
I believe I need to remove the file path at some stage of the unzip process since I can get the code to run if I use zip files with .txt files in them without any sub-directories. Any pointers would be much appreciated.
Here is my code:
class Program
{
static void Main(string[] args)
{
DateTime dt = DateTime.Now;
foreach (var zp in Directory.GetFiles(#"D:\\My Documents\\DMU\\Frontrunner2015\\ZipIn\\", "*.zip"))
{
string zipPath = zp;
string extractPath = #"D:\\My Documents\\DMU\\Frontrunner2015\\ZipOut\\";
using (ZipArchive archive = ZipFile.OpenRead(zipPath))
{
foreach (ZipArchiveEntry entry in archive.Entries)
{
if (entry.FullName.EndsWith(".txt", StringComparison.OrdinalIgnoreCase))
{
entry.ExtractToFile(Path.Combine(extractPath, entry.FullName));
}
foreach (var file in Directory.GetFiles(extractPath))
{.....
Would have helped if you left the path in the error message there so people could see what path was not found. I would guess that when you combine extractPath and FullName you end up with a folder name that does not exist - as you mentioned the files in the zip file have subdirectories.
I think you really meant to use Name property in your Path.Combine call.
Assume I have a zip file which contains 10 text files. It's easy to iterate over these text files using:
using (ZipArchive archive = ZipFile.OpenRead(zipIn))
{
foreach (ZipArchiveEntry entry in archive.Entries)
{
Console.writeLine(entry)
}
}
However, suppose the text files are within a subdirectory:
zip/subdirectory/file1.txt
In this case the above code only outputs the subdirectory folder ('subdirectory'), as opposed to all the text files within that folder.
Is there a simple way of looping over the files in the subdirectory also?
I have reproduced your program. When I iterate over a zip archive the way you do it, I get a list of all files in the full directory structure within the archive. So you do not need recursion, just iterate like you are doing now.
I understand your confusion since the API does not make a distinction between files and folders. Here is an extension method to help:
static class ZipArchiveEntryExtensions
{
public static bool IsFolder(this ZipArchiveEntry entry)
{
return entry.FullName.EndsWith("/");
}
}
Then you can do:
using (var archive = ZipFile.OpenRead("bla.zip"))
{
foreach (var s in archive.Entries)
{
if (s.IsFolder())
{
// do something special
}
}
}
I can't reproduce your problem. It works fine in my test case:
using (var archive = ZipFile.OpenRead(zipIn))
{
foreach (var zipArchiveEntry in archive.Entries)
{
Console.WriteLine(zipArchiveEntry);
}
}
Console.ReadLine();
Result: