mirror of
https://github.com/XFox111/GZipCompression.git
synced 2026-04-22 06:16:18 +03:00
Finished and polished project (added files)
This commit is contained in:
@@ -0,0 +1,74 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
|
||||
namespace GZipTest
|
||||
{
|
||||
class CompressionModule : ProcessingModule
|
||||
{
|
||||
/// <summary>
|
||||
/// Reading uncompressed source file
|
||||
/// </summary>
|
||||
internal override void Read()
|
||||
{
|
||||
try
|
||||
{
|
||||
using (FileStream input = File.OpenRead(source)) //Opening reading stream
|
||||
{
|
||||
segmentCount = (long)Math.Ceiling((double)input.Length / 1048576); //segmentCount field will be used to display progress bar
|
||||
length = input.Length; //This variable will be used in post analysis
|
||||
|
||||
for (int i = 0; input.Position < input.Length; i++)
|
||||
{
|
||||
if (readBuffer.Count >= 5 * Environment.ProcessorCount) //Helping compression thread if there's too many unprocessed blocks
|
||||
{
|
||||
ProcessOne();
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
|
||||
int blockSize = (int)Math.Min(1048576, input.Length - input.Position); //Determining new block size. Either 1MB or count of the last bytes
|
||||
|
||||
byte[] block = new byte[blockSize]; //Instantiating empty block
|
||||
input.Read(block, 0, blockSize); //Reading next block
|
||||
|
||||
readBuffer.Enqueue(new KeyValuePair<int, byte[]>(i, block)); //Adding read block to compression queue. Each block must contain its position number since compression is multi thread
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
ReportError(this, $"Error occured in Reading thread. Served blocks: {served}", e);
|
||||
}
|
||||
}
|
||||
|
||||
internal override void ProcessOne()
|
||||
{
|
||||
if (!readBuffer.TryDequeue(out KeyValuePair<int, byte[]> block)) //Extracting read block
|
||||
return;
|
||||
|
||||
processed.WaitOne(); //Waiting for empty place for compressed block
|
||||
|
||||
using (MemoryStream stream = new MemoryStream()) //Instatiating memory stream which will contain compressed block
|
||||
using (GZipStream compressor = new GZipStream(stream, CompressionMode.Compress)) //Instantiating compression stream
|
||||
{
|
||||
compressor.Write(block.Value, 0, block.Value.Length); //Compressing block
|
||||
compressor.Close();
|
||||
|
||||
byte[] compressedBlock = stream.ToArray(); //Getting compressed block
|
||||
byte[] fileMeta = block.Key == 0 ? BitConverter.GetBytes(segmentCount) : new byte[0]; //If it's the first block in a file we write info about total block count (that will be used to count progress)
|
||||
byte[] zippedMeta = BitConverter.GetBytes(compressedBlock.Length); //Creating compressed block length info
|
||||
|
||||
byte[] newBlock = new byte[fileMeta.Length + 4 + compressedBlock.Length]; //Merging arrays
|
||||
fileMeta.CopyTo(newBlock, 0);
|
||||
zippedMeta.CopyTo(newBlock, fileMeta.Length);
|
||||
compressedBlock.CopyTo(newBlock, fileMeta.Length + 4);
|
||||
|
||||
processedBuffer.TryAdd( //Processing block and adding it to write queue keeping its position number
|
||||
block.Key,
|
||||
newBlock);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user