Dateien über Sockets problem

Stefan852

Grünschnabel
Hallo,

Ich habe ein kleines Problem beim übertragen von Dateien über Sockets und würde mich freuen wenn ihr mir helfen könntet:

Mein Code zum Senden:
Java:
long fileSize = file.length();
int stepSize = 200000;
long completed = 0;
byte[] buffer = new byte[stepSize];
FileInputStream fis = new FileInputStream(file);
while(completed<=fileSize){
fis.read(buffer);
objectWriter.write(buffer);
completed+=stepSize;
}
objectWriter.flush();
Die variable objectWriter ist ein ObjectOutputStream, das File file wird übergeben

Mein Code zum Empfangen:
Java:
long completed = 0;
int stepSize = 320000;
        byte[] buffer = new byte[stepSize];
        try {
            FileOutputStream fos = new FileOutputStream(fileName);
        while(completed<=fileSize){
            ois.read(buffer);
            fos.write(buffer);
            completed+=stepSize;
        }
        fos.close();
            System.out.println("Completed\n");
        } catch (Exception ex) {
            System.out.println(ex);
        }
ois ist ein ObjectInputStream

Problembeschreibung:
Textdateien kann ich ohne Probleme übertragen, die Datei ist vollständig und unbeschädigt
Wenn ich allerdings versuche ein Bild zu übertragen ist die Datei beschädigt und ich kann sie nicht öffnen.

Info:
Ich verwende den ObjectStreams weil ich auch SerialisierteObjekte über den selben Socket sende.

Ich würde mich über eure Hilfe freuen
Stefan
 
Moin,

wenn ich mich recht erinnere (ist schon länger her, dass ich an sowas mal dran war) darfst Du keinen FILE...Stream nehmen!

Versuch es mal mit "DataInputStream" resp. "DataOutputStream" !

Gruß
Klaus
 
Hi.

Erstmal, die File{In,Out}putStream sind völlig OK.

Aber das kann so nicht funktionieren.

1. Du liest n Bytes von der Datei ein und speicherst diese Daten in "buffer". Nur, wieviel Bytes wurden denn eingelesen? Der Buffer ist in jedem Fall 200000 Bytes groß, die Dateigröße ist aber in den seltensten Fällen ein Vielfaches von 200000.

2. Du sendest den 200000 Byte großen Buffer zum Empfänger. Einerseits ist das Verschwendung: wenn die Datei nur wenige Byte groß ist sendest du mind. 200000 Bytes. Außerdem kennt der Empfänger wieder nicht die Anzahl der Bytes die von dem empfangenen Buffer in die Datei geschrieben werden müssen.

Du mußt dir also merken wieviel Daten du per read liest. Und du mußt die Information wie groß die Datei ist auch an den Empfänger übermitteln.
 
Ich würde es so machen
Server
Java:
BufferedInputStream bb=new BufferedInputStream(new FileInputStream(f)); //InputStream vom File erstellen
ous.writeObject((int)f.length()); //Größe auslesen und an Client übertragen
byte[]file=new byte[(int) f.length()]; 
bb.read(file); // File in byte array speichern
ous.writeObject(file); //Array an Client senden
bb.flush(); //Stream flushen und schließen
bb.close();

Client
Java:
int length = (int) ois.readObject(); //Länge empfangen
BufferedOutputStream fw = new BufferedOutputStream(new FileOutputStream(new File("Filename"))); //OutputStream zum File schreiben erstellen
byte[] file = new byte[length]; 
file = (byte[]) ois.readObject(); //Daten lesen
fw.write(file); //Daten speichern
fw.flush();
fw.close();

Lg hendl
 
Seine bisherigen Versuche waren Textdateien oder Bilder die eigentlich nicht so groß sein sollten.
 
Hallo :)

Danke für die Antworten!
Ich habe aber leider immer noch ein Problem bei dem ich mich über eure Hilfe freuen würde:
Meine bisherige Lösung sieht so aus:
Kleinere Dateien werden komplett eingelesen und auf einmal versendet. <-- Funktioniert ohne Probleme
Bei größeren also ab ein paar GB funktioniert das nicht mehr deshalb splitte ich die Datei auf (part-größe ist dynamisch).
Das auslesen der Parts funktioniert allerdings habe ich ein Problem beim empfangen. Es werden immer die korrekten Parts gesendet allerdings sieht es so aus als ob ich immer nur das erste empfangen würde.
Hier habe ich einen kleinen Teil der Ausgabe (SEND: <-- was ich sende; REC: <-- was ich empfange (serverseitig)):
Der letzte Wert ist das erste Byte im Array

SEND: PartNumber: 0 | PartLength: 200000 | Anzahl der Parts: 32666 | 26
REC: PartNumber: 0 | PartLength: 200000 | Anzahl der Parts: 32666 | 26
SEND: PartNumber: 1 | PartLength: 200000 | Anzahl der Parts: 32666 | 0
SEND: PartNumber: 2 | PartLength: 200000 | Anzahl der Parts: 32666 | 6
REC: PartNumber: 0 | PartLength: 200000 | Anzahl der Parts: 32666 | 26
REC: PartNumber: 0 | PartLength: 200000 | Anzahl der Parts: 32666 | 26
SEND: PartNumber: 3 | PartLength: 200000 | Anzahl der Parts: 32666 | 12
REC: PartNumber: 0 | PartLength: 200000 | Anzahl der Parts: 32666 | 26
SEND: PartNumber: 4 | PartLength: 200000 | Anzahl der Parts: 32666 | 127
REC: PartNumber: 0 | PartLength: 200000 | Anzahl der Parts: 32666 | 26
SEND: PartNumber: 5 | PartLength: 200000 | Anzahl der Parts: 32666 | -120
REC: PartNumber: 0 | PartLength: 200000 | Anzahl der Parts: 32666 | 26
SEND: PartNumber: 6 | PartLength: 200000 | Anzahl der Parts: 32666 | 20
REC: PartNumber: 0 | PartLength: 200000 | Anzahl der Parts: 32666 | 26
SEND: PartNumber: 7 | PartLength: 200000 | Anzahl der Parts: 32666 | -128
REC: PartNumber: 0 | PartLength: 200000 | Anzahl der Parts: 32666 | 26
SEND: PartNumber: 8 | PartLength: 200000 | Anzahl der Parts: 32666 | 34
REC: PartNumber: 0 | PartLength: 200000 | Anzahl der Parts: 32666 | 26
SEND: PartNumber: 9 | PartLength: 200000 | Anzahl der Parts: 32666 | -67
REC: PartNumber: 0 | PartLength: 200000 | Anzahl der Parts: 32666 | 26
SEND: PartNumber: 10 | PartLength: 200000 | Anzahl der Parts: 32666 | -101
REC: PartNumber: 0 | PartLength: 200000 | Anzahl der Parts: 32666 | 26

Man sieht dass ich immer nur das erste empfange obwohl ich andere Versende.
Wo liegt dieses Problem bzw wie kann ich dieses Problem lösen?

Lg Stefan852
 
Hallo,

versuch mal, nachdem du die Daten versendet hast, deinen Output-Stream zu resetten (reset()).

Gruß,
Wolf
 
Ist vielleicht etwas off-topic, aber mich würde interessieren, warum es bei den Java-Sockets dieses Verhalten gibt, dass man einen Reset duchführen muss, bzw. warum sich die Stream den Status bereits geschriebener Objekte merken und dann keine neue Daten schicken wenn die Objekt-Referenz sich nicht ändert? Mir hat sich bisher der Sinn dahinter noch nicht so erschlossen.

Gruß,
Wolf
 
Zurück