2016-04-27 14 views
0

Ich habe Probleme mit dem Lesen meiner Datei. Ich bin auch ziemlich neu bei NIO. Die tatsächliche Größe der Datei, die ich an den Server senden möchte, ist fast 900MB und erhielt nur 3MB.Unvollständige Datei Kopieren Java NIO

den Seitencode des Servers zum Lesen:

private void read(SelectionKey key) throws IOException{ 
    SocketChannel socket = (SocketChannel)key.channel(); 
    RandomAccessFile aFile = null; 
    ByteBuffer buffer = ByteBuffer.allocate(300000000); 
    try{ 
     aFile = new RandomAccessFile("D:/test2/test.rar","rw"); 

     FileChannel inChannel = aFile.getChannel(); 

     while(socket.read(buffer) > 0){ 
      buffer.flip(); 
      inChannel.write(buffer); 
      buffer.compact(); 
     } 
     System.out.println("End of file reached.."); 
    }catch(Exception e){ 
     e.printStackTrace(); 
    } 
} 

Das ist mein Code für die Schreibmethode der Client-Seite ist:

private void write(SelectionKey key) throws IOException { 
    SocketChannel socket = (SocketChannel) key.channel(); 
    RandomAccessFile aFile = null; 
    try { 
     File f = new File("D:/test.rar"); 
     aFile = new RandomAccessFile(f, "r"); 
     ByteBuffer buffer = ByteBuffer.allocate(300000000); 

     FileChannel inChannel = aFile.getChannel(); 
     while (inChannel.read(buffer) > 0) { 
      buffer.flip(); 
      socket.write(buffer); 
      buffer.compact(); 
     } 
     aFile.close(); 
     inChannel.close(); 

     key.interestOps(SelectionKey.OP_READ); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 
+0

Nur zu denken: read() sagt Ihnen normalerweise die genaue Anzahl Bytes, die gelesen wurden. Das bedeutet nicht, dass ALLE Pufferbytes gelesen wurden. Zumindest in der alten Schule IO mussten Sie Schleife, bis Sie ALLE Bytes von Ihrem Puffer lesen. – GhostCat

+0

'socket.read (buffer)> 0' + nicht blockierendes IO = Fehler, weil Null nicht das Ende des Streams bedeutet, sondern nur das Fehlen von Daten, die im Moment zum Lesen bereit sind. Sie lesen also völlig blockierend, während Sie mit NIO arbeiten, was offensichtlich nicht funktioniert. – user3707125

Antwort

2
  1. Sie eine neue Datei zu öffnen jedes Mal, Der Socket-Kanal wird lesbar. Jedes TCP-Segment, das ankommt, erstellt die Zieldatei neu und verwirft daher das, was zuvor empfangen wurde.

    Die einfache Lösung wäre, die Datei zum Anhängen auf jedem OP_READ zu öffnen, aber es würde lächerlich ineffizient bleiben. Sie sollten die Zieldatei öffnen, sobald Sie wissen, was sie ist, und sie schließen, wenn Sie das Ende des Streams vom Absender lesen, oder wenn Sie den gesamten Inhalt gelesen haben, wenn dies nicht am Ende des Streams angezeigt wird. Sie haben Ihr Anwendungsprotokoll nicht veröffentlicht, daher kann ich nicht genauer sein.

  2. read() gibt Null zurück, wenn keine Daten zum Lesen ohne Blockierung verfügbar sind. Sie behandeln das als Dateiende. Es ist nicht.
  3. Die kanonische Weise zu Schreib zwischen den Kanälen ist wie folgt:

    while ((in.read(buffer) > 0 || buffer.position() > 0) 
    { 
        buffer.flip(); 
        out.write(buffer); 
        buffer.compact(); 
    } 
    

    Allerdings, wenn das Ziel ein nicht-blockierenden Socket-Kanal diese wesentlich komplexer wird: Sie müssen manipulieren, ob Sie ausgewählt sind für OP_WRITE oder nicht, abhängig davon, ob die letzte write() Null zurückgegeben hat oder nicht. Sie werden das hier in einer großen Anzahl von Beiträgen finden, viele von mir.

  4. Ich habe noch nie einen zwingenden Grund für nicht blockierende E/A auf der Client-Seite gesehen, es sei denn, es verbindet sich mit mehreren Servern (ein Web-Crawler zum Beispiel). Ich würde Blockierungsmodus oder java.net.Socket auf dem Client verwenden, was die oben erwähnte Schreibkomplexität vermeidet.

NB Sie müssen nicht sowohl die RandomAccessFile und die FileChannel zu schließen, die von ihm abgeleitet wurde. Beides funktioniert.

+0

Also, was ist der beste Weg zu schreiben, wenn es ein nicht blockierender Socket-Kanal ist? – jnapor

+0

Mit einem * blockierenden * Socket-Kanal oder einem 'java.net.Socket'. Ich sagte, dass. – EJP

Verwandte Themen