2015-12-03 6 views
0

Я пытаюсь записать сжатые данные в файл, а затем читать данные и распаковывать их с помощью библиотеки GZIP. Я попытался изменить все форматирование на StandardCharsets.UTF-8 и ISO-8859-1, и ни одна из них не исправила ошибку формата GZIP. Мне интересно, возможно ли это сделать с файлом, который я читаю? Вот функция сжатия:Не в формате GZIP - JAVA

public static byte[] compress(String originalFile, String compressFile) throws IOException { 

    // read in data from text file 
    // The name of the file to open. 
    String fileName = originalFile; 

    // This will reference one line at a time 
    String line = null; 
    String original = ""; 

    try { 
     // FileReader reads text files in the default encoding. 
     FileReader fileReader = 
      new FileReader(fileName); 

     // Always wrap FileReader in BufferedReader. 
     BufferedReader bufferedReader = 
      new BufferedReader(fileReader); 

     while((line = bufferedReader.readLine()) != null) { 
      original.concat(line); 
     } 

     // Always close files. 
     bufferedReader.close();   
    } 
    catch(FileNotFoundException ex) { 
     System.out.println(
      "Unable to open file '" + 
      fileName + "'");     
    } 
    catch(IOException ex) { 
     System.out.println(
      "Error reading file '" 
      + fileName + "'");     
     // Or we could just do this: 
     // ex.printStackTrace(); 
    } 


    // create a new output stream for original string 
    try (ByteArrayOutputStream out = new ByteArrayOutputStream()) 
    { 
     try (GZIPOutputStream gzip = new GZIPOutputStream(out)) 
     { 
      gzip.write(original.getBytes(StandardCharsets.UTF_8)); 
     } 
     byte[] compressed = out.toByteArray(); 
     out.close(); 

     String compressedFileName = compressFile; 

     try { 
      // Assume default encoding. 
      FileWriter fileWriter = 
       new FileWriter(compressedFileName); 

      // Always wrap FileWriter in BufferedWriter. 
      BufferedWriter bufferedWriter = 
       new BufferedWriter(fileWriter); 

      // Note that write() does not automatically 
      // append a newline character. 
      String compressedStr = compressed.toString(); 
      bufferedWriter.write(compressedStr); 

      // Always close files. 
      bufferedWriter.close(); 
     } 
     catch(IOException ex) { 
      System.out.println(
       "Error writing to file '" 
       + fileName + "'"); 
      // Or we could just do this: 
      // ex.printStackTrace(); 
     } 
     return compressed; 
    } 
} 

(Я получаю ошибку на линии в следующей функции декомпрессия) -

GZIPInputStream compressedByteArrayStream = new GZIPInputStream(new ByteArrayInputStream(s.getBytes(StandardCharsets.UTF_8))); 

декомпрессионной Функция:

public static String decompress(String file) throws IOException { 

    byte[] compressed = {}; 
    String s = ""; 

    File fileName = new File(file); 
    FileInputStream fin = null; 
    try { 
     // create FileInputStream object 
     fin = new FileInputStream(fileName); 

     // Reads up to certain bytes of data from this input stream into an array of bytes. 
     fin.read(compressed); 
     //create string from byte array 
     s = new String(compressed); 
     System.out.println("File content: " + s); 
    } 
    catch (FileNotFoundException e) { 
     System.out.println("File not found" + e); 
    } 
    catch (IOException ioe) { 
     System.out.println("Exception while reading file " + ioe); 
    } 
    finally { 
     // close the streams using close method 
     try { 
      if (fin != null) { 
       fin.close(); 
      } 
     } 
     catch (IOException ioe) { 
      System.out.println("Error while closing stream: " + ioe); 
     } 
    } 


    // create a new input string for compressed byte array 
    GZIPInputStream compressedByteArrayStream = new GZIPInputStream(new ByteArrayInputStream(s.getBytes(StandardCharsets.UTF_8))); 
    ByteArrayOutputStream byteOutput = new ByteArrayOutputStream(); 

    byte[] buffer = new byte[8192]; 

    // create a string builder and byte reader for the compressed byte array 
    BufferedReader decompressionBr = new BufferedReader(new InputStreamReader(compressedByteArrayStream, StandardCharsets.UTF_8)); 
    StringBuilder decompressionSb = new StringBuilder(); 

    // write data to decompressed string 
    String line1; 
    while((line1 = decompressionBr.readLine()) != null) { 
     decompressionSb.append(line1); 
    } 
    decompressionBr.close(); 

    int len; 
    String uncompressedStr = ""; 
    while((len = compressedByteArrayStream.read(buffer)) > 0) { 
     uncompressedStr = byteOutput.toString(); 
    } 

    compressedByteArrayStream.close(); 
    return uncompressedStr; 
} 

