Using zip archives - c#

I created quite a neat application for backups. It just copies the directories you specify to wherever you want. Unfortunately I encountered a problem. The maximum length of the file path is about 250 so what happens is that the program can't copy files if the new location path is longer - and the program collapses.
I learned that using zip archives would resolve the problem. But... The program uses some filters and it's logic isn't that straightforward. I really wouldn't like to rewrite it all.
My program visits all subdirectories in a specified directory and checks if there are any new or modified files there. If it finds some it copies it to ..../Backups/......../dir_A/dir_B/file. Every file and dir is processed separately (it's checked if it was modified, if it fits the filters, etc)
What I need is something that would help me substitute Backups directory with Backups.zip Especially offering something like this:
myArchive.copyFile("dir_a/dir_b/...../file", original_file_path);
myArchive.fileModificationDate("dir_a/dir_b/...../file");
myArchive.getDirectotiesIn("dir_a/dir_b/");
Is there such a feature in .Net? Or maybe there is a free library for this?

There are mainly two free alternatives for handling zip files in c# :
DotNetZip
SharpZipLib
I prefer DotNetZip.

SharpZipLib

Related

Best way to manage resources(Not necessarily RESX files) in .Net solution

This sounded like a trivial question initially but I did not come across any solid/best practice solution on how to do this so I am asking the question here. Now, let's imagine that we have to work with couple of ".txt" files in our code which is in a class library.
Now, I think there are 3 major ways to handle this:
Just put everything in your Bin/Debug/Resources folder of the calling application and in your code use "Resources\*.txt". I think this is the simplest and most unobtrusive way to handle this. However, there are many trivial problems with it:
When you check in the source control would not check-in the files inside the Bin/Debug folder
So in this case, probably adding the folder one level above and then writting post-build scripts is the most efficient option I guess?
Add resources folder on the same level as Bin folder. That way we can successfully manage it using the source control. however now when we need to reference it through our code it becomes tricky
We can reference this files assuming that the Binary folder's structure is like Bin/Debug and reference to the Resources folder like ..\..\Resources
But this structure is not always guaranteed what if the binary folder structure is like Bin/ (without any debug folder in it) then ../../Resources is going to fail
Add all the txt files as .RESX files. But I am not sure if it is the practice around everywhere and the most popular way to store resources.
-Also, the code that we have to write to access the resources files sounds like cumbersome as oppose to just picking up the file from windows file system.
Probably I am missing something trivial but I was just curious and was thinking that it should be much more simpler than this. Any suggestions?
Create a different project in the solution called Myproject.Resources.
Next install Microsoft MAT and manage your translations with MAT: https://developer.microsoft.com/en-us/windows/develop/multilingual-app-toolkit
You manage your translations with MAT and the .resx files are kept up-to-date. ;-)

Add Multiple Folders / Directories to a ZipFile

I am writing a backup program that requires predefined multiple folder(s) & single file(s) to be added to a single zip archive. I have had no issues adding a single folder using -ZipFile.CreateFromDirectory(string, string, c..level, bool(false))
However i am having a hard time adding multiple folders as there does not seem to be a way to update an archive or target two folders using the CreateFromDirectory method.
- Would be nice if there was an UpdateFromDirectory mehod!
I have been trying to stay away from third party libraries for no reason really, however as far as i have found none deal with multiple unrecursive folders.
I have tried just about everything other than writing my own code to recurse & add individually which i don't really want to do.
The program has several inputs that defines the folders / files to be zipped and depending on whether they are not null should add them to a single zip file regardless of whether they are a folder or file.
I guess my question is whether this is possible at all using the boxed libraries without custom recursing or even with a third party library without heavy mods... Not sure if i have made my question clear, sure you will all let me know if i have not.
From what I can tell using the ZipFile class you can only create and read. if you want to update you would need to create the whole zip again. [Source: ZipFile methods]
to target more than one folder you could arrange all the files and folders into one folder then zip the entire source without including the source folder. In most cases moving this files/folders isn't possible so I'd recommend looking into Symlinks within windows. I'd redirect to you [Issue with creating symbolic link to directory
You can create a "myFolder" folder and put in it all the folders you want found in the zipped folder. Then do ZipFile.CreateFromDirectory("myFolder", "name of zip file to create", CompressionLevel.Fastest, false, Encoding.UTF8). Overriding this IncludeBaseDirectory method to false allows this to be done.

Comparing files in folder and moving them if size smaller

im new here, have been trying to compere one file to another and if previous file in folder is bigger then move the file. I was trying to find solution for vba, batch, c# but had no luck yet. there are many files in folder sorted by date and we need to compare one file to next and so on. If i could get ANY help on that i would greatly appreciate that!
For c#:
Use the static methods on the Directory class to get a list of the files in a folder.
Use the FileInfo class to get information about the files (IE: file size)
Use File.Move() to relocate the files if they match your criteria.
Have a look over the IOException and UnauthorizedAccessException documentation to see all the bad things that might happen when your program runs.

How to merge 2 zip files together into 1 zip

