# Buffergröße anpassen, aber wie?



## Hans Guck In Die Luft (2. Nov 2007)

Hallo,
ich habe einen Server und einen Client programmiert, die sich eine Datei zuschicken sollen. Wenn ich kleine Dateien benutze funktioniert das ganze auch. Bei größeren Dateien klappt es allerdings nicht. Ich glaube, dass das daran liegt, dass der letzte Buffer, der verschickt wird nicht, nicht vollständig gefüllt ist. Wie kann ich es hinbekommen, dass der letzte Buffer nur so groß ist, wie er auch sein muss? Bin für jede Antwort dankbar. Hier Quellcode von Server und Client...


SERVER:

```
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.io.*;

public class FileTransferServer {

	DataInputStream dis = null; 
	  int b = 0;
	  byte[] schreib = new byte[1024];
	  String text = "";
	  DataOutputStream textstream;
	  
	  
	  private final ServerSocket server;
	  public FileTransferServer( int port ) throws IOException
	  {
	    server = new ServerSocket( port );
	    //server.setSoTimeout(60000); //60 Sekunden
	    
	  }
	  private void startServing()
	  {
	    while ( true )
	    {
	      Socket client = null;
	      try
	      {
	        client = server.accept();
	        handleConnection ( client );
	      }
	      catch ( IOException e ) {
	        e.printStackTrace();
	      }
	      finally {
	        if ( client != null )
	          try { client.close(); } catch ( IOException e ) { e.printStackTrace(); }
	      }
	    }
	  }
	  private void handleConnection( Socket client ) throws IOException
	  {
		    OutputStream out = client.getOutputStream();
		
	    try 
	    { 
	          b = 0;
	          File f = new File("C:/datei.exe"); 

	          FileInputStream fis = new FileInputStream(f); 
	          BufferedInputStream bis = new BufferedInputStream(fis); 
	          dis = new DataInputStream(bis);
	          
	          while ( b != -1 ) 
	          { 
	              
	               b = dis.read(schreib);
	         	  
	               out.write(schreib);
	               
	               out.flush();

	            }
	    }
	    
	    
	    catch (IOException e) 
	    { 
	       System.out.println("IO Excpetion: " + e.getMessage()); 
	    }
	    
	    finally
	    { 
	       if (dis != null)
	      { 
	    	   
	    	   try 
	    	   {
	    		   dis.close(); 
	    	   } 
	      
	    	   catch (IOException ioe)
	    	   {
	    	   }
	      
	       } 
	    }
	   
	  }
	
	  
	public static void main(String[] args) throws IOException {
		
		FileTransferServer server = new FileTransferServer( 3141 );
	    server.startServing();

	}

}
```


CLIENT:

```
import java.net.*;
import java.io.*;

class Client
{
  public static void main( String[] args )
  {
    int b=0;
    File nf = new File("D:/datei.exe");
    DataOutputStream dos;
    Socket server = null;
    byte[] les = new byte[1024];
    
    try
    {
    	
      InetAddress adresse = InetAddress.getByName("localhost");
    		
      server = new Socket(adresse , 3141 );
      InputStream in = server.getInputStream();
           
      FileOutputStream fos = new FileOutputStream(nf);
      BufferedOutputStream bos = new BufferedOutputStream(fos);
      dos = new DataOutputStream(bos);
      
while ( b != -1 ) { 
    	  
    	  b = in.read(les);
    	  
          dos.write(les);
          dos.flush();          

       }
      
    }
    catch ( UnknownHostException e ) {
      e.printStackTrace();
    }
    catch ( IOException e ) {
      e.printStackTrace();
    }
    finally
    {
      if ( server != null )
        try { server.close(); } catch ( IOException e ) { e.printStackTrace(); }
    }
  }
}
```


----------



## SlaterB (2. Nov 2007)

das Array ist ok, aber wenn es nicht voll gefüllt ist,
dann schreibe nur soviel davon wie gefüllt ist,
(sowohl beim Client als auch beim Servert)

