C # Memory & GZipInputStream: Kann nicht mehr als 256 Byte .Read

stimmen
1

Ich habe ein Problem mit dem Schreiben einen unkomprimierten GZIP Stromes SharpZipLib des GZipInputStream verwenden. Ich scheine nur in der Lage sein, 256 Bytes im Wert von Daten zu erhalten, der Rest nicht sein geschrieben und auf Null gestellt gelassen. Der komprimierte Strom (compressedSection) wurde geprüft und alle Daten gibt (1500 Bytes). Das Snippet des Dekomprimierungsvorgang ist unten:

int msiBuffer = 4096;
                using (Stream msi = new MemoryStream(msiBuffer))
                {
                    msi.Write(compressedSection, 0, compressedSection.Length);
                    msi.Position = 0;
                    int uncompressedIntSize = AllMethods.GetLittleEndianInt(uncompressedSize, 0); // Gets little endian value of uncompressed size into an integer

                    // SharpZipLib GZip method called
                    using (GZipInputStream decompressStream = new GZipInputStream(msi, uncompressedIntSize))
                    {
                        using (MemoryStream outputStream = new MemoryStream(uncompressedIntSize))
                        {
                            byte[] buffer = new byte[uncompressedIntSize];
                            decompressStream.Read(buffer, 0, uncompressedIntSize); // Stream is decompressed and read         
                            outputStream.Write(buffer, 0, uncompressedIntSize);
                            using (var fs = new FileStream(kernelSectionUncompressed, FileMode.Create, FileAccess.Write))
                            {
                                fs.Write(buffer, 0, buffer.Length);
                                fs.Close();
                            }
                            outputStream.Close();
                        }
                        decompressStream.Close();

Also in diesem Auszug:

1) Der Druckabschnitt geleitet wird, fertig dekomprimiert werden.

2) Die erwartete Größe des unkomprimierten Ausgangs (die in einem Header mit der Datei als einen 2-Byte-Little-Endian-Wert gespeichert ist) wird durch eine Methode übergeben konvertieren es integer zu. Der Header wird entfernt früher, da sie nicht Teil der komprimierten GZIP-Datei.

3) SharpLibZip des GZIP Strom mit dem komprimierten Dateistrom deklariert wird (msi) und einen Puffer gleich int uncompressedIntSize (haben mit einem statischen Wert von 4096 als auch) getestet.

4) stelle ich einen Memorystream bis zu handhaben die Ausgabe in eine Datei als GZipInputStream Schreiben nicht über Lese- / Schreib; es nimmt die erwartete dekomprimiert Dateigröße als Argument (Kapazität).

5) Die Lese- / Schreibvorgang des Stream Bedürfnisse byte [] -Array als erstes Argument, so dass ich eine byte [] Array mit genügend Platz alle Bytes der dekomprimierten Ausgang zu nehmen (3584 Bytes in diesem Fall, abgeleitet von uncompressedIntSize ).

6) int GzipInputStream decompressStream verwendet .Read mit dem Puffer als erstes Argument, von 0 versetzt ist, die uncompressedIntSize als die Zählung verwendet wird. Prüfen der Argumente hier hat der Puffer-Array noch eine Kapazität von 3584 Bytes, wurde aber nur 256 Byte Daten gegeben. Der Rest sind Nullen.

Es sieht aus wie die Ausgabe von .Read ist auf 256 Bytes gedrosselt, aber ich bin nicht sicher, wo. Gibt es etwas, das ich mit den Streams verpasst haben, oder ist dies eine Einschränkung mit .Read?

Veröffentlicht am 09/10/2019 um 19:00
quelle vom benutzer
In anderen Sprachen...                            


2 antworten

stimmen
2

Sie müssen Schleife , wenn sie von einem Strom zu lesen; die faule Art und Weise ist wahrscheinlich:

decompressStream.CopyTo(outputStream);

(aber das garantiert nicht , nach dem stoppen uncompressedIntSizeBytes - es wird versuchen , bis zum Ende zu lesen decompressStream)

Eine manuelle Version (die eine auferlegte Längenbegrenzung respektiert) wäre:

const int BUFFER_SIZE = 1024; // whatever
var buffer = ArrayPool<byte>.Shared.Rent(BUFFER_SIZE);
try
{
    int remaining = uncompressedIntSize, bytesRead;
    while (remaining > 0 && // more to do, and making progress
        (bytesRead = decompressStream.Read(
        buffer, 0, Math.Min(remaining, buffer.Length))) > 0)
    {
        outputStream.Write(buffer, 0, bytesRead);
        remaining -= bytesRead;
    }
    if (remaining != 0) throw new EndOfStreamException();
}
finally
{
    ArrayPool<byte>.Shared.Return(buffer);
}
Beantwortet am 09/10/2019 um 19:10
quelle vom benutzer

stimmen
0

Die Frage stellte sich heraus, ein Versehen sein, die ich früher in den entsandten Code gemacht hatte:

Die Datei, die ich mit gerade arbeite hat 27 Abschnitte, die gzipped sind, aber sie haben jeweils einen Header, der die gzip-Dekomprimierung brechen wird, wenn der GZipInput Strom einer von ihnen trifft. Wenn die Basisdatei zu öffnen, wurde ausgehend von Anfang an statt jedes Mal (bereinigt um 6 den ersten Kopf zu vermeiden) auf den nächsten Post-Kopf gehen versetzt:

brg.BaseStream.Seek (6, SeekOrigin.Begin);

Anstatt von:

brg.BaseStream.Seek (absoluteSectionOffset, SeekOrigin.Begin);

Dies bedeutete, dass die extrahierten komprimierten Daten ein Amalgam des ersten headerless Abschnitt + Teil des zweiten Abschnitts zusammen mit seinem Kopf war. Da der erste Abschnitt 256 Bytes lang ohne seine Header ist, wurde dieser Teil korrekt durch den Strom GZipInput dekomprimiert wird. Aber danach 6-Byte-Header, die es bricht, was zu dem Rest des auszugebende 00s.

Es gab keinen expliziten Fehler durch den GZipInput Strom geworfen wird, wenn dies geschehen ist, so würde ich fälschlicherweise angenommen, dass die Ursache die .Read oder etwas im Strom war Daten aus dem vorherigen Durchlauf zu halten. Tut mir leid wegen dem Ärger.

Beantwortet am 10/10/2019 um 13:58
quelle vom benutzer

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more