Datei in mehrere kleine Dateien umwandeln

ocsme

Top Contributor
Hallo zusammen,
ich versuche eine Aufgabe zu lösen die Aufgabe ist folgende:

Filesplit
Möchte man eine große Datei auf Diskette kopieren, dann besteht bei Dateien über 1,44 MB ein Problem. Man könnte dann aus einer großen Datei mehrere kleine "diskettenkompatible" machen. Schreibe für das Problem ein Programm, welches sich etwa so auf der Kommandozeile aufrufen lässt:
$ java Filesplit Datei.exe
Ist zum Beispiel die Datei 2,44 MiB groß, dann wird das Programm daraus die Dateien Datei.exe.1 und Datei.exe.2 mit den Größen 1,44 MiB und 1 MiB machen.

Derzeit zerbreche ich mir leider noch den Kopf wie ich es hin bekomme!
Bitte kommt jetzt nicht mit Kommentaren wie denk weiter drüber nach :p <- destruktive Kommentare bekomme ich schon genug von anderen :(

Es ist noch beim Konzept. Meine Frage in erster Linie, ist wie bekomme ich die Größe hin also wie hier z. B. auf 1,44 Mib?
Wollte da erst eine Methode schreiben die mir eine Anzahl an Schleifen Durchläufe zurück gibt. Sprich ich Buffere den InputStream mit 4096 Bytes = 4 Kbyte dann rechne ich die 1,44 MByte/4 Kbyte und sollte sofern das Korrekt gerechnet ist auf 170,24 = 171 Durchläufe kommen.
Jetzt wollte ich das Programm aber nicht nur mit 1,44 MByte laufen lassen sondern die größe soll mit angegeben werden können :)
Wie bekomme ich das nun hin. Habe mir die File API auch angeschaut um die Metadatei auszulesen doch dort habe ich leider keine passende Methode gefunden oder ich bekomme es nicht zusammen. Denn was ich bräuchte wäre eine Methode die mir die Größe der Datei zurück geben würde dann könnte man das ganze vereinfachen :) man fragt bei jedem Durchlauf ist die Datei derzeit 1,44 Mib groß.

Wenn die Frage irgendwie zu doof ist dann "einfach" ignorieren Okay :)
Dann schau ich weiter. Doch ich sitze (schande über mich :D) schon seit 11:00 Uhr davor und bekomme es nicht zusammen.

Ich hoffe Ihr könnt mir Helfen :)

LG
 
K

kneitzel

Gast
Also Du hast doch schon einen guten Ansatz. Genau so solltest Du heran gehen.

Aber wichtig: Nicht aufrunden sondern abrunden. Wenn du genau 1,44 Mib Platz hast und du 171 Durchläufe zu 4Kbyte machst, dann bist Du ja drüber. Also da wirklich gut aufpassen!

Und du brauchst auch nicht wirklich die Größe der original Datei, denn Du kannst die Datei öffnen und immer wieder versuchen, deinen Buffer zu füllen. Du bekommst da in der Regel bei Binary Read Operationen zurück, wieviele Bytes gelesen wurden. Du führst die Schleife so lange durch, bis Du weniger als Deinen Block an Daten bekommst.

Und in dieser Schleife prüfst Du, der wievielte Durchgang es ist. Ist die Anzahl der gewünschten Blöcke erreicht, dann schließt Du die Ziel-Datei und öffnest die nächste Zieldatei. (Also z.B. ein <Original-Filename>.<Zähler>)

Also eigentlich relativ einfach. Ginge vom Code her noch einfacher, indem Du einen Block reservierst, der genau der Zielgröße entspricht. Dann hast Du weniger Abfragen und mit kleinen Zieldateien funktioniert es gut. Nur wenn Du dann eine Datei von 20TB in 4TB große Blöcke zerteilen willst, um diese Datei auf mehreren 4TB großen Platten zu transportieren, dann hast Du ein Problem :)
 

ocsme

Top Contributor
Aber wichtig: Nicht aufrunden sondern abrunden. Wenn du genau 1,44 Mib Platz hast und du 171 Durchläufe zu 4Kbyte machst, dann bist Du ja drüber. Also da wirklich gut aufpassen!
Das wäre das erste was ich schon verhauen hätte :D nicht nachgedacht.
Doch das nächste ist auch das umrechnen bzw. das rechnen wie oft die Schleifen laufen darf denn das brauch ich ja weiterhin.
Ich fülle den Buffer mit 4096 Bytes so und die Datei ist jetzt 20 MByte groß. Wie rechne ich das jetzt um.
Auf dem Papier geht das ja ganz Leicht mit 2er Potenzen :)
20 x M x Byte = 20 * 2(hoch 20) * 2(hoch 3)
4 x K x Byte = 2(hoch 2) * 2(hoch 10) * 2(hoch3)
dann kürzt man wild und erhält seinen Count :)
Wenn ich das jetzt aber Programmieren müsste wüsste ich ehrlich gesagt gerade überhaupt nicht wie :(

LG

moment geht das mit dem Objekt File dann die größe der Datei und das Teile ich einfach durch die größer es Buffer :) mal gleich nach schauen :p
 
Zuletzt bearbeitet:

Tarrew

Top Contributor
Du musst dir vorher nicht ausrechnen, wie oft deine Schleife laufen muss.
Nimm eine while-Schleife, die so lange 4kB-Blöcke aus der Eingabedatei ausliest, bis das Ende der Datei erreicht wurde.

