2015-08-16 4 views
0

Я написал загрузчик, который должен использоваться для загрузки текстовых файлов, а также изображений. Поэтому я загружаю файлы в виде двоичных файлов. Многие из загрузок работают очень хорошо, но некоторые части текстовых файлов и многие файлы изображений повреждены. Ошибки происходят всегда в тех же файлах и в тех же местах (до тех пор, пока я могу сказать, анализируя текстовые файлы). Я использовал этот код для загрузки:Файлы, загруженные как двоичные с Java, повреждены

public File downloadFile(HttpURLConnection connection) { 
     return writeFileDataToFile(getFileData(connection)); 
    }  

    //downloads the data of the file and returns the content as string 
    private List<Byte> getFileData(HttpURLConnection connection) { 
     List<Byte> fileData = new ArrayList<>(); 

     try (InputStream input = connection.getInputStream()) { 
      byte[] fileChunk = new byte[8*1024]; 
      int bytesRead; 

      do { 
       bytesRead = input.read(fileChunk); 
       if (bytesRead != -1) { 
        fileData.addAll(Bytes.asList(fileChunk)); 
        fileChunk = new byte[8*1024]; 
       } 
      } while (bytesRead != -1); 

      return fileData; 
     } catch (IOException e) { 
      System.out.println("Receiving file at " + url.toString() + " failed"); 
      System.exit(1); 
      return null; //shouldn't be reached 
     } 
    } 

    //writes data to the file 
    private File writeFileDataToFile(List<Byte> fileData) { 

     if (!this.file.exists()) { 
      try { 
       this.file.getParentFile().mkdirs(); 
       this.file.createNewFile(); 
      } catch (IOException e) { 
       System.out.println("Error while creating file at " + file.getPath()); 
       System.exit(1); 
      } 
     } 

     try (OutputStream output = new FileOutputStream(file)) { 
      output.write(Bytes.toArray(fileData)); 
      return file; 
     } catch (IOException e) { 
      System.out.println("Error while accessing file at " + file.getPath()); 
      System.exit(1); 
      return null; 
     } 
    } 
+0

Вы полагаете, что '' bytesRead' является -1' или '8192', что это такое MTU, как ~ 1500 байт? –

ответ

1

Я мог бы предложить вам не пройти через Список Byte, так как вы создаете список байт из массива, чтобы получить его обратно в массив байт, который не является действительно эффективный.

Кроме того, вы ошибочно принимаете размер блока (не обязательно 8192 байта).

Почему вы не просто делать что-то как:

private File writeFileDataToFile(HttpURLConnection connection) { 
    if (!this.file.exists()) { 
     try { 
      this.file.getParentFile().mkdirs(); 
      //this.file.createNewFile(); // not needed, will be created at FileOutputStream 
     } catch (IOException e) { 
      System.out.println("Error while creating file at " + file.getPath()); 
      //System.exit(1); 
      // instead do a throw of error or return null 
      throw new YourException(message); 
     } 
    } 
    OutputStream output = null; 
    InputStream input = null; 
    try { 
     output = new FileOutputStream(file): 
     input = connection.getInputStream(); 
     byte[] fileChunk = new byte[8*1024]; 
     int bytesRead; 
     while ((bytesRead = input.read(fileChunk)) != -1) { 
     output.write(fileChunk , 0, bytesRead); 
     } 
     return file; 
    } catch (IOException e) { 
     System.out.println("Receiving file at " + url.toString() + " failed"); 
     // System.exit(1); // you should avoid such exit 
     // instead do a throw of error or return null 
     throw new YourException(message); 
    } finally { 
     if (input != null) { 
     try { 
      input.close(); 
     } catch (Execption e2) {} // ignore 
     } 
     if (output != null) { 
     try { 
      output.close(); 
     } catch (Execption e2) {} // ignore 
     } 
    } 
} 
+0

Спасибо! Сбой состоял в том, чтобы каждый раз добавлять файл fileChunk, даже если он не был полностью использован, что вызвало добавление неправильных 0 байтов в fileData. – DevWurm

0

Провал добавлял весь fileChunk массив в файл данных, даже если он не был полностью заполнен операции чтения.

Fix:

//downloads the data of the file and returns the content as string 
private List<Byte> getFileData(HttpURLConnection connection) { 
    List<Byte> fileData = new ArrayList<>(); 

    try (InputStream input = connection.getInputStream()) { 
     byte[] fileChunk = new byte[8*1024]; 
     int bytesRead; 

     do { 
      bytesRead = input.read(fileChunk); 
      if (bytesRead != -1) { 
       fileData.addAll(Bytes.asList(Arrays.copyOf(fileChunk, bytesRead))); 
      } 
     } while (bytesRead != -1); 

     return fileData; 
    } catch (IOException e) { 
     System.out.println("Receiving file at " + url.toString() + " failed"); 
     System.exit(1); 
     return null; //shouldn't be reached 
    } 
} 

Если соответствующее изменение меняется

if (bytesRead != -1) { 
    fileData.addAll(Bytes.asList(fileChunk)); 
    fileChunk = new byte[8*1024]; 
} 

в

if (bytesRead != -1) { 
    fileData.addAll(Bytes.asList(Arrays.copyOf(fileChunk, bytesRead))); 
} 
Смежные вопросы