2016-10-07 4 views
1

Ich schreibe gerade eine Dropbox Art von Servlet und bin in der Phase, dass ich downloadbare Dateien zur Verfügung stellen kann und ich frage mich, ob es einen Unterschied in der Effizienz zwischen diesen beiden Methoden gibt.Servlet - was ist effizienter beim Bereitstellen einer herunterladbaren Datei?

Dies ist die Methode, die ich im Moment bin mit einem Download zur Verfügung zu stellen, verwende ich ein FileInputStream die Datei zu schreiben, die heruntergeladen wird immer:

  PrintWriter out = response.getWriter(); 
      response.setContentType("APPLICATION/OCTET-STREAM"); 
      response.setHeader("Content-Disposition","attachment; filename=\"" + "/" + fileName + "\""); 
      FileInputStream fileInputStream = new FileInputStream(filePath[1]); 
      int i; 
      while ((i=fileInputStream.read()) != -1) 
      { 
       out.write(i); 
      } 
      fileInputStream.close(); 
      out.close(); 

Aber nach einigen Recherchen fand ich heraus, dass die Mehrheit der Menschen verwendet eine byte Art von Ansatz statt:

OutputStream out = response.getOutputStream(); 
FileInputStream in = new FileInputStream(my_file); 
byte[] buffer = new byte[4096]; 
int length; 
while ((length = in.read(buffer)) > 0){ 
    out.write(buffer, 0, length); 
} 
in.close(); 
out.flush(); 

mein Ansatz in keiner Weise nachsteht? Oder ist die obige Methode einfach beliebter, weil es weniger Code ist?

Antwort

2

PrintWriter ist optimiert mit CharSequence arbeiten:

Drucke formatiert Darstellungen von Objekten auf einen Text-Ausgabe-Stream.

Abstrakte Klasse zum Schreiben in Zeichenströme. (Von Writer Dokumentation)

In Ihrem Code lesen Sie aus der Datei Byte für Byte und Sie kopieren das Byte auf dem PrintWriter. Es ist effizienter, Zeile für Zeile zu lesen und eine vollständige Zeile in die PrintWriter zu schreiben.


direkt die Verwendung von OutputStream Sie Batzen 4096 Bytes lesen und schreiben. Dies ist effizienter in Bezug auf CPU, weil Sie weniger while Schleifen machen.

In jedem Fall ist der Unterschied sehr begrenzt, da hier die Geschwindigkeit nicht mit der CPU, sondern mit der Geschwindigkeit des Netzwerks zusammenhängt. Wenn Sie versuchen, die Geschwindigkeit beider Methoden zu testen, werden Sie feststellen, dass es keinen messbaren Unterschied gibt und dass sie stark vom Netzwerkverkehr beeinflusst werden können.

Zusätzlich sollte die PrintWriter nur mit Textdateien verwendet werden, stattdessen ist die OutputStream Lösung nicht vom Dateityp abhängig.

-1

können Sie verwenden org.apache.commons.io.IOUtils für diese Aufgabe

 try { 
      // getting output and input streams 
      // Setting response headers.     
       out.write(IOUtils.toByteArray(inputStream)); 
       out.flush(); 
     } catch(Exception e) {//or you can handle the appropriate Exception. 
     } finally { 
       IOUtils.closeQuietly(inputStream); 
     } 
+0

Was passiert, wenn Sie versuchen, eine 10GB-Datei zu senden? Wie gut wird das mit einer 64MB JVM funktionieren? – stdunbar

+0

@stdunbar Es wird OOM werfen. Mein Code ist nur ein Beispiel für die bessere Möglichkeit, den Stream in die Antwort zu kopieren. Wenn es 10GB Datei ist, erhalten Sie OOM trotzdem, wenn Sie 64 MB JVM verwenden, es sei denn, Sie senden die Datei in Blöcken. Ich würde lieber eine andere Art bevorzugen, wie Cloud-Speicher und File-Sharing-Dienste machen das Senden von großen Dateien einfacher als je zuvor, und oft sind sie viel schneller und zuverlässiger. – user3325637

Verwandte Themen