Java:
        byte[] buffer;
        while ((buffer = deinFileInputStream.readNBytes(blockSize)).length != 0) {
            // schreibe Buffer in Teildatei
        }
 

ocsme

Top Contributor
Okay dann läuft die Schleife bis die Datei am ende ist :) das ist schon mal sehr schön.
Doch dann habe ich ja immer noch das Problem WANN FÄNGT DIE NEUE DATEI AN.
Ich müsste ja eine gewisse Dateigröße haben, also hier die 1,44 Mbyte und das durch die 4kByte teilen oder geht das auch anders?
Denn so zu rechnen ist irgenwie auch etwas umständlich finde ich das sind ja alles super große Zahlen geht das nicht leichter?
lg
 

Tarrew

Top Contributor
Wieso setzt du deine Blocksize nicht einfach auf 1,44 MB? Dann erzeugst du mit jedem Schreibvorgang eine neue Datei.
 

ocsme

Top Contributor
Ich soll also ein Array anlegen das 1,44 MB speichert diese dann lesen und im Hauptspeicher Buffern.
Dann werden die Bytes über die Schleife in eine neue Datei geschrieben habe ich das jetzt richtig verstanden.
Die Methode finde ich nur nicht readNBytes(...).
Desweiteren ist es ja okay für 1,44 MB aber was ist wenn es 2 GB wären? soll ich die in den Hauptspeicher auf einmal laden?
LG
 

Tarrew

Top Contributor
Die Methode gibts erst seit Java 9. Vermutlich hast du noch ein älteres JDK, kannst du aber ruhig mal updaten, wir sind schon bei Java 11 ;)

Bei der Aufgabenstellung ist es ja eher unwarscheinlich, dass du auf einmal eine Datei in mehrere 2GB-Dateien teilst, aber gut.
Wenn du deinen Buffer kleiner wählst, als die Zielgröße der Datei, dann musst du eben mitzählen wie viele Bytes du schon geschrieben hast.

Mit der Methode sollte das kein Problem sein:
https://docs.oracle.com/javase/8/docs/api/java/io/FileOutputStream.html#write-byte:A-int-int-

Wenn du mit dem Inhalt deines aktuellen Buffers beim Schreiben die Zielgröße erreichen würdest, schreibst du nicht den kompletten Buffer, sondern nur bis zu einer bestimmten Länge (dafür der len-Parameter). Den Rest des Buffers schreibst du dann in die neue Datei (offset-Parameter).

Musst halt nur immer aufsummieren, wie viele Bytes du schon in die aktuelle Datei geschrieben hast, dann weiß du auch, wie viele noch fehlen.
 

ocsme

Top Contributor
Das mit dem mit zählen der bytes hört sich glaube gut an :)
2GByte sind dann 2*2(hoch 30) Bytes. Soll ich das dann vorher berechnen? Mit der pow Funktion.
Ich tu mir bei der Aufgabe echt schwer wenn nicht schau ich morgen nochmal nach mit einem klaren kopf!
LG
 
K

kneitzel

Gast
Also wieso machst du es dir so kompliziert? Du kannst doch erst einmal als Parameter angeben lassen, wieviel KB jede einzelne Datei groß sein soll. Dann kann der Benutzer rechnen.

Also x KB bedeutet, dass du x mal 1024 Byte Blöcke in eine Datei schreiben willst.

Aber selbst wenn es andere Größen sein sollen, ist es doch einfach:
1MB = 1024 KB
1 GB = 1024 MB
Also einfach immer mal 1024 nehmen...
 

mihe7

Top Contributor
Du möchtest g Bytes lesen. Ein Puffer der Größe g ist im Allgemeinen zu groß, daher verwendest Du einen Puffer mit einer Größe p < g.

Bei jedem Lesevorgang
1. kannst Du angeben, wie viele Bytes höchstens gelesen werden sollen
2. wird zurückgegeben, wie viele Bytes tatsächlich gelesen wurden.

Du kannst also zu jeder Zeit angeben, wie viele Bytes noch zu lesen sind. Benennen wir diese Angabe mal mit r. Zu Beginn gilt natürlich r = g und in jeder Iteration verringert sich r um die Zahl der gelesenen Bytes. Du willst in jeder Iteration also so viel Bytes wie möglich lesen. Möglich ist in der Regel p, außer falls r < p gilt.

Wäre mal ein Ansatz.
 

ocsme

