i am trying to use GZipStream to create a gz file using c#.
my problem is that i have a list that contains strings. and i need to create a password protected zip file, and put in it a text file containing the strings.
i don't want to create the textfile, then zip it, and then delete the textfile. i want to directly create a password protected zip file that contains the text file.
any help?
EDIT: i am done with the zipping stuff. now i need to set a pass for the created zip file. any help?
You should consider using SharpZipLib. It's an open source .net compression library. It includes examples on how to create either a .gz or a .zip file. Note that you can write directly to the .zip file. You don't need to create an intermediate file on disk first.
Edit: (in response to your edit) SharpZipLib supports zip passwords too.
Just create a StreamWriter wrapping your GZipStream, and write text to it.
GZipStream can be used to create a .gz file, but this is not the same as a .zip file.
For creating password-protected zip files, I think you need to go to a third-party library.
Here's how to do it using DotNetZip...
var sb = new System.Text.StringBuilder();
sb.Append("This is the text file...");
foreach (var item in listOfStrings)
sb.Append(item);
// sb now contains all the content that will be placed into
// the text file entry inside the zip.
using (var zip = new Ionic.Zip.ZipFile())
{
// set the password on the zip (implicitly enables encryption)
zip.Password = "Whatever.You.Like!!";
// optional: select strong encryption
zip.Encryption = Ionic.Zip.EncryptionAlgorithm.WinZipAes256;
// add an entry to the zip, specify a name, specify string content
zip.AddEntry("NameOfFile.txt", sb.ToString());
// save the file
zip.Save("MyFile.zip");
}
Related
I have a compressed file (.osz) stored on an S3 Bucket which contains a .os file which I need to read the contents of.
I need to be able to extract/decompress and read the contents of the compressed file without downloading the file directly to the PC due to security reasons.
I am able to retrieve the compressed file (.osz) using the URL address of it's S3 Bucket path. Then using ZipArchive I am able to access the files contained within the compressed file. I am then able to extract the file I require by using the 'ExtractToFile' function as seen below. However, this function extracts the file (.os) and saves it locally in the path specified.
WebClient client = new WebClient();
byte[] bytes = client.DownloadData(OSZFilepath); // Read the .osz file contents into a byte array
using (MemoryStream zipStream = new MemoryStream(bytes))
{
// Create the zip containing the file from the stream
ZipArchive zip = new ZipArchive(zipStream);
// extract the compressed file and download the .os file contained within
var fileName = Guid.NewGuid().ToString() + ".OS";
var baseDirectory = Environment.ExpandEnvironmentVariables(System.Web.Configuration.WebConfigurationManager.AppSettings["DataStorage"].ToString());
zip.Entries[0].ExtractToFile(Path.Combine(baseDirectory, "ProjectFiles", fileName));
Although this extracted file can be successfully read and imported by my program, I cannot use this method as I am not able to save the file onto the user's computer due to security restrictions and program requirements.
Therefore I need to programmatically extract/decompress the file I need in order to read the contents and programmatically import it into my program.
I have tried to use the following code to do this:
ZipArchiveEntry entry = zip.GetEntry(zip.Entries[0].Name);
Stream stream = entry.Open();
StreamReader reader = new StreamReader(stream);
string contents = reader.ReadToEnd();
However the resulting contents throws up an error when I try to import it, indicating that the contents is different to the contents of the file that gets saved using 'ExtractToFile'.
This is confirmed when I save this contents as a seperate file and compare it to the file saved using 'ExtractToFile'. The 'ExtractToFile' file is bigger than the latter.
So my question is: is there another way to successfully decompress/extract a compressed file and obtain the contents without using the 'ExtractToFile' method and having to save the extracted file somewhere?
Thanks for your help.
I've got a windows program using C# that is working with log files. Some of these different log files come in gzipped (for instance test.log.gz). I've got code using SharpZipLib to unzip those log files and it works really well.
public static void unZip(string gzipFilePath, string targetDir)
{
byte[] dataBuffer = new byte[4096];
using (System.IO.Stream fs = new FileStream(gzipFilePath, FileMode.Open, FileAccess.Read))
{
using (GZipInputStream gzipStream = new GZipInputStream(fs))
{
string fnOut = Path.Combine(targetDir, Path.GetFileNameWithoutExtension(gzipFilePath));
using (FileStream fsOut = File.Create(fnOut))
{
StreamUtils.Copy(gzipStream, fsOut, dataBuffer);
}
}
}
}
From my research, it would seem that gzip files are typically one file, so it's always for instance, test.htm.gz. So I would create a file named test.htm and put the uncompressed information into test.htm, which happens in this part of the code:
using (GZipInputStream gzipStream = new GZipInputStream(fs))
{
string fnOut = Path.Combine(targetDir, Path.GetFileNameWithoutExtension(gzipFilePath));
using (FileStream fsOut = File.Create(fnOut))
{
StreamUtils.Copy(gzipStream, fsOut, dataBuffer);
}
}
This is all well and good but the problem I'm having is I've been given a log file, for example again, test.log.gz that has directories zipped into it.
When I use the 7-Zip gui to unzip the file, the log file I need is five directories deep in folders. So after unzipping with 7-zip, it outputs:
folder1 -> folder2 -> folder3 -> folder4 -> folder5 -> test.log
Trying to use the method provided from SharpLib only gives me a small subset of the data of the file in test.log.
I haven't been able to find any code or issues dealing with gzipped files containing folders and from what I can tell, you're not supposed to do that. It should be in a .tar and then gzipped.
Any one have any idea of what I could do with this .gz file?
First Maybe try using another lib here are a few
http://dotnetzip.codeplex.com/
http://www.icsharpcode.net/OpenSource/SharpZipLib/
There is also a built in GZ lib built into .net see
Unzipping a .gz file using C#
There is still just one file in there, so there isn't any violation of the gzip format. gzip permits an entire path name to be stored with the file, so that path may simply be ghostcache/ic_split_files/CBN/00-christmas/test.log and 7-Zip is faithfully recreating that path. You should be able to see this in the gzip header, starting about ten bytes in.
The fact that you are getting back only a subset of the log may or may not be related to the pathname in the gzip file.
Please provide a hex dump of the first 64 bytes of the .gz file that worked and the the .gz file that didn't.
All right guys and gals it's time for the age old question, how do you password protect an xml file using C#?
I have acutally created the file in C# as well (not as if that is relevant) and now I need to password protect it so I can email it out to clients, any suggestions guys,
Also I tried putting the xml file into a zip file, using C# and upon doing this the file loses its extension, and it does this with every method I find, so I would really just like to password protect the original file.
I should have been more clear on this, the file loses it's extension permanetly, when the end user unzips it, it's no longer an xml file, it's just a file with a name, no association or any thing
ok changing this a bit, it's been pointed out a lot that xml doesn't get password protected because it's just text, not a problem, so lets change this up how about the ziping of it
FileStream sourceFile = File.OpenRead(#"C:\sample.xml");
FileStream destFile = File.Create(#"C:\sample.zip");
GZipStream compStream = new GZipStream(destFile, CompressionMode.Compress);
try
{
int theByte = sourceFile.ReadByte();
while (theByte != -1)
{
compStream.WriteByte((byte)theByte);
theByte = sourceFile.ReadByte();
}
}
finally
{
compStream.Dispose();
}
this code above zips the file, but when the file is unziped by the end user the file loses it's xml extension and with it it's file association
ok i have an update i figured out how to keep the file from losing it's extension, if i change the output file name to sample.xml.zip, the system handles it fine, granted the output file comes out reading just like this, sample.xml.zip, but winzip never bitches about opening it, neither does 7zip so i'm perfectly happy with this, now the password protected thing is something i haven't figured out yet.
just for reference sake, my new code.
FileStream sourceFile = File.OpenRead(#"C:\sample.xml");
FileStream destFile = File.Create(#"C:\sample.xml.zip");
GZipStream compStream = new GZipStream(destFile, CompressionMode.Compress);
try
{
int theByte = sourceFile.ReadByte();
while (theByte != -1)
{
compStream.WriteByte((byte)theByte);
theByte = sourceFile.ReadByte();
}
}
finally
{
compStream.Dispose();
}
and upon doing this the file looses
it's extension
What do you mean, the file name changes from MyXMLFile.xml to MyXMLFile.zip?
There's nothing you can do about that, absolutely nothing.
An xml file is a plain text file, you can't password protect the file without somehow encrypting it. Once you encrypt it, it's no longer an Xml file, it's an encrypted file, that when decrypted will produce an Xml file.
Encrypting your xml file into a password protected Zip file is a perfectly good solution to this problem.
Once the end user unzips the zip file, they'll see it as an Xml file, and then everything will be ok.
Hope this helps.
You can't password protect an XML file the way you can with a Word document. The reason you can place passwords on Word documents is because Word and presumably other programs which can read Word documents support password protection. Nothing prevents a program from completely ignoring the password (unless the file is somehow encrypted using the password as a key generator).
XML files are simply text files. No password protection is possible without placing them in a password protected container (such as a zip file). When you zip up the XML file, it is placed inside a zip archive with the extension of .zip to indicate that it is a zip file.
It is then up to the person receiving the zip file provide the correct password in order to decompress the zip file and retrieve the original XML file.
I don't believe .NET has any support for managing .zip files. You can use an third-party library like DotNetZip to help you with this.
Encrypting the file and then decrypting it would be one option. This article give some information on encrypting and decrypting.
I think a good option would be to zip it and password protect the zip file. Not the xml. A library like dotnetzip could work for this and is pretty straight forward.
I use to store document/file in byte[] in database, and I want user can view/run that file from my application.
You need to know the file extension for the file you're writing, so the OS can run the default program based on the extension. The code would be something like this:
byte[] bytes = GetYourBytesFromDataBase();
string extension = GetYourFileExtension(); //.doc for example
string path = Path.GetTempFileName() + extension;
try
{
using(BinaryWriter writer = new BinaryWriter(File.Open(path, FileMode.Create)))
{
writer.Write(yourBytes);
}
// open it with default application based in the
// file extension
Process p = System.Diagnostics.Process.Start(path);
p.Wait();
}
finally
{
//clean the tmp file
File.Delete(path);
}
You will need to store the file extension in the database too. If you don't have the file extension the problem becomes very difficult as you cannot rely on the operating system to work out which program to launch to handle the file.
You can use the following pattern:
Load data from database and save to file using the original file extension.
Start a new System.Diagnostics.Process that points to the saved file path.
As you have saved the file with the original file extension, the OS will look for a program that is registered for the extension to open the file.
As chibacity and Daniel suggest, storing the file extension in the db, and agreed -- storing the file extension, or at least some indicator that tells you the file type, is a good idea.
If these files are of a format of your own creation then you might also want to store information about which version of the file format the data is stored in. During development file formats are prone to changing, and if you don't remember which version you used to store the data then you have a hard job recovering the information.
The same problems are faced in object persistence generally.
I have a string with a C# program that I want to write to a file and always overwrite the existing content. If the file isn't there, the program should create a new file instead of throwing an exception.
System.IO.File.WriteAllText (#"D:\path.txt", contents);
If the file exists, this overwrites it.
If the file does not exist, this creates it.
Please make sure you have appropriate privileges to write at the location, otherwise you will get an exception.
Use the File.WriteAllText method. It creates the file if it doesn't exist and overwrites it if it exists.
Generally, FileMode.Create is what you're looking for.
Use the file mode enum to change the File.Open behavior. This works for binary content as well as text.
Since FileMode.Open and FileMode.OpenOrCreate load the existing content to the file stream, if you want to replace the file completely you need to first clear the existing content, if any, before writing to the stream. FileMode.Truncate performs this step automatically
// OriginalFile:
oooooooooooooooooooooooooooooo
// NewFile:
----------------
// Write to file stream with FileMode.Open:
----------------oooooooooooooo
var exists = File.Exists(path);
var fileMode = exists
? FileMode.Truncate // overwrites all of the content of an existing file
: FileMode.CreateNew // creates a new file
using (var destinationStream = File.Open(path, fileMode)
{
await newContentStream.CopyToAsync(destinationStream);
}
FileMode Enum
If your code doesn't require the file to be truncated first, you can use the FileMode.OpenOrCreate to open the filestream, which will create the file if it doesn't exist or open it if it does. You can use the stream to point at the front and start overwriting the existing file?
I'm assuming your using a streams here, there are other ways to write a file.