die Information steckt in b


void write(byte[] b, int off, int len) 
          Writes len bytes from the specified byte array starting at offset off to this output stream.


----------



## Guest (2. Nov 2007)

Das hilft mir leider noch nicht so richtig weiter.
Kann mir jemand ein kleines Beispiel dazu geben?


```
while ( b != -1 ) { 
    	  
    	  b = in.read(les);
    	  
    	  if(b != 1024)
    	  {
    		  ??? 
    	  }
    	  
          dos.write(les, 0, b);
          dos.flush();

       }
      

    }
```

Wie genau krieg ich denn jetzt raus, wieviele von den 1024 gefüllt sind und wie schreibe ich das dann in einen neuen Buffer mit der entsprechenden Größe?


----------



## SlaterB (2. Nov 2007)

einfach nur 
b = in.read(les); 
dos.write(les, 0, b); 


wenn am Ende nur noch 400 Daten da sind,
dann ist das Array zu 400 Bytes richtig und zu 624 Bytes mit alten Daten gefüllt,
b ist 400 und dos.write(les, 0, b); schreibt genau die verbleibenden 400 Daten,

evtl. solltest du noch abfangen, ob b genau in diesem Moment -1 ist,
aber wahrscheinlich kommt dos.write(les, 0, b);  auch mit b = -1 klar (testen!)


----------



## Guest (2. Nov 2007)

Aber wie schneide ich die 624 Bytes alte Daten ab?


----------



## SlaterB (2. Nov 2007)

das musst du doch nicht 

> void write(byte[] b, int off, int len) 
> Writes len bytes from the specified byte array starting at offset off to this output stream.

wenn len nur 400 ist, dann wird der hintere Teil des Arrays ignoriert


----------



## Guest (2. Nov 2007)

Aber die Datei scheint nicht richtig übertragen zu werden, weil ich sie nach der Übertragung nicht mehr ausführen kann. Hast Du eine Ahnung woran das dann liegt? Irgendwo muss doch dann im Code noch was falsch sein.


----------



## Guest (2. Nov 2007)

Die empfangene Datei ist immer größer als die gesendete Datei. Kann mir jemand sagen woran das liegt und wie ich das korrigieren kann?


----------



## SlaterB (2. Nov 2007)

wie gesagt muss du das sowohl beim Client als auch beim Server machen,
bei beiden werden Arrays befüllt und weitergereicht,

und wenns noch nicht hilft, dann fängt das Debugging an,
verwende ein Array der Länge 3, eine Datei der Länge 5 mit 5 unterschiedlichen Bytes/ chars 0, 1, 2, 3, 4

und dann schaue an allen Stellen der Übertragung was jeweils aus Sockets gelesen oder geschrieben wird,
die Array-Inhalte,
wie sieht die Finaldatei genau aus usw.

nur fragend davorstehen hat noch kein Problem gelöst  :bae:


----------



## Guest (2. Nov 2007)

Ok, ich hab's geschafft. Die Datei wird richtig übertragen, aber ich bekomme trotzdem noch einige Fehlermeldungen ausgespuckt, mit denen ich nicht viel anfangen kann...

Beim Server:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException
	at java.net.SocketOutputStream.socketWrite(Unknown Source)
	at java.net.SocketOutputStream.write(Unknown Source)
	at FileTransferServer.handleConnection(FileTransferServer.java:61)
	at FileTransferServer.startServing(FileTransferServer.java:32)
	at FileTransferServer.main(FileTransferServer.java:97)


Beim Client:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException
	at java.lang.System.arraycopy(Native Method)
	at java.io.BufferedOutputStream.write(Unknown Source)
	at java.io.DataOutputStream.write(Unknown Source)
	at Client.main(FileTransferClient.java:30)


Kann das jemand für mich interpretieren?


----------



## SlaterB (2. Nov 2007)

wie kann gleichzeitig eine Exception auftreten sowie die Datei korrekt übertragen werden?