Top Contributor
Leider komme ich mit euren Vorschlägen überhaupt nicht wirklich weiter deswegen habe ich das versucht mit dem Rechnen doch da hänge ich jetzt auch :(

Hier mal mein bisheriger versuch:
Java:
package Insel;
import java.io.*;

public class Filesplit {
    public static long loopRuns(double splitLength, int bufferLength) {
        return (long) (splitLength/bufferLength);
    }
   
    public static void main(String...strings ) throws IOException {
        InputStream is = null;
        OutputStream os = null;
        try {
            File f = new File("/home/test");
            is = new FileInputStream("/home/test");
            byte[] buffer = new byte[4096];
            int countName = 0;
            int bufferLength = buffer.length;
            double splitLength = 1.33*1024*1024;        //1.33 M
            long runs = loopRuns(splitLength,bufferLength);
            String outputPath = "/home/a";
           
            System.out.println(f.length()+" "+buffer.length+" "+runs);
                       
            if(f.isFile()) {
                if(f.length() < buffer.length) {
                    os = new FileOutputStream(outputPath);
                    int b = is.read(buffer);
                    while (b != -1) {
                        os.write(buffer, 0, b);
                        b = is.read(buffer);
                    }
                }
                else {
                    countName++;
                    outputPath+=""+countName;
                    os = new FileOutputStream(outputPath);
                    int b = is.read(buffer);
                   
                }
            }
            else if(f.isDirectory()) {
                System.out.println("");
            }
                else throw new Exception("unknow error");
           
        }
        catch(IOException ex) {
            ex.getMessage();
        }
        catch(Exception ex) {
            ex.getMessage();
        }
        finally {
            if(is!=null)
                is.close();
            if(os!=null)
                os.close();
        }
   
       
       
    }

}


Ist die Datei kleiner als mein Buffer funktioniert es super :)
Wird die Datei größer und ich muss Sie aufteilen habe ich ein Problem. Nun sagen wir mal die Rechnung wäre Korrekt und ich komme bei einer Datei größe von 1,33 M / 4 K auf 340 Durchläufe.
Doch wie stelle ich fest wie viel noch über ist von der Datei, was ist wenn es gar nicht mehr 1,33 M sind und ich laufe dann 340 mal durch dann knallt es :(
Irgendwie bin ich hierfür einfach zu doof :( "andernfalls lasse ich es einfach ist ja nur mein Privat vergnügen :D"

LG


Last es gut sein bekomme es nicht hin.
 
Zuletzt bearbeitet:

ocsme

Top Contributor
so doch natürlich geht es nicht :D
Java:
package Insel;
import java.io.*;

public class Filesplit {
    public static long loopRuns(double splitLength, int bufferLength) {
        return (long) (splitLength/bufferLength);
    }
    
    public static void main(String...strings ) throws IOException {
        InputStream is = null;
        OutputStream os = null;
        try {
            File f = new File("/home/buch.pdf");
            is = new FileInputStream("/home/buch.pdf");
            byte[] buffer = new byte[4096];
            String outputPath = "/home/a";
            long fileSize = f.length();
            int countName = 0;
            int bufferLength = buffer.length;
            double splitLength = 1.33*1024*1024;        //1.33 M
            long runs = loopRuns(splitLength,bufferLength); //durchlauefe fuer eine 1.33 M grosse Datei
            long count = (int) (fileSize/splitLength);   
            if(f.isFile()) {
                if(f.length() < buffer.length) {
                    os = new FileOutputStream(outputPath);
                    int b = is.read(buffer);
                    while (b != -1) {
                        os.write(buffer, 0, b);
                        b = is.read(buffer);
                    }
                }
                else {
                    while (count > 0) {
                        countName++;
                        String tmp = outputPath + countName;
                        int runsTmp = runs;
                        os = new FileOutputStream(tmp);
                        int b = is.read(buffer);
                        while (runsTmp > 0) {
                            os.write(buffer, 0, b);
                            b = is.read(buffer);
                            runsTmp--;
                        }
                        count--;
                    }
                }
            }
            else if(f.isDirectory()) {
                System.out.println("");
            }
                else throw new Exception("unknow error");
            
        }
        catch(IOException ex) {
            ex.getMessage();
        }
        catch(Exception ex) {
            ex.getMessage();
        }
        finally {
            if(is!=null)
                is.close();
            if(os!=null)
                os.close();
        }
    
        
        
    }

}


Bekomme das nicht hin da ich keine Ahnung habe wie ich abfrage wieviele bytes ich schon habe :( naja
 

mihe7

Top Contributor
Ich dachte eher an so was (ungetestet)
Java:
void copyBytes(InputStream is, OutputStream os, int size) { 
    byte[] buf = new byte[4096]; // 4 KiB Buffer

    int remaining = size;
    int n;
    while (remaining > 0 && (n = is.read(buf, 0, Math.min(buf.length, remaining))) != -1) {
        os.write(buf, 0, n);
        remaining -= n;
    }
}
 

ocsme

Top Contributor
in die variable size kommt jetzt die Angabe wie groß die Datei sein soll.
Jetzt habe ich nur das nächste Problem wie verhält sich den der FileInputStream und FileOutputStream wenn man jetzt x MB von der Datei abzwickt also liest und schreibt. Macht der FileInputStream dann danach weiter?
Denn das ganze bräuchte man ja dann nur noch um eine Schleife zu legen die eben auch so lange läuft wie sie noch Daten hat oder sehe ich das Falsch?
 

mihe7

Top Contributor
Macht der FileInputStream dann danach weiter?
Natürlich, er wird ja nicht geschlossen. Du kannst also in copyBytes in boolean zurückgeben, ob noch Bytes zur Verfügung stehen könnten (return n != -1;) und dann
dann nur noch um eine Schleife zu legen die eben auch so lange läuft wie sie noch Daten hat oder sehe ich das Falsch?
Also irgendetwas wie
Java:
public void split(InputStream is, String basename, String ext, int size) {
    int fileNo = 1;
    FileOutputStream fos;
    do {
        fos = new FileOutputStream(String.format("%s%d%s", basename, fileNo++, ext));
    } while (copyBytes(is, fos, size));
}
 

ocsme

Top Contributor
Danke.
Wo muss ich jetzt welche Streams schließen?
Oder reicht es wenn ein in einer Methode einen Stream öffnet denn in der main zu schließen?

Ich bekomme es aber leider immer noch nicht hin. Irgendwie verstehe ich das alles noch überhaupt nicht :( sry!

LG

so irgendwie habe ich mir das gedacht aber was muss nach der netten Methode copyBytes dann bei read stehen?
Java:
            int b = is.read(buffer);
            while(b!=-1) {
                copyBytes(is,os,size);
                b=is.read(b, off, len)
            }


wie lese ich nun die Datei die größer ist als 1,33 MB weiter ein?
 
Zuletzt bearbeitet:

mihe7

Top Contributor
Die Methode, die den Stream öffnet, sollte ihn auch schließen. Insofern wäre es besser:
Java:
public void split(InputStream is, String basename, int size) throws IOException {
    int fileNo = 1;
    boolean moreBytes;
    do {
        try(FileOutputStream fos = new FileOutputStream(String.format("%s.%d", basename, fileNo++))) {
            moreBytes = copyBytes(is, fos, size);
        }
    } while (moreBytes);
}
und z. B.
Java:
public void splitFile(File file, int size) throws IOException {
    try(FileInputStream fis = new FileInputStream(file)) {
        split(is, file.getAbsolutePath(), size);
    }
}
zu verwenden.
 

ocsme

Top Contributor
public void split(InputStream is, String basename, int size) throws IOException { int fileNo = 1; boolean moreBytes; do { try(FileOutputStream fos = new FileOutputStream(String.format("%s.%d", basename, fileNo++))) { moreBytes = copyBytes(is, fos, size); } } while (moreBytes); }


Bricht der code nicht ab wenn er die Datei die zu Zerteilen ist 1x Zerteilt hat?
Ich verstehe es nicht! sry


Ich verstehe auch immer noch nicht so ganz wie ich nach der Methode Ihm sagen kann lies doch bitte ab Size weiter ;)
Dann würde ich das ganze einfach in eine while(nach size bis dateiende) packen und dem os immer einen neuen Namen mit geben Fertig :)

Java:
            int size = (int) (1.33*1024*1024);

Java:
    public static boolean copyBytes(InputStream is, OutputStream os, int size) throws IOException {
        byte[] buf = new byte[4096]; // 4 KiB Buffer

        int remaining = size;
        int n=0;
        while (remaining > 0 && (n = is.read(buf, 0, Math.min(buf.length, remaining))) != -1) {
            os.write(buf, 0, n);
            remaining -= n;
        }
        is.close();
        os.close();
        return n!=-1;
    }

Denn so in der Richtung geht es nicht:
Java:
int size = (int) (1.33*1024*1024);
            byte[] buffer = new byte[size];
 int b = is.read(buffer);
            while(b != -1) {
                String outputPath2 = outputPath+count;
                os = new FileOutputStream(outputPath2);
                copyBytes(is,os,size);
                count++;
                b = is.read(buffer, 0, b);
            }
 
Zuletzt bearbeitet:

mihe7

Top Contributor
Nochmal langsam:
Java:
boolean copyBytes(InputStream is, OutputStream os, int size) throws IOException { 
    byte[] buf = new byte[4096]; // 4 KiB Buffer

    int remaining = size;
    int n;
    while (remaining > 0 && (n = is.read(buf, 0, Math.min(buf.length, remaining))) != -1) {
        os.write(buf, 0, n);
        remaining -= n;
    }
    return n != -1;
}

Die Methode kopiert bis zu size Bytes aus dem InputStream in den OutputStream. Am Ende gibt es zwei Möglichkeiten: entweder es wurden size Bytes kopiert - dann ist remaining == 0 - oder das Dateiende wurde zuvor erreicht - dann ist n == -1. Wurde das Dateiende noch nicht erreicht (n != 1), dann können weitere Bytes aus dem InputStream gelesen werden. Die Methode liefert false zurück, falls das Dateiende erreicht wurde, true sonst.
 

ocsme

Top Contributor
Jetzt hab ich das verstanden.

Hab die zugehörigen Streams noch geclosed, bei der Methode copyBytes sollte man den InputStream ja nicht closen oder? denn dann würde das so nicht mehr Funktionieren.

Java:
    public static boolean copyBytes(InputStream is, OutputStream os, int size) throws IOException {
        byte[] buf = new byte[4096]; // 4 KiB Buffer

        int remaining = size;
        int n=0;
        while (remaining > 0 && (n = is.read(buf, 0, Math.min(buf.length, remaining))) != -1) {
            os.write(buf, 0, n);
            remaining -= n;
        }
        os.close();
        return n!=-1;
    }
    

    public static void split(InputStream is, String basename, int size) throws IOException {
        int fileNo = 1;
        boolean moreBytes;
        do {
            try(FileOutputStream fos = new FileOutputStream(String.format("%s.%d", basename, fileNo++))) {
            moreBytes = copyBytes(is, fos, size);
            }
        } while (moreBytes);
        is.close();
    }


Man da hab ich wieder auf dem Schlauch gestanden :D so hätte ich das nie hin bekommen :(
 

mihe7

Top Contributor
Hab die zugehörigen Streams noch geclosed,
Die werden automatisch geschlossen, weil ich hier try-with-resources verwende :) Die split-Methode bekommt einen InputStream, daher schließt sie ihn auch nicht. Das macht man von außerhalb wie z. B. in Kommentar #18 die splitFile-Methode (hier wieder automatisch durch try-with-resources).

Funktioniert der Spaß überhaupt?
 

ocsme

Top Contributor
Die Methode habe ich nicht vestanden gehabt deswegen habe ich sie derzeit nicht drin.
Hab aber noch ein Problem, wenn ich auf ein Verzeichnis komme möchte ich diese gerne Einpacken. Doch er packt immer nichts ein :D nur die Ordnerstruktur ist da sonst nichts :(


Das ganze Programm sieht bis jetzt so aus:
Java:
package Insel;
import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

public class Filesplit {
    //method coded by mihe7
    public static boolean copyBytes(InputStream is, OutputStream os, int size) throws IOException {
        byte[] buf = new byte[4096]; // 4 KiB Buffer

        int remaining = size;
        int n=0;
        while (remaining > 0 && (n = is.read(buf, 0, Math.min(buf.length, remaining))) != -1) {
            os.write(buf, 0, n);
            remaining -= n;
        }
        os.close();
        return n!=-1;
    }
    
    //method coded by mihe7
    public static void split(InputStream is, String basename, int size) throws IOException {
        int fileNo = 1;
        boolean moreBytes;
        do {
            try(FileOutputStream fos = new FileOutputStream(String.format("%s.%d", basename, fileNo++))) {
            moreBytes = copyBytes(is, fos, size);
            }
        } while (moreBytes);
        is.close();
    }

    public static void main(String...strings ) throws IOException {
        InputStream is = null;
        OutputStream os = null;
        try {
            String path = "/home/snap/";
            String outputPath = "/home/a";
            int size = (int) (1.33*1024*1024);
            byte[] buffer = new byte[4096];
            File f = new File(path);

            if(f.isFile()) {
                is = new FileInputStream(path);
                if(f.length() < buffer.length) {
                    os = new FileOutputStream(outputPath);
                    int b = is.read(buffer);
                    while (b != -1) {
                        os.write(buffer, 0, b);
                        b = is.read(buffer);
                    }
                }
                else {
                    split(is,outputPath,size);
                }
            }
            else if(f.isDirectory()) {
                os = new FileOutputStream(outputPath);
                ZipOutputStream zos = new ZipOutputStream(os);
                zos.putNextEntry(new ZipEntry(path));
                int b = is.read(buffer);
                while (b != -1) {
                    zos.write(buffer, 0, b);
                    b = is.read(buffer);
                }
                zos.close();
            }
                else throw new Exception("unknow error");
        }
        catch(IOException ex) {
            ex.getMessage();
        }
        catch(Exception ex) {
            ex.getMessage();
        }
        finally {
            if(is!=null)
                is.close();
            if(os!=null)
                os.close();
        }
    }

}

Jetzt hab ich soviel geübt und kann es immer noch nicht :D da muss ich mal in einem Buch nachschlagen doch das Problem ist das dort oft mit nio.2 angefangen wird und wir das nicht behandeln. Wenn ich das hier schon nicht verstehen wieso sollte ich dann nio.2 verstehen :D ???

LG
 

ocsme

Top Contributor
In copyBytes() bitte os.close und in split() is.close()... (s. Kommentar #22) Ich würde erstmal mit einem Refactoring von main anfangen.
Was meinst du mit Refactoring von main? Die main lesbarer machen?
Können in der Methode die Streams offen bleiben wenn Sie in der Main Methode geschlossen werden sind die dann zu oder könnten da noch welche laufen?

nio dürfen wir nicht nutzen :D das muss ich dann selbst schreiben.

lg
 

mrBrown

Super-Moderator
Mitarbeiter
Was meinst du mit Refactoring von main? Die main lesbarer machen?
Ja, aufräumen, kürzen und Dinge auslagern - das lesbarer kommt dann von allein ;)

Können in der Methode die Streams offen bleiben wenn Sie in der Main Methode geschlossen werden sind die dann zu oder könnten da noch welche laufen?
Einfache Regel: Streams dort schließen, wo du sie geöffnet hast.
Die Methoden, die die Streams übergeben bekommen, schließen sie nicht, sondern lassen sie offen. Das schließen übernimmt die Methode, die den stream geöffnet hat.

InputStream is = null; OutputStream os = null;
Woher kommt eigentlich dieses Antipattern, sowas am Anfang zu deklarieren und mit null zu initialisieren :p mit vernünftigen Scopes macht man sich so vieles einfacher ;)


Zur main: close kann auch eine Exception schmeißen, wenn du die nicht fängst, macht es wenig Sinn, die anderen zu fangen und der zweite close-Aufruf wird uU nie ausgeführt. try-with-resources solltest du dir wirklich mal angucken ;)
 

ocsme

Top Contributor
Danke für das Feedback :)
try-with-resources muss ich mir dann mal anschauen. Die close() Methode auch. Uns wurde eben gesagt wir sollten das im finally closen :)

