C # MemoryStream & GZipInputStream: Δεν είναι δυνατή η .Read περισσότερα από 256 bytes

ψήφοι
1

Αντιμετωπίζω ένα πρόβλημα με τη σύνταξη ενός ασυμπίεστο ρεύμα GZIP χρησιμοποιώντας GZipInputStream SharpZipLib του. Μου φαίνεται να είναι σε θέση να πάρει 256 bytes αξίας των στοιχείων με τα υπόλοιπα δεν είναι γραπτή και αριστερά μηδενίζεται μόνο. Το συμπιεσμένο ρεύμα (compressedSection) έχει ελεγχθεί και όλα τα δεδομένα είναι εκεί (1500 + bytes). Το απόσπασμα της διαδικασίας αποσυμπίεσης είναι κάτω:

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();

Έτσι, σε αυτό το απόσπασμα:

1) Το συμπιεσμένο τμήμα διοχετεύεται στο, έτοιμο να αποσυμπιεστούν.

2) Το αναμενόμενο μέγεθος του ασυμπίεστου εξόδου (η οποία αποθηκεύεται σε μια κεφαλίδα με το αρχείο ως 2-byte little-endian αξία) διέρχεται μέσω μιας μεθόδου για να το μετατρέψει σε ακέραιο. Η κεφαλίδα αφαιρείται νωρίτερα, δεδομένου ότι δεν αποτελεί μέρος του συμπιεσμένου αρχείου GZIP.

3) ρεύμα GZIP SharpLibZip του δηλώνεται με το συμπιεσμένο ρεύμα αρχείο (MSI) και ένα ρυθμιστικό διάλυμα ίση με int uncompressedIntSize (έχουν δοκιμαστεί με μία στατική τιμή της 4096, όπως επίσης).

4) Έχω δημιουργήσει ένα MemoryStream να χειριστεί εγγράφως την έξοδο σε ένα αρχείο όπως GZipInputStream δεν έχει ανάγνωσης / εγγραφής? παίρνει το αναμενόμενο αποσυμπιεσμένο μέγεθος του αρχείου ως επιχείρημα (χωρητικότητα).

5) Η ανάγνωση / εγγραφή των αναγκών σύνολο byte [] array ως το πρώτο επιχείρημα, έτσι δημιουργήσει ένα byte [] array με αρκετό χώρο για να λάβει όλα τα bytes του αποσυμπιεσμένου εξόδου (3584 bytes σε αυτή την περίπτωση, που προέρχεται από uncompressedIntSize ).

6) int GzipInputStream decompressStream χρησιμοποιεί .Read με το ρυθμιστικό διάλυμα ως πρώτο επιχείρημα, από offset 0, χρησιμοποιώντας το uncompressedIntSize ως την καταμέτρηση. Έλεγχος των επιχειρήματα εδώ, η συστοιχία ρυθμιστικό διάλυμα εξακολουθεί να έχει μια χωρητικότητα των 3584 bytes, αλλά μόνο έχει δοθεί 256 bytes δεδομένων. Τα υπόλοιπα είναι μηδενικά.

Μοιάζει η έξοδος της .Read είναι να στραγγαλίζεται με 256 bytes, αλλά δεν είμαι σίγουρος πού. Υπάρχει κάτι που έχω χάσει τα ρέματα, ή πρόκειται για ένα περιορισμό με .Read;

Δημοσιεύθηκε 09/10/2019 στις 19:00
πηγή χρήστη
Σε άλλες γλώσσες...                            


2 απαντήσεις

ψήφοι
2

Θα πρέπει να βρόχο κατά την ανάγνωση από ένα ρεύμα? ο τεμπέλης τρόπος είναι πιθανόν να:

decompressStream.CopyTo(outputStream);

(αλλά αυτό δεν εγγυάται για να σταματήσει μετά από uncompressedIntSizebytes - αυτό θα προσπαθήσει να διαβάσει μέχρι το τέλος του decompressStream)

Μια πιο χειροκίνητη έκδοση (η οποία θα σέβεται την επέβαλε όριο) θα είναι:

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);
}
Απαντήθηκε 09/10/2019 στις 19:10
πηγή χρήστη

ψήφοι
0

Το θέμα κατέληξε να είναι μια παράλειψη που είχα κάνει νωρίτερα στην δημοσιεύτηκε κωδικό:

Το αρχείο δουλεύω με έχει 27 τμήματα τα οποία gzipped, αλλά το καθένα έχει μια κεφαλίδα που θα σπάσει την αποσυμπίεση Gzip αν το ρεύμα GZipInput χτυπήσει κάποιο από αυτά. Κατά το άνοιγμα του αρχείου βάσης, έγινε ξεκινώντας από την αρχή (ρυθμίστηκε από 6 για να αποφευχθεί η πρώτη κεφαλίδα) κάθε φορά αντί να πηγαίνουν στο επόμενο post-κεφαλή offset:

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

Αντί:

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

Αυτό σήμαινε ότι η εκχυλίζεται συμπιεσμένων δεδομένων ήταν ένα αμάλγαμα του πρώτου τμήματος χωρίς κεφαλίδα + μέρος του 2ου τμήματος, μαζί με κεφαλίδας του. Καθώς το πρώτο τμήμα έχει μήκος 256 bytes χωρίς επικεφαλίδα του, αυτό το μέρος ήταν να αποσυμπιέζεται σωστά από το ρεύμα GZipInput. Αλλά μετά από αυτό είναι 6-bytes της επικεφαλίδας που σπάει, με αποτέλεσμα το υπόλοιπο της εξόδου είναι 00s.

Δεν υπήρχε ρητή λάθος που ρίχνονται από το ρεύμα GZipInput όταν αυτό συμβεί, γι 'αυτό θα εσφαλμένα θεωρείται ότι η αιτία ήταν η .Read ή κάτι στο ρεύμα διατήρηση δεδομένων από την προηγούμενη πέρασμα. Συγγνώμη για την ταλαιπωρία.

Απαντήθηκε 10/10/2019 στις 13:58
πηγή χρήστη

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