I am trying to make a custom launcher for Minecraft in C# but I have come across a bump.
I want to add something into it, Minecraft Forge, but the only way I could think of is to change the extension of minecraft.jar to minecraft.zip, extract the contents of the Minecraft Forge.zip and the minecraft.zip into the same folder and then zip that entire folder up into minecraft.jar.
However minecraft.jar has a file named aux.class so whenever my extract script (Made in java) tries to extract it, it simply says:
Unable to find file G:\Programming\C#\Console\Forge Installer\Forge Installer\bin\Debug\Merge\aux.class.
The only other way I can think of is to merge minecraft_forge.zip into minecraft.zip, I have spent around 2 hours looking on Google (watch as someone sees it within a couple of minutes) but it always shows me results for "How to zip multiple files", "How to make a zip file in C#" etc.
So I have come here looking for my answer, sorry if this is a lot to read but I always see comments on here saying "You didn't give enough information for us to help you with".
EDIT: The question in case it wasn't clear is: How am I able to put the contents of minecraft_forge.zip into minecraft.zip?
In your case, if you cannot unzip the files due to OS limitations, you need to "skip" unzipping temporary files to zip them. Instead, only handle input & output streams, as suggested in the answers found here: How can I add entries to an existing zip file in Java?
As you pointed out, "aux" is a protected keyword within windows and it does not matter what the file suffix may be; windows won't let you use it. Here are a couple of threads that discusses this in general.
Ref 1: Windows reserved words.
Ref 2: Windows reserved words.
If you are typing in commands to perform the copy or unzip, there is a chance you can get this to work by using a path prefix of the following \\.\ or \\?\. When I tested this, it worked with either a single or double back-slash following the period or question mark. Such that the following work:
\\.\c:\paths\etc
\\.\\c:\paths\etc
\\?\c:\path\etc
\\?\\c:\path\etc
I used the following command to test this. When trying to rename through windows explorer it gave a "The specified device name is invalid." error message. From the command line it worked just fine. I should point out, that once you create these files, you will have to manually delete them using the same technique. Windows Explorer reports that these text files which have a size of 0 bytes "is too large for the destination file system", ie... the recycle bin.
rename "\.\c:\temp\New Text Document.txt" aux.txt
del "\.\c:\temp\aux.txt"
As far as copying directly from zip or jar files, I tried this myself and it appeared to work. I used 7-zip and opened the jars directly using the "open archive..." windows explorer context menu. I then dragged-and-dropped the contents from forge.jar to the minecraft jar file. Since it is the minecraft jar file with the offending file name the chance of needing to create a temporary file on the filesystem is reduced. I did see someone mention that 7-zip may extract to a temporary file when copying between jars and zips.
7-zip reference on copying between archives
I should point out that my copy of minecraft jar (minecraft_server.1.8.7.jar) did not contain a file named aux.class. I also did not try to use the jar after the copy/merge. Nor did I spend too much time trying to figure out how well it merged the two contents since it appears like there may be a conflict with com\google\common\base\ since there are similar class name but with different $ variable suffixes on them.
I hope these two possible suggestions could give you some room to work with to find a solution for your needs... if you're still looking.

ignore files in flight

When I run the code below, it fills my array with a list of files in the specified directory.
This is good.
However, it also grabs files that are 'in flight' - meaning files that are currently being copied to that directory.
This is bad.
How do I go about ignoring those 'in-flight' files? Is there a way to check each file to make sure it's 'fully there' before I process it?
string[] files = Directory.GetFiles(ConfigurationSettings.AppSettings.Get("sourcePath"));
if (files.Length > 0)
{
foreach (string filename in files)
{
string filenameonly = Path.GetFileName(filename);
AMPFileEntity afe = new AMPFileEntity(filenameonly);
afe.processFile();
}
}
Unfortunately there is no way to achieve what you are looking for. Robert's suggestion of opening the file for writing solves a subset of the problem but does not solve the bigger issue which is
The file system is best viewed as a multi-threaded object over which you have no synchronization capabilities
No matter what synchronization construct you try to use to put the file system into a "known state", there is a way for the user to beat it.
The best way to approach this problem is to process the files as normal and catch the exceptions that result from using files that are "in flight". This is the only sane way to deal with the file system.
Yes, you can try to open the file for writing. If you are able to open for writing without an exception then it's likely not "in-flight" anymore. Unfortunately, I have encountered this problem several times before and have not come across a better solution.
Get a list of files in the directory.
Get a list of open handles (see below).
Remove the latter from the former.
You can get a list of open handles by p/invoking NtQuerySystemInformation. There's a project on CodeProject that shows how to do this. Alternatively, you can call Handle.exe, from Sysinternals, and parse its output.
Try to rename/move the file. If you can rename it, it's no longer in use.
Carra's answer gave me an idea.
If you have access to the program that copies the files to this directory, modify it so that it:
Writes files to a temporary directory on the same disk.
Move the files to the appropriate folder after they're finished writing to disk.
On the same filesystem, a move operation just updates the directory entries rather than changing the file's physical location on disk. Which means that it's extremely fast.

Categories