Jetzt habe ich nur wieder ein Verständigungs Problem. Das ist eben genau das was ich so hasse wenn man es nicht selbst schreibt sondern "nur" verstehen muss :( :D
Wenn ich bei copyBytes() den InputStream wieder schließe weiß er später doch nicht wo er aufgehört hat. Das Problem hatte ich ja auch mit dem Versuch das ganze in der Main als Schleife zu erstellen :(

LG
 

mrBrown

Super-Moderator
Mitarbeiter
Wenn ich bei copyBytes() den InputStream wieder schließe weiß er später doch nicht wo er aufgehört hat.
Den Stream solltest du dort auch nicht schließen.
Die Methode bekommt ihn geöffnet übergeben, also lässt sie ihn auch geöffnet.
Wie hier schon gesagt:
Die split-Methode bekommt einen InputStream, daher schließt sie ihn auch nicht.
und hier:
Streams dort schließen, wo du sie geöffnet hast.
Die Methoden, die die Streams übergeben bekommen, schließen sie nicht, sondern lassen sie offen. Das schließen übernimmt die Methode, die den stream geöffnet hat.
Die close() Methode auch. Uns wurde eben gesagt wir sollten das im finally closen :)
selber close aufrufen muss und sollte man heute nahezu nie. Grad wenn man zwei Streams schließen muss, macht man das nahezu immer falsch.
 

ocsme

Top Contributor
selber close aufrufen muss und sollte man heute nahezu nie. Grad wenn man zwei Streams schließen muss, macht man das nahezu immer falsch.
Soll ich das Schließen der Resourcen dann mit try-with-resources schließen lassen?
Dann macht das auch Sinn wenn die Methode copyBytes weiterhin einen offenen Stream hat.
Jetzt nur mal noch eine letzte "doofe" Frage :)