schreibe an die jeweilige Stelle eine Debug-Ausgabe, welche Ausgabe kommt zuletzt vor der Exception?

System.out.println("schreibe Array der Länge x, mit b = b");
dos.write(les, 0, b);
System.out.println("Schreiben erfolgreich, Array der Länge x, mit b = b");


----------



## Guest (2. Nov 2007)

Hab ich gemacht...

Er schreibt jetzt zig mal das gleiche und nur in der Mitte irgendwo das hier...

Werd ich nicht schlau draus...


...vorher immer erfolgreich...

Schreiben erfolgreich, Array der Länge x, mit b = b
schreibe Array der Länge x, mit b = b
Schreiben erfolgreich, Array der Länge x, mit b = b
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException
	at java.lang.System.arraycopy(Native Method)
	at java.io.BufferedOutputStream.write(Unknown Source)
	at java.io.DataOutputStream.write(Unknown Source)
	at Client.main(FileTransferClient.java:30)
schreibe Array der Länge x, mit b = b
Schreiben erfolgreich, Array der Länge x, mit b = b
schreibe Array der Länge x, mit b = b
Schreiben erfolgreich, Array der Länge x, mit b = b


...nachher immer erfolgreich...


----------



## SlaterB (2. Nov 2007)

fange die Exception mit try catch ab und beende das Programm an dieser Stelle, und zu erkennen, wann genau es passiert:
System.out.println("ArrayIndexOutOfBoundsException ");
System.exit(0);

und du sollst keinen festen String ausgeben (was bringt das denn?  )
sondern die aktuelle Länge des Arrays und von b


----------



## Guest (2. Nov 2007)

Ok, beim Server endet das ganze jetzt so:

schreibe Array der Länge [B@7c6768 , mit b = 1024
Schreiben erfolgreich, Array der Länge 1024, mit b = [B@7c6768
schreibe Array der Länge [B@7c6768 , mit b = 1024
Schreiben erfolgreich, Array der Länge 1024, mit b = [B@7c6768
schreibe Array der Länge [B@7c6768 , mit b = 847
Schreiben erfolgreich, Array der Länge 847, mit b = [B@7c6768
schreibe Array der Länge [B@7c6768 , mit b = -1
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException
	at java.net.SocketOutputStream.socketWrite(Unknown Source)
	at java.net.SocketOutputStream.write(Unknown Source)
	at FileTransferServer.handleConnection(FileTransferServer.java:61)
	at FileTransferServer.startServing(FileTransferServer.java:32)
	at FileTransferServer.main(FileTransferServer.java:97)


Das würde bedeuten, dass er ein Problem mit der -1 hat, oder lieg ich da falsch?


----------



## Guest (2. Nov 2007)

Oh, ich hab die Variablen da oben verdreht...


----------



## SlaterB (2. Nov 2007)

und bei -1 musst du ja nicht mehr unbedingt schreiben,
also leicht zu lösen

die Länge eines Arrays bekommt man übrigens mit array.length


----------



## Guest (2. Nov 2007)

Ich habe ja in meinem Quelltext stehen " while (b !=1) ".
Warum führt der das dann trotzdem nochmal aus?


----------



## Guest (2. Nov 2007)

Hat sich schon erledigt. Hab noch eine if-Verzweigung wegen dem -1 eingebaut und jetzt geht's. 
Vielen Dank für Deine Hilfe und Deine Geduld.


----------



## SlaterB (2. Nov 2007)

.........



while ( b != -1 ) // hier b ganz bestimmt nicht -1
             { 

                  b = dis.read(schreib); // hier b vielleicht -1

write(array,0,b); // wer soll bitte verhindern, dass b hier -1 ist?
}


einmal nachdenken sollte doch drin sein


----------



## Guest (2. Nov 2007)

Ja, hab ich dann auch gesehen. War ne blöde Frage. Also es geht jetzt. Vieeelen Dank.


----------

