Ich schreibe ein wenig C# Appx Paket-Editor (appx ist im Grunde eine Zip-Datei mit einer Reihe von XML-Metadaten-Dateien).Wie bekomme ich die komprimierte Größe (ZipArchive) eines FileStream-Blocks?
Um eine gültige appx Datei zu machen, ich brauche einen Block Map-Datei (XML), die für jede Datei zwei Attribute enthält erstellen: hash und Größe wie hier erklärt (https://docs.microsoft.com/en-us/uwp/schemas/blockmapschema/element-block)
Hash repräsentieren ein 64kb unkomprimiert Stück einer Datei. Größe repräsentiert die Größe dieses Chunks nach der Komprimierung (Deflate-Algorithmus). Hier ist, was ich bisher als Proof of Concept hat geschrieben:
using System;
using System.IO;
using System.IO.Compression;
using System.Linq;
namespace StreamTest
{
class Program
{
static void Main(string[] args)
{
using (var srcFile = File.OpenRead(@"C:\Test\sample.txt"))
{
ZipAndHash(srcFile);
}
Console.ReadLine();
}
static void ZipAndHash(Stream inStream)
{
const int blockSize = 65536; //64KB
var uncompressedBuffer = new byte[blockSize];
int bytesRead;
int totalBytesRead = 0;
//Create a ZIP file
using (FileStream zipStream = new FileStream(@"C:\Test\test.zip", FileMode.Create))
{
using (ZipArchive zipArchive = new ZipArchive(zipStream, ZipArchiveMode.Create))
{
using (BinaryWriter zipWriter = new BinaryWriter(zipArchive.CreateEntry("test.txt").Open()))
{
//Read stream with a 64kb buffer
while ((bytesRead = inStream.Read(uncompressedBuffer, 0, uncompressedBuffer.Length)) > 0)
{
totalBytesRead = totalBytesRead + bytesRead;
//Compress current block to the Zip entry
if (uncompressedBuffer.Length == bytesRead)
{
//Hash each 64kb block before compression
hashBlock(uncompressedBuffer);
//Compress
zipWriter.Write(uncompressedBuffer);
}
else
{
//Hash remaining bytes and compress
hashBlock(uncompressedBuffer.Take(bytesRead).ToArray());
zipWriter.Write(uncompressedBuffer.Take(bytesRead).ToArray());
}
}
//How to obtain the size of the compressed block after invoking zipWriter.Write() ?
Console.WriteLine($"total bytes : {totalBytesRead}");
}
}
}
}
private static void hashBlock(byte[] uncompressedBuffer)
{
// hash the block
}
}
}
ich einfach den Hash-Attribut unter Verwendung eines 64 kb-Puffer erhalten kann, während ein Stream zu lesen, meine Frage ist:
Wie erhalte ich die komprimierte Größe von jedem 64kb-Block nach der Verwendung von zipWrite.Write(), ist es überhaupt möglich mit System.IO.Compression oder sollte ich etwas anderes verwenden?
Können Sie es aus dem ZipArchive-Objekt abrufen? So etwas wie zipArchive.GetEntry ("test.txt"). CompressedLength – wakers01
Leider nicht: NotSupportedException Das Zip-Archiv unterstützt das Lesen nicht, wahrscheinlich weil der Eintrag noch nicht komplett geschrieben ist. – Coloris