2014-07-02 9 views
14

Coś jest nie tak z GZIPInputStream lub GZIPOutputStream. Tylko proszę przeczytać następujący kod (lub uruchomić go i zobaczyć, co się dzieje):Wyjątek: nieoczekiwany koniec strumienia wejściowego ZLIB

def main(a: Array[String]) { 
    val name = "test.dat" 
    new GZIPOutputStream(new FileOutputStream(name)).write(10) 
    println(new GZIPInputStream(new FileInputStream(name)).read()) 
} 

Tworzy plik test.dat, pisze jeden bajt 10 formatowanie przez GZIP i odczytać bajt w tym samym pliku w tym samym formacie .

A to co mam działa to:

linia
Exception in thread "main" java.io.EOFException: Unexpected end of ZLIB input stream 
    at java.util.zip.InflaterInputStream.fill(Unknown Source) 
    at java.util.zip.InflaterInputStream.read(Unknown Source) 
    at java.util.zip.GZIPInputStream.read(Unknown Source) 
    at java.util.zip.InflaterInputStream.read(Unknown Source) 
    at nbt.Test$.main(Test.scala:13) 
    at nbt.Test.main(Test.scala) 

Odczyt wydaje się dzieje w niewłaściwy sposób z jakiegoś powodu.

Wylogowałem się pod błędem Unexpected end of ZLIB input stream i znalazłem kilka raportów o błędach dla Oracle, które zostały wydane około 2007-2010. Domyślam się, że błąd nadal pozostaje w jakimś sensie, ale nie jestem pewien, czy mój kod jest właściwy, więc pozwól mi napisać to tutaj i wysłuchać twojej rady. Dziękuję Ci!

+1

* „Coś jest nie tak z GZIPInputStream lub GZIPOutputStream.” * - Wrong diagnoza. Prawdopodobieństwo, że prawdziwy problem nie występuje w tych klasach, wynosi 99,99%. –

+0

W rzeczywistości 100%. Zobacz moją odpowiedź. –

Odpowiedz

19

Musisz zadzwonić pod numer close() na GZIPOutputStream, zanim spróbujesz go przeczytać. Ostateczne bajty pliku zostaną zapisane tylko wtedy, gdy plik zostanie faktycznie zamknięty. (Jest to niezależne od jawnego buforowania w stosie wyjściowym Strumień wie tylko, aby skompresować i zapisać ostatnie bajty, gdy powiesz mu, aby zamknął.A flush() prawdopodobnie nie pomoże ... jednak powinno zadzwonić finish() zamiast close(). Spójrz na javadocs.)

Oto poprawny kod (w Javie);

package test; 

import java.io.FileInputStream; 
import java.io.FileNotFoundException; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.util.zip.GZIPInputStream; 
import java.util.zip.GZIPOutputStream; 

public class GZipTest { 

    public static void main(String[] args) throws FileNotFoundException, IOException { 
     String name = "/tmp/test"; 
     GZIPOutputStream gz = new GZIPOutputStream(new FileOutputStream(name)); 
     gz.write(10); 
     gz.close(); 
     System.out.println(new GZIPInputStream(new FileInputStream(name)).read()); 
    } 
} 

(. Zarządzania zasobami właściwie nie zostały wdrożone Nie traktuj tego jako przykład „dobrej kodu”).

+0

Co, jeśli utworzyłem instancję FileOutputStream tutaj przed zainicjowaniem GZIPOutputStream? Czy muszę również wywoływać close() na tym obiekcie? Ponieważ mój kod rzuca ten sam błąd, gdy wywoływany jest bliski. Czy także kolejność wywołania metody GZIPOutputStream i FileOutputStream close()? – Dish

+0

Nie, nie. Wywołanie 'close' na obiekcie' GZIPOutputStream' spowoduje wywołanie close na 'FileOutputStream', który otacza. (Istnieje teoretyczny wyciek zasobów, jeśli konstrukcja 'GZIPOutputStream' nie powiedzie się, ale myślę, że byłaby zauważalna tylko jeśli złapałeś/naprawiłeś z' Error' ... co jest złym rozwiązaniem.) –

+0

* "Również robi kolejność spraw GZIPOutputStream i FileOutputStream close() "*. Tak. To ma znaczenie. Jeśli najpierw zamkniesz FileOutputStream, to zamknięcie GZIPOutputStream spowoduje zgłoszenie wyjątku ... ponieważ nie może wypisać pozostałej części danych do zamkniętego FileOutputStream. –