Sagen wir mal bei einer solchen Methode wie copyBytes läuft etwas schief und der Stream läuft und läuft. Wie könnte man den nach beenden der Schleife diesen Stream noch schließen? Gar nicht mehr? oder eben auch mit try-with-resources verfahren bzw. das diese Methode den Stream schließt.
Kann sein das ich mich gedanklich gerade mal wieder im Kreis drehe sry!

LG
 

mrBrown

Super-Moderator
Mitarbeiter
Soll ich das Schließen der Resourcen dann mit try-with-resources schließen lassen?
Ja, das macht das "im Hintergrund automatisch".

Sagen wir mal bei einer solchen Methode wie copyBytes läuft etwas schief und der Stream läuft und läuft. Wie könnte man den nach beenden der Schleife diesen Stream noch schließen? Gar nicht mehr? oder eben auch mit try-with-resources verfahren bzw. das diese Methode den Stream schließt.

mit "läuft etwas schief" meinst du eine Exception? Dann greifen die nächsthöheren catch- und finally-Blöcke und damit auch eventuelle try-with-resources die das passend schließen würden.
 

ocsme

Top Contributor
alles klar Danke :)
habt mir echt das Leben gerettet :)
Mal gespannt wann ich euch wieder nerven darf :p sicherlich morgen wenn ich wieder weiter üben möchte :D