Вот сообщение об ошибке что я получаю:

[[email protected] 
File content: 
java.io.EOFException 
    at java.util.zip.GZIPInputStream.readUByte(GZIPInputStream.java:268) 
    at java.util.zip.GZIPInputStream.readUShort(GZIPInputStream.java:258) 
    at java.util.zip.GZIPInputStream.readHeader(GZIPInputStream.java:164) 
    at java.util.zip.GZIPInputStream.<init>(GZIPInputStream.java:79) 
    at java.util.zip.GZIPInputStream.<init>(GZIPInputStream.java:91) 
    at org.kingswoodoxford.Compression.decompress(Compression.java:136) 
    at org.kingswoodoxford.Compression.main(Compression.java:183) 

Любые предложения относительно того, как я могу это исправить?

+0

Ваш исходный файл действительно utf 8? –

+0

Не конвертируйте в строку. Нет необходимости, и большинство наборов символов не будут обрабатывать все возможные байты. И если вы не используете строки, тогда нет необходимости использовать «Reader» и «Writer»; используйте 'InputStream' и' OutputStream'. – kdgregory

ответ

0

Когда вы читаете файл, вы отбрасываете новую строку в конце каждой строки.

Более эффективная опция, которая делает это, заключается в том, чтобы скопировать блок, то есть char[] за раз. Вы также можете преобразовать текст по ходу, а не создавать строку или байт [].

BTW original.concat(line); возвращает конкатенированную строку, которую вы отбрасываете.

Настоящая проблема заключается в том, что вы пишете в один поток и закрываете другой. Это означает, что если в конце файла есть буферные данные (и это очень вероятно), конец файла будет усечен, и когда вы его прочитаете, он будет жаловаться, что ваш файл неполный или EOFException.

Вот короткий пример

public static void compress(String originalFile, String compressFile) throws IOException { 
    char[] buffer = new char[8192]; 
    try (
      FileReader reader = new FileReader(originalFile); 
      Writer writer = new OutputStreamWriter(
        new GZIPOutputStream(new FileOutputStream(compressFile))); 
    ) { 
     for (int len; (len = reader.read(buffer)) > 0;) 
      writer.write(buffer, 0, len); 
    } 
} 

В декомпрессия, не кодируют двоичным как текст и попытаться получить обратно те же данные. Это почти наверняка будет испорчено. Попробуйте использовать буфер и цикл, как я сделал для сжатия. то есть это не должно быть более сложным.

+0

Спасибо, поэтому я считаю, что я исправил проблему закрытия потока, закрыв свой GZIPOutputStream, а также мой ByteArrayOutputStream. Что касается чтения файла, я не совсем уверен, как я отбрасываю новую строку в конце каждой строки и как я могу это исправить. –

+0

@TreyTaylor 'BufferedReader.readLine()' не включает в себя новые строковые символы. См. Мой ответ, как вы должны это делать. –

+0

@TreyTaylor, думая об этом, вы должны действительно чему-то научиться, потому что вы, кажется, объединили почти каждую распространенную ошибку, о которой я могу думать. ;) Хотя вы не использовали StringBuffer как минимум^_^ –