I have a file in a current directory, which name is firstName. I want to create an archive with this file (name of file have to stay). The archive name have to be an archiveName. But when I use my code I get an archive with the rigth name but the name of file in it was changed. How can I fix it?
public static void Compress(string firstName, string secondName)
{
FileInfo fileToCompress = new FileInfo(firstName);
using (FileStream originalFileStream = fileToCompress.OpenRead())
{
if ((File.GetAttributes(fileToCompress.FullName) &
FileAttributes.Hidden) != FileAttributes.Hidden & fileToCompress.Extension != ".gz")
{
using (FileStream compressedFileStream = File.Create(secondName))
{
using (GZipStream compressionStream = new GZipStream(compressedFileStream,
CompressionMode.Compress))
{
originalFileStream.CopyTo(compressionStream);
}
}
FileInfo info = new FileInfo(secondName);
Console.WriteLine("Compressed {0} from {1} to {2} bytes.",
fileToCompress.Name, fileToCompress.Length.ToString(), info.Length.ToString());
}
}
}
GZipStream isn't a ZIP file; it's straight-up stream compression.
It has no notion of files or names; it just compresses bytes.
You're looking for the ZipArchive class.
Related
I have the following code:
private static byte[] ConverterStringToByte(Stream body)
{
string fileName = "data_" + DateTime.Now.ToString("yyyyMMddhhmmss") + ".zip";
// Take out the bytes from the memory stream and safely close the stream
using (var ms = new MemoryStream())
{
body.CopyTo(ms);
using (var zipArchive = new ZipArchive(ms, ZipArchiveMode.Create, false))
{
var zipEntry = zipArchive.CreateEntry(fileName, CompressionLevel.Optimal);
using (BinaryWriter writer = new BinaryWriter(zipEntry.Open()))
{
ms.Position = 0;
writer.Write(ms.ToArray());
}
}
return ms.ToArray();
}
}
I am downloading the file successfully, however I'm getting
invalid file
when trying to open
I think it should be something like this. Not sure about fileName though, because it's the name of the file being put into archive, so I don't think it should have *.zip extension. Unless you are creating a zip of zips.
static byte[] ConverterStringToByte(Stream body)
{
string fileName = #"data_" + DateTime.Now.ToString("yyyyMMddhhmmss") + ".zip";
using (var ms = new MemoryStream())
{
using (var zipArchive = new ZipArchive(ms, ZipArchiveMode.Create, false))
{
var zipEntry = zipArchive.CreateEntry(fileName, CompressionLevel.Optimal);
using (var destStream = zipEntry.Open())
{
body.CopyTo(destStream);
}
}
return ms.ToArray();
}
}
I need to write an API that retrieves a collection of file streams and then returns the files. These files can get large (~1GB). I need this to be as quick as possible, but this service can't consume too much memory.
In the past when I've had to do something like this, the files weren't large, so I just created a ZIP in memory and returned that. I'm not able to do that this time due to the memory constraint. From what I can tell, multipart responses don't exist, so I can't do that either. What options do I have? Is there some way I can stream zip back as a response?
public async Task GetFiles(string someId)
{
List<Stream> streamList = GetStreams(someId);
using (ZipArchive archive = new ZipArchive(responseStream /* ?? */, ZipArchiveMode.Create, true))
{
...
}
}
You could try using a gzipsteam, which avoids loading the files in memory.
https://msdn.microsoft.com/en-us/library/system.io.compression.gzipstream(v=vs.110).aspx
Here is the example from the page:
using System;
using System.IO;
using System.IO.Compression;
namespace zip
{
public class Program
{
private static string directoryPath = #"c:\temp";
public static void Main()
{
DirectoryInfo directorySelected = new DirectoryInfo(directoryPath);
Compress(directorySelected);
foreach (FileInfo fileToDecompress in directorySelected.GetFiles("*.gz"))
{
Decompress(fileToDecompress);
}
}
public static void Compress(DirectoryInfo directorySelected)
{
foreach (FileInfo fileToCompress in directorySelected.GetFiles())
{
using (FileStream originalFileStream = fileToCompress.OpenRead())
{
if ((File.GetAttributes(fileToCompress.FullName) &
FileAttributes.Hidden) != FileAttributes.Hidden & fileToCompress.Extension != ".gz")
{
using (FileStream compressedFileStream = File.Create(fileToCompress.FullName + ".gz"))
{
using (GZipStream compressionStream = new GZipStream(compressedFileStream,
CompressionMode.Compress))
{
originalFileStream.CopyTo(compressionStream);
}
}
FileInfo info = new FileInfo(directoryPath + "\\" + fileToCompress.Name + ".gz");
Console.WriteLine("Compressed {0} from {1} to {2} bytes.",
fileToCompress.Name, fileToCompress.Length.ToString(), info.Length.ToString());
}
}
}
}
public static void Decompress(FileInfo fileToDecompress)
{
using (FileStream originalFileStream = fileToDecompress.OpenRead())
{
string currentFileName = fileToDecompress.FullName;
string newFileName = currentFileName.Remove(currentFileName.Length - fileToDecompress.Extension.Length);
using (FileStream decompressedFileStream = File.Create(newFileName))
{
using (GZipStream decompressionStream = new GZipStream(originalFileStream, CompressionMode.Decompress))
{
decompressionStream.CopyTo(decompressedFileStream);
Console.WriteLine("Decompressed: {0}", fileToDecompress.Name);
}
}
}
}
}
}
I want to to compress and encrypt a file in one go by using this simple code:
public void compress(FileInfo fi, Byte[] pKey, Byte[] pIV)
{
// Get the stream of the source file.
using (FileStream inFile = fi.OpenRead())
{
// Create the compressed encrypted file.
using (FileStream outFile = File.Create(fi.FullName + ".pebf"))
{
using (CryptoStream encrypt = new CryptoStream(outFile, Rijndael.Create().CreateEncryptor(pKey, pIV), CryptoStreamMode.Write))
{
using (DeflateStream cmprss = new DeflateStream(encrypt, CompressionLevel.Optimal))
{
// Copy the source file into the compression stream.
inFile.CopyTo(cmprss);
Console.WriteLine("Compressed {0} from {1} to {2} bytes.", fi.Name, fi.Length.ToString(), outFile.Length.ToString());
}
}
}
}
}
The following lines will restore the encrypted and compressed file back to the original:
public void decompress(FileInfo fi, Byte[] pKey, Byte[] pIV)
{
// Get the stream of the source file.
using (FileStream inFile = fi.OpenRead())
{
// Get original file extension, for example "doc" from report.doc.gz.
String curFile = fi.FullName;
String origName = curFile.Remove(curFile.Length - fi.Extension.Length);
// Create the decompressed file.
using (FileStream outFile = File.Create(origName))
{
using (CryptoStream decrypt = new CryptoStream(inFile, Rijndael.Create().CreateDecryptor(pKey, pIV), CryptoStreamMode.Read))
{
using (DeflateStream dcmprss = new DeflateStream(decrypt, CompressionMode.Decompress))
{
// Copy the uncompressed file into the output stream.
dcmprss.CopyTo(outFile);
Console.WriteLine("Decompressed: {0}", fi.Name);
}
}
}
}
}
This works also with GZipStream.
A decompressing stream is expected to be read from, not written to. (unlike a CryptoStream, which supports all four combinations of read/write and encrypt/decrypt)
You should create the DeflateStream around a CryptoStreamMode.Read stream around the input file, then copy from that directly to the output stream.
With the SharpZip lib I can easily extract a file from a zip archive:
FastZip fz = new FastZip();
string path = "C:/bla.zip";
fz.ExtractZip(bla,"C:/Unzips/",".*");
However this puts the uncompressed folder in the output directory.
Suppose there is a foo.txt file within bla.zip which I want. Is there an easy way to just extract that and place it in the output directory (without the folder)?
The FastZip does not seem to provide a way to change folders, but the "manual" way of doing supports this.
If you take a look at their example:
public void ExtractZipFile(string archiveFilenameIn, string outFolder) {
ZipFile zf = null;
try {
FileStream fs = File.OpenRead(archiveFilenameIn);
zf = new ZipFile(fs);
foreach (ZipEntry zipEntry in zf) {
if (!zipEntry.IsFile) continue; // Ignore directories
String entryFileName = zipEntry.Name;
// to remove the folder from the entry:
// entryFileName = Path.GetFileName(entryFileName);
byte[] buffer = new byte[4096]; // 4K is optimum
Stream zipStream = zf.GetInputStream(zipEntry);
// Manipulate the output filename here as desired.
String fullZipToPath = Path.Combine(outFolder, entryFileName);
string directoryName = Path.GetDirectoryName(fullZipToPath);
if (directoryName.Length > 0)
Directory.CreateDirectory(directoryName);
using (FileStream streamWriter = File.Create(fullZipToPath)) {
StreamUtils.Copy(zipStream, streamWriter, buffer);
}
}
} finally {
if (zf != null) {
zf.IsStreamOwner = true;stream
zf.Close();
}
}
}
As they note, instead of writing:
String entryFileName = zipEntry.Name;
you can write:
String entryFileName = Path.GetFileName(entryFileName)
to remove the folders.
Assuming you know this is the only file (not folder) in the zip:
using(ZipFile zip = new ZipFile(zipStm))
{
foreach(ZipEntry ze in zip)
if(ze.IsFile)//must be our foo.txt
{
using(var fs = new FileStream(#"C:/Unzips/foo.txt", FileMode.OpenOrCreate, FileAccess.Write))
zip.GetInputStream(ze).CopyTo(fs);
break;
}
}
If you need to handle other possibilities, or e.g. getting the name of the zip-entry, the complexity rises accordingly.
I am having two problems
My problems are
My file name is 20110505.txt , and it is compressing a zip file name as -> 20110505.txt.zip
But I need after compressing this file 20110505.txt as --> 20110505.zip only.
I am using this dll
using System.IO.Compression;
Here is my code for compress,
1)is my text format
string path = DayDestination + "\\" + txtSelectedDate.Text + ".txt";
StreamWriter Strwriter = new StreamWriter(path);
DirectoryInfo di = new DirectoryInfo(path);
FileInfo fi = new FileInfo(path);
Compress(fi);
public static void Compress(FileInfo fi)
{
// Get the stream of the source file.
using (FileStream inFile = fi.OpenRead())
{
// Prevent compressing hidden and already compressed files.
if ((File.GetAttributes(fi.FullName) & FileAttributes.Hidden)
!= FileAttributes.Hidden & fi.Name != ".zip")
{
// Create the compressed file.
using (FileStream outFile = File.Create(fi.FullName + ".zip"))
//using (FileStream outFile = File.Create( fi.Name+ ".zip"))
{
using (GZipStream Compress = new GZipStream(outFile,
CompressionMode.Compress))
{
// Copy the source file into the compression stream.
byte[] buffer = new byte[4096];
int numRead;
while ((numRead = inFile.Read(buffer, 0, buffer.Length)) != 0)
{
Compress.Write(buffer, 0, numRead);
}
Console.WriteLine("Compressed {0} from {1} to {2} bytes.",
fi.Name, fi.Length.ToString(), outFile.Length.ToString());
}
}
}
}
}
If my zip file name is 20110505.zip after uncompressing i want my file name to be 20110505.txt . after uncomressing the zip file to text file i want to delete the zip file after compressing
string Path2 = (string)(Application.StartupPath + "\\TEMP\\" + "\\" + name_atoz);
DirectoryInfo di = new DirectoryInfo(Path2);
FileInfo fi = new FileInfo(Path2);
Compress(fi);
public static void Decompress(FileInfo fi)
{
// Get the stream of the source file.
using (FileStream inFile = fi.OpenRead())
{
// Get original file extension, for example "doc" from report.doc.gz.
string curFile = fi.FullName;
string origName = curFile.Remove(curFile.Length - fi.Extension.Length);
//Create the decompressed file.
using (FileStream outFile = File.Create(origName))
{
using (GZipStream Decompress = new GZipStream(inFile,
CompressionMode.Decompress))
{
//Copy the decompression stream into the output file.
byte[] buffer = new byte[4096];
int numRead;
while ((numRead = Decompress.Read(buffer, 0, buffer.Length)) != 0)
{
outFile.Write(buffer, 0, numRead);
}
Console.WriteLine("Decompressed: {0}", fi.Name);
}
}
}
}
I want this because i am creating a project which reads the text file .
Is there any suggestion for my problem.
Thanks In Advance
As Mitch pointed out in the comments above, the problem seems to be with your file name being used for the zip file. You include the FullName, but that has the .txt at the end. Trim that off and you should have what you want.
The line I'm talking about is this one:
using (FileStream outFile = File.Create(fi.FullName + ".zip"))
A simple way to fix it would be as follows:
using (FileStream outFile = File.Create(System.Text.RegularExpressions.Regex.Replace(fi.FullName, ".txt$", "") + ".zip"))
To delete your zip file after you decompress it, put the following line in your Decompress method as the very last line (outside your outer-most using statement):
File.Delete(fi);
You probably want to wrap that in a try-catch but this is the basic code to run. Here is an article on how to delete a file safely:
http://www.dotnetperls.com/file-delete