2016-04-02 8 views
1

wurden wir ein paar Übungen im Labor gegeben und einer von diesen ist die Dateiübertragungsmethode von FileInputStream in BufferedInputStream zu konvertieren. Es ist ein Client, der eine GET-Anfrage an einen Webserver sendet, der die angeforderte Datei sendet. Ich kam zu einer einfachen Lösung, und ich wollte nur überprüfen, ob es korrekt ist.Von FileInputStream zu BufferedInputStream Konvertierung

Originalcode:

try { 
     FileInputStream fis = new FileInputStream(req); 
     // req, String containing file name 
     byte[] data = new byte [fis.available()]; 
     fis.read(data); 
     out.write(data); // OutputStream out = socket.getOutputStream(); 
    } catch (FileNotFoundException e){ 
     new PrintStream(out).println("404 Not Found"); 
    } 

Mein Versuch:

try { 
     BufferedInputStream bis = new BufferedInputStream (new FileInputStream(req)); 
     byte[] data = new byte[4]; 

     while(bis.read(data) > -1) { 
     out.write(data); 
     data = new byte[4]; 
     } 
    } catch (FileNotFoundException e){ 
     new PrintStream(out).println("404 Not Found"); 
    } 

Die Datei ist eine Web-Seite index.html genannt, die eine einfache HTML-Seite enthält. Ich muss das Array jedes Mal neu zuweisen, da bei der letzten Ausführung der While-Schleife, wenn die Datei kein Vielfaches von 4 ist, das Datenarray Zeichen aus der vorherigen Ausführung enthält, die im Browser angezeigt werden . Ich wählte 4 als Datengröße für Debugging-Zwecke. Ausgabe ist korrekt.

Ist das eine gute Lösung oder kann ich es besser machen?

Antwort

1

Sie müssen das Byte-Array nicht jedes Mal neu erstellen - überschreiben Sie es einfach. Was noch wichtiger ist, Sie haben einen konzeptionellen Fehler innerhalb Ihrer Schleife. Jede Iteration schreibt das Array einfach in den Stream, vorausgesetzt, es ist alles gültig. Wenn Sie die Dokumentation von BufferedInputStream#read untersuchen, sehen Sie, dass möglicherweise nicht genügend Daten gelesen werden, um das gesamte Array zu füllen, und die Anzahl der tatsächlich gelesenen Bytes zurückgibt. Sie sollten diese Nummer verwenden, um die Menge an Bytes zu begrenzen Sie schreiben:

while((int len = bis.read(data)) > -1) { 
    out.write(data, 0, len); 
} 
0

Ich schlage vor, Sie schließen Sie Ihre Datei, sobald Sie fertig sind. Der BufferedInputStream verwendet standardmäßig einen 8-KB-Puffer, den Sie auf einen kleineren Puffer reduzieren. Eine einfachere Lösung besteht darin, 8 KB gleichzeitig zu kopieren und den hinzugefügten Puffer

try (InputStream in = new FileInputStream(req)) { 
    byte[] data = new byte[8 << 10]; 
    for (int len; (len = bis.read(data)) > -1;) 
     out.write(data, 0, len); 
} catch (IOException e) { 
    out.write("404 Not Found\n".getBytes()); 
} 
+0

nicht zu verwenden danke für die Antwort. Im Falle von Dateien, die auf dem hd gespeichert sind, greift FileInputStream bei jeder Leseoperation auf den Datenträger zu, während BufferedInputStream dies nicht tut, was es allgemein effizienter macht. Stimmt das, wenn Dateien über ein Netzwerk bereitgestellt werden - was ist jetzt mein Fall? Oder gibt es im Grunde keinen Unterschied? –

+0

FileInputStream greift bei jedem Lesevorgang auf das Betriebssystem zu, das Betriebssystem kann vorausschauend vorauslesen und trifft nur gelegentlich auf die Festplatte. BufferedInputStream hilft nur, wenn die Datenblöcke, die Sie lesen, viel kleiner sind, z. << 512 Bytes, als der Puffer es liest. es ist keine Magie, es macht nur das, was Sie bereits tun, indem Sie einen größeren Puffer lesen. –