Ausgabe
In einem Java-Projekt erzeuge ich eine große CSV-Datei (ca. 500 MB), und ich muss diese Datei in mehrere Dateien mit einer Größe von jeweils höchstens 10 MB aufteilen. Ich habe viele ähnliche Posts gefunden, aber jeder beantwortet meine Frage, da der Java-Code in allen Posts die Originaldateien in genau 10-MB-Dateien aufteilt und (offensichtlich) Datensätze abschneidet. Stattdessen brauche ich, dass jeder Datensatz vollständig und intakt ist. Jeder Datensatz sollte abgeschnitten werden. Wenn ich einen Datensatz aus der ursprünglichen großen CSV-Datei in eine generierte Datei kopiere und die Dateidimension 10 MB überschreitet, wenn ich den Datensatz kopiere, sollte ich in der Lage sein, diesen Datensatz nicht zu kopieren, diese Datei zu schließen und eine neue Datei zu erstellen und kopieren Sie den Datensatz in den neuen. Ist es möglich? Kann mir jemand helfen? Vielen Dank!
Ich habe diesen Code ausprobiert:
File f = new File("/home/luca/Desktop/test/images.csv");
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(f));
FileOutputStream out;
String name = f.getName();
int partCounter = 1;
int sizeOfFiles = 10 * 1024 * 1024;// 1MB
byte[] buffer = new byte[sizeOfFiles];
int tmp = 0;
while ((tmp = bis.read(buffer)) > 0) {
File newFile=new File("/home/luca/Desktop/test/"+name+"."+String.format("%03d", partCounter++));
newFile.createNewFile();
out = new FileOutputStream(newFile);
out.write(buffer,0,tmp);
out.close();
}
Funktioniert aber offensichtlich nicht. Dieser Code teilt eine Quelldatei in n 10-MB-Dateien auf, wobei Datensätze abgeschnitten werden. In meinem Fall hat meine CSV-Datei 16 Spalten, also habe ich mit dem obigen Verfahren zum Beispiel der letzte Datensatz nur 5 Spalten gefüllt. Die anderen sind abgeschnitten.
LÖSUNG
Hier der Code, den ich geschrieben habe.
FileReader fileReader = new FileReader("/home/luca/Desktop/test/images.csv");
BufferedReader bufferedReader = new BufferedReader(fileReader);
String line="";
int fileSize = 0;
BufferedWriter fos = new BufferedWriter(new FileWriter("/home/luca/Desktop/test/images_"+new Date().getTime()+".csv",true));
while((line = bufferedReader.readLine()) != null) {
if(fileSize + line.getBytes().length > 9.5 * 1024 * 1024){
fos.flush();
fos.close();
fos = new BufferedWriter(new FileWriter("/home/luca/Desktop/test/images_"+new Date().getTime()+".csv",true));
fos.write(line+"\n");
fileSize = line.getBytes().length;
}else{
fos.write(line+"\n");
fileSize += line.getBytes().length;
}
}
fos.flush();
fos.close();
bufferedReader.close();
Dieser Code liest eine CSV-Datei und teilt sie in n Dateien auf, jede Datei ist maximal 10 Mb groß und jede CSV-Zeile wird vollständig oder gar nicht kopiert.
Lösung
Im Prinzip ganz einfach.
Sie erstellen einen Puffer von 10 MB (Byte []) und lesen so viele Bytes wie möglich aus der Quelle. Dann suchen Sie von hinten nach einem Zeilenvorschub. Der Teil vom Beginn des Puffers bis zum Zeilenvorschub = neue Datei. Sie behalten den überzähligen Teil und kopieren ihn an den Anfang des Puffers (Offset 0). Das wiederholst du alles bis keine Quelle mehr kommt.
Beantwortet von – Durandal
Antwort geprüft von – Willingham (FixError Volunteer)