LG
 

mihe7

Top Contributor
Sorry, war indisponiert.

nio dürfen wir nicht nutzen :D das muss ich dann selbst schreiben.
Das ist nicht schwer. Rekursiver Algorithmus:
Code:
besuche(Path folder):
    für alle Dateien d in folder
        falls d ein Verzeichnis ist, dann besuche(d) sonst mach was mit d
oder, wenn es Dir ohne Rekursion besser gefällt, dann
Code:
besuche(Path folder):
    l := leerer Stack
    push(l, folder)
    so lange l nicht leer
        f := pop(l)
        für alle Dateien d in f
            falls d ein Verzeichnis ist, dann push(l, d) sonst mach was mit d
dabei enthält l also alle noch nicht besuchten Verzeichnisse.
 

ocsme

Top Contributor
Ihr seit schon zu beneiden :)
Einer wie ich zerbreche mir den Kopf bei solchen Aufgaben und Ihr Tippst das einfach mal locker Leicht ins Forum :)

Nochmals Danke :)
LG
 

mihe7

Top Contributor
Keine Angst, das kommt mit der Zeit von ganz alleine. Geht man davon aus, dass die Dateien/Verzeichnisse in einer Baumstruktur organisiert sind, dann ist ein Durchlauf ein Standardproblem. Will man das für den allgemeinen Fall haben, müsste man übrigens berücksichtigen, dass der Graph durch symbolische Links ggf. seine Baumeigenschaft verliert. Dann muss man sicherstellen, dass man nicht sprichwörtlich im Kreis läuft.
 
X

Xyz1

Gast
Wofür braucht ihr jetzt eine Baumstruktur? Es soll doch nur eine Datei geteilt werden?
Das Traversieren ist in Java nicht ganz trivial übrigens. Python wäre da zum Bleistift sehr viel angenehmer.
 
X

Xyz1

Gast
Er will Verzeichnisse zippen.


In Python sind das Dreizeiler:
Python:
from os import walk
from os.path import join as j

def walk_dir(dirname):
  for (dirpath, dirnames, filenames) in walk(dirname):
    [pre_file(dirpath, filename) for filename in filenames]
    [walk_dir(dirname) for dirname in dirnames]

def pre_file(dirpath, filename):
  print("saw file:", j(dirpath, filename))
  # Do sth. with Filename...

walk_dir(".")
 

mrBrown

Super-Moderator
Mitarbeiter
In Python sind das Dreizeiler:
Python:
from os import walk
from os.path import join as j

def walk_dir(dirname):
  for (dirpath, dirnames, filenames) in walk(dirname):
    [pre_file(dirpath, filename) for filename in filenames]
    [walk_dir(dirname) for dirname in dirnames]

def pre_file(dirpath, filename):
  print("saw file:", j(dirpath, filename))
  # Do sth. with Filename...

walk_dir(".")
In Java ein Einzeiler: Files.walk(Paths.get(".")).forEach(path -> System.out.println(path)/*Do sth. with Filename...*/)
 

mrBrown

Super-Moderator
Mitarbeiter

ocsme

Top Contributor
Ich hoffe das eskaliert hier jetzt nicht ^.^
Danke an euch sehr nett :) Vielleicht schaffe ich das auch irgendwann mal :)

