Kadaj Geschrieben 1. Dezember 2012 Teilen Geschrieben 1. Dezember 2012 Hallo, ich versuche grade eine Datei stückchenweise in ein byte-array einzulesen und in eine andere Datei zu schreiben. Das funktioniert aber nur, wenn die Datei bis 1024 Byte groß ist, muss das Programm sie zerlegen, dann ist sie unbrauchbar. Hier der Code dazu: FileInputStream fis = new FileInputStream(args[2]); byte[] DataBytes = new byte[1024]; // Bytes für die Daten int PacketNum = 0, NumCounter=1; PacketNum = (int)filesize/1024; if( filesize%1024 != 0 ) PacketNum++; int Lastsize = (int)filesize%1024; FileOutputStream fos = new FileOutputStream("clienttest"); for(; NumCounter <= PacketNum;NumCounter++ ){ while( fis.read( DataBytes ) != -1 ){} if( NumCounter == PacketNum ) fos.write(DataBytes, 0, Lastsize); else fos.write(DataBytes); } [/PHP] Und so sieht der Inhalt der Datei aus, die ich zum testen angebe: [code] start Ich bin ein Text Das sind 1024 Byte Ich bin ein Text Das sind 2048 Byte und noch ein wenig... end [/code] Das ist die Kopie: [code] und noch ein wenig... end Das sind 2048 Byte und noch ein wenig... end Das sind 2048 Byte und noch ein wenig... end [/code] Ich kann mir absolut nicht erklären wie das zustande kommt. Hat jemand von euch einen Durchblick? Gruß Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
R1I9C8H5I Geschrieben 1. Dezember 2012 Teilen Geschrieben 1. Dezember 2012 Naja... die 1024 steckt in deinem Code, habe den jetzt nicht genau nachvollzogen, aber mit Sicherheit machst du da an einer Stelle einen Fehler... debug das Ding doch mal, dann wird es dir mit Sicherheit nach einiger Zeit auffallen. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Kadaj Geschrieben 1. Dezember 2012 Autor Teilen Geschrieben 1. Dezember 2012 Seh ich denn beim debug was in der datei passiert? Ich weiß leider ohnehin nicht wie ich das unter fedora-eclipse mache :/ Jedenfalls hab ich Beispiel im Netz gefunden und mein Fehler ist hier: //while( fis.read( DataBytes ) != -1 ){} fis.read( DataBytes ); [/PHP] Ich dachte es wird immer nur ein byte beim Aufruf in das byte geschrieben und -1 wird zurückgegeben, wenn das byte-array voll ist. Aber das byte wird gleich vollgeschrieben und -1 wird zurückgegeben, wenn das Dateiende erreicht wurde. Das habe ich an der Stelle wohl damit verwechselt: [PHP] int c; while ((c = in.read()) != -1) { ... Jedenfalls wird die Kopie jetzt fehlerfrei kopiert. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
R1I9C8H5I Geschrieben 2. Dezember 2012 Teilen Geschrieben 2. Dezember 2012 Super. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Gast runtimeterror Geschrieben 2. Dezember 2012 Teilen Geschrieben 2. Dezember 2012 Hier noch mein üblicher Senf dazu while( fis.read( DataBytes ) != -1 ){} Das ist gefährlich, da du nicht wissen kannst, wie viele Bytes gelesen wurden. Wenn z.B. nur 100 Bytes gelesen wurden, dann schreibt der später dennoch die vollen 1024 bytes ins Ziel. Man sollte immer den Rückgabewert der read-Methode auslesen und diesen für den späteren zugriff auf den Buffer verwenden. Und noch ein kleiner Verbesserungsvorschlag: PacketNum = (int)filesize/1024; if( filesize%1024 != 0 ) PacketNum++; Geht kürzer: final int BUFFER_SIZE = 1024; PacketNum = (filesize + BUFFER_SIZE - 1) / BUFFER_SIZE Mit dem Trick funktioniert das Aufrunden wie gewünscht. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Kadaj Geschrieben 2. Dezember 2012 Autor Teilen Geschrieben 2. Dezember 2012 Das ist gefährlich, da du nicht wissen kannst, wie viele Bytes gelesen wurden. Wenn z.B. nur 100 Bytes gelesen wurden, dann schreibt der später dennoch die vollen 1024 bytes ins Ziel. Man sollte immer den Rückgabewert der read-Methode auslesen und diesen für den späteren zugriff auf den Buffer verwenden. Ja, das ist mir auch aufgefallen. Ich hatte mich anfangs gewundert, dass die Dateien viel größer sind, bis mir bei der Textdatei aufgefallen ist, dass noch Nullen am Ende stehen. Ich hab es dann so gelöst, dass mein Client und mein Server anhand der Dateigröße im ersten Paket einfach berechnen wie viele bytes sie einlesen müssen. Geht kürzer: final int BUFFER_SIZE = 1024; PacketNum = (filesize + BUFFER_SIZE - 1) / BUFFER_SIZE Mit dem Trick funktioniert das Aufrunden wie gewünscht. Gut zu wissen, danke Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Gast runtimeterror Geschrieben 2. Dezember 2012 Teilen Geschrieben 2. Dezember 2012 Ich weiß nicht, ob du mich richtig verstanden hast: Jeder read()-Aufruf kann eine zufällige Anzahl an Bytes einlesen. Das heißt vom buffer sind immer nur die ersten n Bytes korrekt. Der Rest ist Müll. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Kadaj Geschrieben 2. Dezember 2012 Autor Teilen Geschrieben 2. Dezember 2012 Kann das passieren? Also bei mir funktioniert es sowohl mit Bildern als auch mit mp3-Dateien von einem Rechner zum anderen. Laut doc auf oracle.com: read(byte[] Reads up to b.length bytes of data from this input stream into an array of bytes. Vielleicht passiert das, wenn man im Laufe des Quellcodes diesem Array mal ein anderes zuweist mit "=", dann verändert sich nämlich auch dessen Größe. Anders könnte ich mir das nicht erklären Gruß Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Gast runtimeterror Geschrieben 2. Dezember 2012 Teilen Geschrieben 2. Dezember 2012 Steht eigentlich da: "Reads up to b.length bytes" = "liest bis zu b.length Bytes" Siehe auch: InputStream (Java Platform SE 7 )[]%29 "The number of bytes read is, at most, equal to the length of b." (Die Forensoftware macht den Link kaputt:) http://docs.oracle.com/javase/7/docs/api/java/io/InputStream.html#read%28byte[]%29 Falls dein Eingabemedium langsamer ist (Modem, Serielle Schnittstelle, Tastatur, Temperatursensor, ...) dann liefert die Methode u.U. nur so viele Bytes, wie das Eingabegerät gerade ohne nennenswerte Verzögerung liefern kann. Bin beim Implementieren eines HTTP-Stacks damit mal böse auf die Schnauze gefallen. Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Gast runtimeterror Geschrieben 2. Dezember 2012 Teilen Geschrieben 2. Dezember 2012 Hier mal ein (ungetestetes) Beispiel in dem zunächst alle Bytes in einen Puffer eingelesen werden und dann geschrieben werden: final int bytesExpected = 1234; final byte[] buffer = new byte[bytesExpected]; int bufferOffset = 0; while (bufferOffset < buffer.length) { final int bytesRead = in.read(buffer, bufferOffset, buffer.length - bufferOffset); if (bytesRead == -1) throw new Error("Zu wenig Eingabedaten"); bufferOffset += bytesRead; } out.write(buffer); Und hier die (ebenfalls ungetestete) performante und latenzarme Variante, welche den Stream mit einem kleinen Buffer kopiert: final int bytesExpected = 12345; final int BUFFER_SIZE = 4096; final byte[] buffer = new byte[BUFFER_SIZE]; // Anzahl bislang gelesener Bytes int byteCount = 0; while (byteCount < bytesExpected) { // Nicht mehr Bytes lesen, als in den Buffer passen (buffer.length) // Nicht mehr Bytes lesen, als noch benötigt (bytesExpected - byteCount) final int bytesRead = in.read(buffer, 0, Math.min(buffer.length, bytesExpected - byteCount)); if (bytesRead == -1) throw new Error("Zu wenig Eingabedaten"); // Nur so viele Bytes schreiben, wie zuvor gelesen wurden out.write(buffer, 0, bytesRead); byteCount += bytesRead; } Zitieren Link zu diesem Kommentar Auf anderen Seiten teilen Mehr Optionen zum Teilen...
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.