tach auch.
Ich versuche gerade eine Datei von einem Client Socket zu einer ServerSocket zu verschicken. Nach anfänglichen Problemen kommen kleinere Dateien korrekt auf der anderen Seite an. (Versuche mit 50k und 1,2 MB) Bei einer Datei mit 4,6MB versagt allerdings die Kommunikation. Ab einer bestimmten Dateiposition kommt nur noch Müll an.
Client
fStream ist ein FileInputStream und hinter c verbingt sich im Grunde genommen ein DataOutputStream. oStream ist eine Datei die ich als Kontrolle verwende. Diese Kontrolldatei ist in Ordnung.
try
{
byte[]buffer=new byte[1024];
int anz=0;
long sum=0;
while(anz!=-1)
{
anz=fStream.read(buffer);
if(anz!=-1)
{
sum+=anz;
c.send(buffer,anz);
oStream.write(buffer,0,anz);
}
}
System.out.println("Gesamt gesendet:"+sum);
}
catch(IOException e)
{
//c.send(buffer);
e.printStackTrace();
}
Server
Auf Serverseite habe ich folgendes Versucht. Das Ergebnis von getInputStream() ist ein DataInputStream
log("Dateiname:"+fullFile);
log("Dateigroesse:"+size);
try
{
FileOutputStream ausgabe=new FileOutputStream(fullFile);
byte[]buffer=new byte[maxBufferSize];
while(size\>maxBufferSize)
{
getInputStream().read(buffer);
ausgabe.write(buffer);
ausgabe.flush();
size-=maxBufferSize;
}
getInputStream().read(buffer, 0, (int)size);
ausgabe.write(buffer,0,(int)size);
ausgabe.flush();
ausgabe.close();
}
catch(FileNotFoundException noFile)
{
log("konnte Datei nicht schreiben");
log(noFile.getMessage());
}
catch(IOException rw)
{
}
Wie gesagt. Bei kleineren Dateien funzt das, bei der Großen nicht. Die Dateigröße der geschriebenen Datei passt allerdings aufs Byte genau mit der Originaldatei überein.
Für jede Idee dankbar.
Gruss
Jens
Moin
Ab einer bestimmten
Dateiposition kommt nur noch Müll an.
> byte[]buffer=new byte[1024];
> int anz=0;
(....)
> c.send(buffer,anz);
Da gehört ein "c.flush ()" rein.
(... serverside ...)
> FileOutputStream ausgabe=new FileOutputStream(fullFile);
>
> byte[]buffer=new byte[maxBufferSize];
das sollte maxBufferSize = 1024 gelten, damit's Sinn macht. (Je kleiner du das hier wählst desdo länger fählt der Bug den du verbaut hast nicht auf)
> while(size\>maxBufferSize)
sehr schlechter Styl.
> {
> getInputStream().read(buffer);
der macht den Buffer nicht unbedingt ganz voll, das solltest du abfangen.
> ausgabe.write(buffer);
Der Buffer war u.U. nicht ganz voll, du schreibst ihn aber komplet in die Datei. =\> Überreste des letzten Buffers könnten nochmal geschrieben werden.
> ausgabe.flush();
GUT.
> getInputStream().read(buffer, 0, (int)size);
> ausgabe.write(buffer,0,(int)size);
> ausgabe.flush();
> ausgabe.close();
das ist nicht nötig wenn du die Buffer-grösse richtig setzts.
Wie gesagt. Bei kleineren Dateien funzt das, bei der Großen
nicht.
Bei kleinen reicht der TCP/IP-Buffer bei grossen nicht.
Die Dateigröße der geschriebenen Datei passt allerdings
aufs Byte genau mit der Originaldatei überein.
bei der while-Schleife muss sie ja passen.
Für jede Idee dankbar.
-
check die Grösse des Buffers auf der Server-seite.
-
Mit DataInput/OutputStream könntest du die Grösse der Datei vor der eigentlichen Datei mit writeInt (int i) und readInt(int i) verschicken.
-
Benutz niemals einen Stream ohne BufferedInput /BufferedOutputStream (z.b. DataInputStream DI = new DataInputStream (new BufferedInputStream (new FileInputStream (File))) sieht komisch aus, ist aber besser) (und benutz nie FileInput oder FileOutputstream’s direkt, das ist das langsamste was java zu bieten hat)
viel Glück.
Hi pumpkin
[…]
c.send(buffer,anz);
Da gehört ein „c.flush ()“ rein.
In der Methode send von c ist das flush schon mit drin. Trotzdem danke.
(… serverside …)
FileOutputStream ausgabe=new FileOutputStream(fullFile);
byte[]buffer=new byte[maxBufferSize];
das sollte maxBufferSize = 1024 gelten, damit’s Sinn macht.
(Je kleiner du das hier wählst desdo länger fählt der Bug den
du verbaut hast nicht auf)
OK. Werde ich ausprobieren…
[…]
2. Mit DataInput/OutputStream könntest du die Grösse der Datei
vor der eigentlichen Datei mit writeInt (int i) und
readInt(int i) verschicken.
Die korrekte Dateigröße hab ich schon. Das ist ja nicht das Problem.
- Benutz niemals einen Stream ohne BufferedInput
/BufferedOutputStream (z.b. DataInputStream DI = new
DataInputStream (new BufferedInputStream (new FileInputStream
(File))) sieht komisch aus, ist aber besser) (und benutz nie
FileInput oder FileOutputstream’s direkt, das ist das
langsamste was java zu bieten hat)
OK. Ich werde das mal Puffer.
Ein Problem bei deiner while schleife ist, dass du erwartest das die Datei das letzte ist, was von dem Stream rein kommt. Allerdings ist die Datei nur eine von vielen und über den Stream kommen auch noch andere Daten (müssen nicht zwangläufig Dateien sein). Deswegen hatte ich den „schlechten Stil“ programmiert.
Kann ich den Streams direkt sagen hole x Byte vom InputStream und schreib den direkt in die Datei rein? Funzt das dann auch bei langsamen Verbindungen?
Gruss Jens
Gruss Jens
Moin
Ein Problem bei deiner while schleife ist, dass du erwartest
das die Datei das letzte ist, was von dem Stream rein kommt.
Das ist ziemlich egal, hast du den Fehler mit dem nicht gefüllten Buffer gefunden ?
Allerdings ist die Datei nur eine von vielen und über den
Stream kommen auch noch andere Daten (müssen nicht zwangläufig
Dateien sein). Deswegen hatte ich den „schlechten Stil“
programmiert.
ack.
Kann ich den Streams direkt sagen hole x Byte vom InputStream
und schreib den direkt in die Datei rein?
Du kanns mit gzip-Stream da etwas sehr lustiges bauen, was allerdings programmier-fehleranfällig ist und nicht automatisch abläuft. Man bestimmt was rüberkommen soll (Dateiname, Anzahl der Dateien) und benutzt dann einen GZIPOutputStream zum senden jeder einzelnen Datei und einen GZIPInputStream zum empfangen. Wenn der InputStream nichts mehr von sich gibt und noch eine Datei ankommen soll erzeugt man einen neuden GZIPInputStream, und saugt den leer,… (siehe java.util.zip)
Das spart Bandbreite und man muss nicht wissen wie lang die Dateien sind, weil der ZIP-Stream aufhört wenn die Datei zu ende ist. Es erhöht allerdings die Latenz.
cu
1 „Gefällt mir“
tach
Ich hatte erst jetzt die Möglichkeit/Ruhe wieder daran zu basteln. Auf der Serverseite habe ich die Puffergröße auf 1024 gesetzt und dein wildes Konstrukt mit den 3 Streams eingebaut.
und Schwups tut alles. Ich war sogar so waghalsig und hab 'ne 90MB-Datei verschubst. Auch die kommt so an wie soll. Danke.
Die Sache mit dem ZIP muß ich später mal versuchen…
Gruss Jens
ps: Wen’s interessiert, es war dafür:
http://software.nigjo.de/pov-ic/
Moin
und Schwups tut alles. Ich war sogar so waghalsig und hab 'ne
90MB-Datei verschubst. Auch die kommt so an wie soll. Danke.
tests nicht nur mit grossen Dateien, verschick was von Floppy zu Platte und von Platte zu Floppy. (mein Standart-Buffer-test…)
Die Sache mit dem ZIP muß ich später mal versuchen…
wenn du mit POV arbeitets:
-
zip die scenen-Dateien. Selbst in der niedigsten zip-Einstellung kommt da ein Faktor 2 raus. Zip sie aber nicht „on-the-fly“ da sonst der Server bei grösseren Clustern zusammenbricht. (=> verteilte Server (einen für Bilder, einen für scene-Dateien) und „on-demand“ Filetransfers (die POV-Dateien sind relativ einfach zu parsen))
-
Zip die Bilder nicht. Daran rechned sich der Server tot und es bringt gar nichts.
-
kuck dir mal den MD5-Generator von java an, der hilft wenns um einen „quick&dirty“ update von Dateien zwischen Rechnern. (Beim Empfang der Datei mitlaufen lassen, wenn der Server neue hat kann er einen Satz MD5’s verschicken, ist schneller als immer die gesamten Dateien auszutauschen)
ps: Wen’s interessiert, es war dafür:
http://software.nigjo.de/pov-ic/
hab nur kurz drüber gelesen, sieht gut aus. (hab mal was ähnliches gebaut)
cu