Werde es später versuchen hab noch ein paar mehr Aufgaben die "wichtiger" sind, die ich erledigen muss. Sprich das was wir eigentlich Programmieren sollen :p Denn das hier mache ich ja nur für mich um IO etwas besser hin zu bekommen :)

LG
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
F Mehrere Zeilen zu einer Zeile zusammenfügen und in eine Datei schreiben Java Basics - Anfänger-Themen 1
N Datei Zeilenweise einlesen, Ausgabe mehrere Arrays Java Basics - Anfänger-Themen 7
I Klassen Mehrere Java Klassen in einer .java Datei Java Basics - Anfänger-Themen 7
D Input/Output Mehrere Objecte in einer Datei Java Basics - Anfänger-Themen 5
B Datei in mehrere Ordner splitten und wieder zusammenfuegen... Java Basics - Anfänger-Themen 3
isowiz Mehrere Threads schreiben in eine Datei Java Basics - Anfänger-Themen 5
S mehrere einzelne klassen in eine datei packen Java Basics - Anfänger-Themen 4
H mehrere Strings zeitlich versetzt in eine Datei schreiben Java Basics - Anfänger-Themen 3
G Mehrere Typen in einer Datei Java Basics - Anfänger-Themen 5
L Mehrere Objekte mit NIO in eine Datei schreiben Java Basics - Anfänger-Themen 4
G Mehrere Zahlen aus Datei lesen Java Basics - Anfänger-Themen 3
F Mehrere Strings in Datei schreiben Java Basics - Anfänger-Themen 4
V Mehrere Zeilen in eine Datei schreiben + Zeitstempel Java Basics - Anfänger-Themen 3
K Warum wird hier nur etwas in eine txt Datei geschrieben und nicht in alle drei (InputStream/OutputStream/Reader/Writer) Java Basics - Anfänger-Themen 1
farbenlos Csv Datei in Java einlesen Java Basics - Anfänger-Themen 18
E Audio Datei unter Bedingungen ausführen Java Basics - Anfänger-Themen 19
S Daten aus Import Datei auslesen und sortieren Java Basics - Anfänger-Themen 2
A exe Datei erstellen Java Basics - Anfänger-Themen 8
J .jar datei öffnen funktioniert nicht Java Basics - Anfänger-Themen 17
P Aus Text Datei nur Zahlen übernehmen Java Basics - Anfänger-Themen 13
P Welches SDK für das erstellen einer ausführbaren Datei? Java Basics - Anfänger-Themen 4
W Fehler in der Datei pom.xml Java Basics - Anfänger-Themen 19
M Verständnisfrage: Warum wird die Datei ohne Inhalt übertragen Java Basics - Anfänger-Themen 3
D Jar Datei startet unter Linux nicht Java Basics - Anfänger-Themen 3
P Probleme mit NetBeans: Wie lässt sich jar. Datei an einem MacBook öffnen Java Basics - Anfänger-Themen 21
N Programm Funktioniert mit .txt Datei aber nicht mit .rtf Datei Java Basics - Anfänger-Themen 2
A Wie führe ich eine Batch-Datei von meiner Java-Anwendung aus? Java Basics - Anfänger-Themen 18
D Java Programm mit Batch-Datei starten Java Basics - Anfänger-Themen 32
W Objekte einer ArrayList in txt-datei schreiben mit Paths? Java Basics - Anfänger-Themen 2
E TIF Datei auslesen Java Basics - Anfänger-Themen 2
B von Java/Eclipse verwendete Datei existiert gar nicht? Java Basics - Anfänger-Themen 6
M Spezifischen Wert einer Zeile aus .txt Datei entnehmen Java Basics - Anfänger-Themen 15
B Popups mit Klicksabfangen zumAusfüllen einer .ods Datei Java Basics - Anfänger-Themen 0
M Daten aus .txt Datei einlesen und weiterverarbeiten Java Basics - Anfänger-Themen 80
M RandomAccessFile int und String gleichzeitig in einer Datei Java Basics - Anfänger-Themen 49
I Datei (Bild) Drucken und wie Druckeinstellung speichern? Java Basics - Anfänger-Themen 3
A CSV-Datei Verarbeiten Java Basics - Anfänger-Themen 8
D Downloadfortschritt von Datei über Google Drive API v3 Java Basics - Anfänger-Themen 10
A CSv.Datei einlesen und die werte in zweidemosional Int Array speichern Java Basics - Anfänger-Themen 9
B Den Dateipfad einer Java Datei durch Code in Selbiger finden? Java Basics - Anfänger-Themen 10
S In Datei schreiben in Java? Java Basics - Anfänger-Themen 1
Saiko Zeilen einer Datei einlesen Java Basics - Anfänger-Themen 3
sserio TXT-Datei Auslesen und den Wert jedes Namen ausrechnen etc. Java Basics - Anfänger-Themen 37
sserio Txt Datei einlesen Java Basics - Anfänger-Themen 9
T Printwriter Datei nicht überschreiben Java Basics - Anfänger-Themen 10
berserkerdq2 An selbst ersteller txt Datei immer Text dranhängen, ohne den vorherign Text zu löschen Java Basics - Anfänger-Themen 8
berserkerdq2 Wie gebe ich den Pfad zu einer Datei an, die in einem Ordner in Eclipse ist? Java Basics - Anfänger-Themen 1
D Strings aus Excel-Datei einlesen Java Basics - Anfänger-Themen 2
M Text in Datei schreiben Java Basics - Anfänger-Themen 9
S Datei anlegen Problem! Groß- und Kleinschreibung wird nicht unterschieden Java Basics - Anfänger-Themen 4
J selbst erstellte Datei mit Programm öffnen Java Basics - Anfänger-Themen 10
J int innerhalb einer Datei ändern Java Basics - Anfänger-Themen 1
T208 Text Datei individuell benennen. Java Basics - Anfänger-Themen 5
julian112 Input/Output .gz bzw. .txt Datei Einlesen und Umgang mit Exceptions Java Basics - Anfänger-Themen 1
F Aus eingelesener Datei korrekt Objekte erzeugen Java Basics - Anfänger-Themen 5
E extern Datei von meinem Computer aufmachen Java Basics - Anfänger-Themen 5
H Scripte oder Programmcode aus Datei lesen? Java Basics - Anfänger-Themen 5
E PDF Datei im xfdf-Datei umwandeln und auf dem Laufwerk ablegen Java Basics - Anfänger-Themen 0
J CSV-Datei verarbeiten Java Basics - Anfänger-Themen 27
A Verarbeiten einer Excel Datei durch das java-Programm Java Basics - Anfänger-Themen 3
P Datei einlesen, nach Begriff filtern und in Datei ausgeben. Problem Standardausgabe über Konsole Java Basics - Anfänger-Themen 19
nbergmann Installation unter jdk.java.net: Keine ZIP-Datei zum entpacken Java Basics - Anfänger-Themen 2
J Datei aus Netzwerk auslesen Java Basics - Anfänger-Themen 9
EchtKeineAhnungManchmal hallo habe ein Problem mit einer Datei -> (Zugriff verweigert) Java Basics - Anfänger-Themen 4
EchtKeineAhnungManchmal Controller aus FXML Datei entfernen Java Basics - Anfänger-Themen 49
I Probleme mit OutputStream - Datei lässt sich nicht öffnen Java Basics - Anfänger-Themen 4
Kotelettklopfer Sqlite DB aus Java Datei ansprechen. Java Basics - Anfänger-Themen 147
C XML Datei speichern und laden Java Basics - Anfänger-Themen 18
M Von einem Menü Methode aus anderer Klasse ausführen, die errechnete Werte in Datei schreibt. Java Basics - Anfänger-Themen 8
C XML Datei schreiben Java Basics - Anfänger-Themen 14
S Zufällige ungerade Zeile aus Text-Datei lesen Java Basics - Anfänger-Themen 5
J Wert in einer json Datei ändern und speichern Java Basics - Anfänger-Themen 3
L Java erstellt leere Datei Java Basics - Anfänger-Themen 8
J Json Datei auslesen Java Basics - Anfänger-Themen 4
J In main() Datei geöffnet, von anderer Funktion beschreiben Java Basics - Anfänger-Themen 3
I JAX-WS.... Datei ".ical" zurückgeben.... Wie annotieren? Java Basics - Anfänger-Themen 1
O zweidimensionales array in eine csv-Datei Java Basics - Anfänger-Themen 1
CptK Richtigen Pfad beim einlesen von Datei finden Java Basics - Anfänger-Themen 2
E Pfadangaben bei Ausführbarer Jar Datei Java Basics - Anfänger-Themen 8
J Input/Output Konstruktor ergänzen, der zur Datei mit einem Objekt passt Java Basics - Anfänger-Themen 0
I Datei als Stream aus Ressource laden? Java Basics - Anfänger-Themen 2
LetsSebi Methode, die einen arry von objekten speichert in einer datei Java Basics - Anfänger-Themen 6
R Wie installiere ich Jdownloadersetup.sh datei mit debian Java Basics - Anfänger-Themen 2
J Csv-Datei einlesen Java Basics - Anfänger-Themen 52
H Daten aus einer Datei in eine Liste speichern Java Basics - Anfänger-Themen 23
W Java in Exe Datei umgewandelt, Ressourcen fehlen (Bilder und Audiodateien) Java Basics - Anfänger-Themen 1
A Fehler beim Ausführen einer class Datei Java Basics - Anfänger-Themen 6
L Konstruktor für eine Map-Datei/Map-Datei einlesen Java Basics - Anfänger-Themen 5
S CSV Datei auslesen und anders darstellen Java Basics - Anfänger-Themen 2
O zufälliges Wort aus einer Datei einlesen Java Basics - Anfänger-Themen 32
E Input/Output Datei anhand von Dateinamen einlesen Java Basics - Anfänger-Themen 5
C Datei über relative Pfade einlesen Java Basics - Anfänger-Themen 6
F Auto String mit Array Name aus Datei... oder so ähnlich Java Basics - Anfänger-Themen 4
O Best Practice Datei-Pfad zerlegen Java Basics - Anfänger-Themen 4
N Java CSV Datei auslesen Java Basics - Anfänger-Themen 6
J Ein Wort aus einer Datei zufällig ermitteln Java Basics - Anfänger-Themen 3
S Verbindung von einer Excel Datei zu Java-- Java Basics - Anfänger-Themen 4
G In Datei schreiben Java Basics - Anfänger-Themen 1
J Klassen .class Datei öffnen Java Basics - Anfänger-Themen 31
P Datei einlesen und zurückgeben Java Basics - Anfänger-Themen 5

Ähnliche Java Themen

Neue Themen


Oben