Exemple #1
0
        /// <param name="sparseIndex">one-based index</param>
        /// <returns>True if the write was complete (i.e. this was the last sparse)</returns>
        public static bool WriteCompressedSparse(Stream input, Stream output, long maxSparseSize)
        {
            // We will write the header later
            output.Seek(SparseHeader.Length, SeekOrigin.Begin);
            long currentSparseSize = SparseHeader.Length;

            uint chunkCount = 0;

            if (input.Position != 0)
            {
                WriteDontCareChunk(output, (uint)(input.Position / BlockSize));
                chunkCount++;
            }

            MemoryStream rawChunk = new MemoryStream();

            byte[] fill      = null;
            int    fillCount = 0;

            // We keep reading as long as we have a room for an additional chunk
            // (the largest chunk is a raw chunk)
            while (currentSparseSize + ChunkHeader.Length + BlockSize <= maxSparseSize &&
                   input.Position < input.Length)
            {
                byte[] block = new byte[BlockSize];
                input.Read(block, 0, BlockSize);
                byte[] currentFill = SparseCompressionHelper.TryToCompressBlock(block);

                if (fill != null)
                {
                    if (currentFill != null)
                    {
                        if (ByteUtils.AreByteArraysEqual(fill, currentFill))
                        {
                            fillCount++;
                        }
                        else
                        {
                            WriteFillChunk(output, fill, (uint)fillCount);
                            chunkCount++;

                            fillCount          = 1;
                            fill               = currentFill;
                            currentSparseSize += ChunkHeader.Length + 4;
                        }
                    }
                    else
                    {
                        WriteFillChunk(output, fill, (uint)fillCount);
                        chunkCount++;

                        ByteWriter.WriteBytes(rawChunk, block);
                        fill               = null;
                        fillCount          = 0;
                        currentSparseSize += ChunkHeader.Length + BlockSize;
                    }
                }
                else // fill == null
                {
                    if (currentFill != null)
                    {
                        WriteRawChunk(output, rawChunk);
                        chunkCount++;

                        rawChunk           = new MemoryStream();
                        fillCount          = 1;
                        fill               = currentFill;
                        currentSparseSize += ChunkHeader.Length + 4;
                    }
                    else
                    {
                        ByteWriter.WriteBytes(rawChunk, block);
                        currentSparseSize += BlockSize;
                    }
                }
            }

            if (rawChunk.Length > 0)
            {
                WriteRawChunk(output, rawChunk);
                chunkCount++;
            }
            else
            {
                WriteFillChunk(output, fill, (uint)fillCount);
                chunkCount++;
            }

            bool complete = (input.Position == input.Length);

            if (!complete)
            {
                WriteDontCareChunk(output, (uint)((input.Length - input.Position) / BlockSize));
                chunkCount++;
            }

            output.Seek(0, SeekOrigin.Begin);
            SparseHeader sparseHeader = new SparseHeader();

            sparseHeader.BlockSize   = BlockSize;
            sparseHeader.TotalBlocks = (uint)(input.Length / BlockSize);
            sparseHeader.TotalChunks = chunkCount;
            sparseHeader.WriteBytes(output);
            output.Close();

            return(complete);
        }
Exemple #2
0
        private static void Compress(string inputPath, string outputPath, long maxSparseSize)
        {
            FileStream input;

            try
            {
                input = File.Open(inputPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
            }
            catch (IOException)
            {
                Console.WriteLine("Cannot open " + inputPath);
                return;
            }
            catch (UnauthorizedAccessException)
            {
                Console.WriteLine("Cannot open {0} - Access Denied", inputPath);
                return;
            }

            if (input.Length % SparseCompressionHelper.BlockSize > 0)
            {
                Console.WriteLine("Image size is not a multiple of {0} bytes", SparseCompressionHelper.BlockSize);
                return;
            }

            if (!Directory.Exists(outputPath))
            {
                Console.WriteLine("Output directory does not exist");
                return;
            }

            if (!outputPath.EndsWith(":") && !outputPath.EndsWith(@"\"))
            {
                outputPath += @"\";
            }

            string imageFileName = Path.GetFileName(inputPath);
            string prefix        = outputPath + imageFileName + "_sparsechunk";
            int    sparseIndex   = 1;

            while (true)
            {
                string     sparsePath = prefix + sparseIndex.ToString();
                FileStream output;
                try
                {
                    output = File.Open(sparsePath, FileMode.Create, FileAccess.ReadWrite, FileShare.None);
                    output.SetLength(0);
                }
                catch (IOException)
                {
                    Console.WriteLine("Cannot open " + sparsePath);
                    return;
                }
                catch (UnauthorizedAccessException)
                {
                    Console.WriteLine("Cannot open {0} - Access Denied", sparsePath);
                    return;
                }

                Console.WriteLine("Writing: {0}", sparsePath);
                bool complete = SparseCompressionHelper.WriteCompressedSparse(input, output, maxSparseSize);
                if (complete)
                {
                    break;
                }
                sparseIndex++;
            }
            input.Close();
        }