i am trying to not exceeded memory max size so i have to check every time if It greater than Max Memory Size Then i flush it into zip file Stream . The Problem Here it replace memory stream with existence one in file stream ,Or Is there Any way To Do the Same Rquired with Another Way ( But With Out Using Any DLL Lib)
MemoryStream memoryStream = new MemoryStream();
FileStream fileStream = new FileStream(sbZipFolderName.ToString(),FileMode.Create);
foreach (FileInfo flInfo in ListfileFolderPaths)
{
using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Update, true))
archive.CreateEntryFromFile(flInfo.FullName, slastFolderName + "/" + flInfo.DirectoryName.Replace(new DirectoryInfo(sFolderPath.ToString()).FullName, "") + "/" + flInfo.Name);
if (memoryStream.Length > MaxSize)
{
using (fileStream = new FileStream(sFolderPath + "/" + slastFolderName + ".zip", FileMode.Create))
{
memoryStream.Seek(0, SeekOrigin.Begin);
memoryStream.CopyTo(fileStream);
memoryStream = new MemoryStream();
}
}
}
if ((memoryStream != null) && (memoryStream.Length > 0))
memoryStream.CopyTo(fileStream);
You can use theGzip archive to compress a file.
This is the compression:
public static byte[] Compress(byte[] raw)
{
using (MemoryStream memory = new MemoryStream())
{
using (GZipStream gzip = new GZipStream(memory,
CompressionMode.Compress, true))
{
gzip.Write(raw, 0, raw.Length);
}
return memory.ToArray();
}
}
}
And this to decompression :
static byte[] Decompress(byte[] gzip)
{
// Create a GZIP stream with decompression mode.
// ... Then create a buffer and write into while reading from the GZIP stream.
using (GZipStream stream = new GZipStream(new MemoryStream(gzip), CompressionMode.Decompress))
{
const int size = 4096;
byte[] buffer = new byte[size];
using (MemoryStream memory = new MemoryStream())
{
int count = 0;
do
{
count = stream.Read(buffer, 0, size);
if (count > 0)
{
memory.Write(buffer, 0, count);
}
}
while (count > 0);
return memory.ToArray();
}
}
}
}
Tell me if it worked.
Goodluck.
Related
I make an archiver with block-by-block reading and file compression. I put the compressed block in FileStream.
I am reading the 5 mb block. The problem is that if I compress a pic of 8 mb, then when I pull it out of the resulting archive, its sum-hash does not match the original and it opens pic halfway, and the size is the same... I don’t know what to try. I ask for help.
Read chunk void:
private byte[] ReadChunk(int chunkId)
{
using (var inFile = new FileStream(sourceFile, FileMode.Open, FileAccess.Read, FileShare.Read))
{
long filePosition = chunkId * chunkDataSize;
int bytesRead;
if (inFile.Length - filePosition <= chunkDataSize)
{
bytesRead = (int)(inFile.Length - filePosition);
}
else
{
bytesRead = chunkDataSize;
}
var lastBuffer = new byte[bytesRead];
inFile.Read(lastBuffer, 0, bytesRead);
return lastBuffer;
}
}
Compress and write void:
private void CompressBlock(byte[] bytesTo)
{
using (MemoryStream ms = new MemoryStream())
{
using (GZipStream gs = new GZipStream(ms, CompressionMode.Compress))
{
gs.Write(bytesTo, 0, bytesTo.Length);
}
byte[] compressedData = ms.ToArray();
using (var outFile = new FileStream(resultFile, FileMode.Append))
{
BitConverter.GetBytes(compressedData.Length).CopyTo(compressedData, 4);
outFile.Write(compressedData, 0, compressedData.Length);
}
}
}
When I use the same GZipStream to compress file blocks in loop the result file compress successfully:
public static void Compress1(string fi)
{
using (FileStream inFile = File.Open(fi,FileMode.Open,FileAccess.Read,FileShare.Read))
{
using (FileStream outFile = File.Create(fi + ".gz"))
{
using (GZipStream Compress = new GZipStream(outFile,
CompressionMode.Compress))
{
byte[] buffer = new byte[6315120];
int numRead;
while ((numRead = inFile.Read(buffer, 0, buffer.Length)) != 0)
{
Compress.Write(buffer, 0, numRead);
}
}
}
}
}
But when I compress file blocks separately in different streams the result file corrupts:
public static void Compress2(string fi, int offset)
{
using (FileStream inFile = File.Open(fi,FileMode.Open))
{
using (FileStream outFile = File.OpenOrCreate(fi + ".gz"))
{
using (GZipStream Compress = new GZipStream(outFile,
CompressionMode.Compress))
{
// Copy the source file into the compression stream.
byte[] buffer = new byte[6315120];
int numRead=-1;
inFile.Seek(offset,SeekOrigin.Begin);
numRead = inFile.Read(buffer, 0, buffer.Length);
Compress.Write(buffer, 0, numRead);
}
}
}
}
In these examples I have a file with size = 12630240. And devide it into 2 blocks, size of each block = 6315120 (buffer size). So, the first block compress correctly in both methods, but the second block in second method compress different from the first method. What I missed?
What is happening is you are creating to different files as each GZipStream has its one headers
by dividing what you are doing is creating to different GZ files and if you write the two to the same file it is a corrupt file.
I am working in win forms. Getting errors while doing following operation.
It shows me System.OutOfMemoryException error when i try to run the operation around 2-3 times continuously. Seems .NET is not able to free the resouces used in operation. The file i am using for operation is quite big, around more than 500 MB.
My sample code is as below. Please help me how to resolve the error.
try
{
using (FileStream target = new FileStream(strCompressedFileName, FileMode.Create, FileAccess.Write))
using (GZipStream alg = new GZipStream(target, CompressionMode.Compress))
{
byte[] data = File.ReadAllBytes(strFileToBeCompressed);
alg.Write(data, 0, data.Length);
alg.Flush();
data = null;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
Replace ReadAllBytes with Stream.CopyTo
using (FileStream target = new FileStream(strCompressedFileName, FileMode.Create, FileAccess.Write))
using (GZipStream alg = new GZipStream(target, CompressionMode.Compress))
{
using (var fileToRead = File.Open(.....))
{
fileToRead.CopyTo(alg);
}
}
A very rough example could be
// destFile - FileStream for destinationFile
// srcFile - FileStream of sourceFile
using (GZipStream gz = new GZipStream(destFile, CompressionMode.Compress))
{
byte[] src = new byte[1024];
int count = sourceFile.Read(src, 0, 1024);
while (count != 0)
{
gz.Write(src, 0, count );
count = sourceFile.Read(src, 0, 1024);
}
}
// flush, close, dispose ..
So basically I changed your ReadAllBytes to read only chunks of 1024 bytes.
You can try to use this method to compress file MSDN link
public static void Compress(FileInfo fileToCompress)
{
using (FileStream originalFileStream = fileToCompress.OpenRead())
{
using (FileStream compressedFileStream = File.Create(fileToCompress.FullName + ".gz"))
{
using (GZipStream compressionStream = new GZipStream(compressedFileStream, CompressionMode.Compress))
{
originalFileStream.CopyTo(compressionStream);
}
}
}
}
usage:
string directoryPath = #"c:\users\public\reports";
DirectoryInfo directorySelected = new DirectoryInfo(directoryPath);
foreach (FileInfo fileToCompress in directorySelected.GetFiles())
{
Compress(fileToCompress);
}
I need to compress a file using GZip by batch of specified size (not in a whole). I can successfuly fill the byte[] buffer, but after copying it into the compression stream, it just leaves the output stream empty.
public void Compress(string source, string output)
{
FileInfo fi = new FileInfo(source);
byte[] buffer = new byte[BufferSize];
int total, current = 0;
using (FileStream inFile = fi.OpenRead())
{
using (FileStream outFile = File.Create(output + ".gz"))
{
while ((total = inFile.Read(buffer, 0, buffer.Length)) != 0)
{
using (MemoryStream compressedStream = new MemoryStream())
{
using (MemoryStream bufferStream = new MemoryStream())
{
CopyToStream(buffer, bufferStream);
using (GZipStream Compress = new GZipStream(compressedStream, CompressionMode.Compress, true))
{
bufferStream.Position = 0;
bufferStream.CopyTo(Compress);
current += total;
}
compressedStream.Position = 0;
compressedStream.CopyTo(outFile);
}
}
}
}
}
}
static void CopyToStream(byte[] buffer, Stream output)
{
output.Write(buffer, 0, buffer.Length);
}
You need to rewind compressedStream by setting Position=0 before compressedStream.CopyTo(outFile);.
You are trying to over complicate things... You do not require additional MemoryStreams or buffers...
Taken from the MSDN... http://msdn.microsoft.com/en-us/library/system.io.compression.gzipstream.aspx
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.Extension != ".gz")
{
// Create the compressed file.
using (FileStream outFile =
File.Create(fi.FullName + ".gz"))
{
using (GZipStream Compress =
new GZipStream(outFile,
CompressionMode.Compress))
{
// Copy the source file into
// the compression stream.
inFile.CopyTo(Compress);
Console.WriteLine("Compressed {0} from {1} to {2} bytes.",
fi.Name, fi.Length.ToString(), outFile.Length.ToString());
}
}
}
}
}
I have code that should do the compression:
FileStream fs = new FileStream("g:\\gj.txt", FileMode.Open);
FileStream fd = new FileStream("g:\\gj.zip", FileMode.Create);
GZipStream csStream = new GZipStream(fd, CompressionMode.Compress);
byte[] compressedBuffer = new byte[500];
int offset = 0;
int nRead;
nRead = fs.Read(compressedBuffer, offset, compressedBuffer.Length);
while (nRead > 0)
{
csStream.Write(compressedBuffer, offset, nRead);
offset = offset + nRead;
nRead = fs.Read(compressedBuffer, offset, compressedBuffer.Length);
}
fd.Close();
fs.Close();
and I think it does, but I want to decompress what was compressed the way above. I do somethink like that:
FileStream fd = new FileStream("g:\\gj.new", FileMode.Create);
FileStream fs = new FileStream("g:\\gj.zip", FileMode.Open);
GZipStream csStream = new GZipStream(fs, CompressionMode.Decompress);
byte[] decompressedBuffer = new byte[500];
int offset = 0;
int nRead;
nRead=csStream.Read(decompressedBuffer, offset, decompressedBuffer.Length);
while (nRead > 0)
{
fd.Write(decompressedBuffer, offset, nRead);
offset = offset + nRead;
nRead = csStream.Read(decompressedBuffer, offset, decompressedBuffer.Length);
}
fd.Close();
fs.Close();
and here it doesn't... I've got nRead = 0 befeore entering the loop... What I do wrong??
The test file I use is the simpliest TEXT file (size: 104 bytes)...
My first thought is that you haven't closed csStream. If you use using this happens automatically. Since gzip buffers data, you could be missing some.
Secondly; don't increment offset; that is the offset in the buffer (not the stream). Leave at 0:
using (Stream fs = File.OpenRead("gj.txt"))
using (Stream fd = File.Create("gj.zip"))
using (Stream csStream = new GZipStream(fd, CompressionMode.Compress))
{
byte[] buffer = new byte[1024];
int nRead;
while ((nRead = fs.Read(buffer, 0, buffer.Length))> 0)
{
csStream.Write(buffer, 0, nRead);
}
}
using (Stream fd = File.Create("gj.new.txt"))
using (Stream fs = File.OpenRead("gj.zip"))
using (Stream csStream = new GZipStream(fs, CompressionMode.Decompress))
{
byte[] buffer = new byte[1024];
int nRead;
while ((nRead = csStream.Read(buffer, 0, buffer.Length)) > 0)
{
fd.Write(buffer, 0, nRead);
}
}
The two methods I have are like James Roland mentioned.
private static byte[] Compress(HttpPostedFileBase file)
{
using var to = new MemoryStream();
using var gZipStream = new GZipStream(to, CompressionMode.Compress);
file.InputStream.CopyTo(gZipStream);
gZipStream.Flush();
return to.ToArray();
}
private static byte[] Decompress(byte[] compressed)
{
using var from = new MemoryStream(compressed);
using var to = new MemoryStream();
using var gZipStream = new GZipStream(from, CompressionMode.Decompress);
gZipStream.CopyTo(to);
return to.ToArray();
}
However, I'm using an upload with
Request.Files[0]
then compress and save in the db. Then I pull the img out, decompress and set a src with
$"data:image/gif;base64,{ToBase64String(Decompress(img))}";