Pre allocate File Data in Java

Tagchen,

rf = new RandomAccessFile(file, "rw");
rf.setLength(LEN);```

- [java - Pre-allocating drive space for file storage - Stack Overflow](http://stackoverflow.com/questions/18031841/pre-allocating-drive-space-for-file-storage)

hilft das einer Dateifragmentierung als Prophylaxe zuverhüten? Ist es plattformabhängig?

Das ist plattformabhängig. Da in der Dokumentation sogar steht, dass der Inhalt der vergrößerten Datei undefiniert ist, lässt dies auch den JVM-Entwicklern Freiräume.
Wahrscheinlich ist, dass ein sparse-file angelegt wird, welches erst einmal keinen weiteren Speicherplatz auf der Festplatte verbraucht.
Ob überhaupt Fragmentierung auftritt, ist aber eine Sache vom Dateisystem. Es gibt welche, die sind sehr anfällig dafür (z. B. FAT32) und welche, die nur sehr wenig fragmentieren (die ext-Familie bspw.). Darüber hinaus ist die Fragmentierung zusätzlich noch abhängig von dem Füllstand der Festplatte.

.flush() verhält sich auch komisch bei NTFS. Ich hab trotz .flush() am Anfang Schreibgeschwindigkeiten von ca. 300 mbs, welches dann langsam heruntergeht auf 100 mbs. Die Idee mit dem Präallozieren entstand, weil 7zip nicht präalloziert:
https://sourceforge.net/p/sevenzip/discussion/45797/thread/3a6ccdcb/

  • Deswegen wollte ich das einfach selber schreiben, wegen der möglichen Fragmentierung, aber es scheint schwieriger, als angedacht.

vieleicht weil Du versucht eine Low-Level Aufgabe mit einer High-Level Programmiersprache zu lösen

flush() ist dafür auch nicht gedacht - im Gegenteil, bei zuviel flush() wird die Schreibgeschwindigkeit noch viel schlimmer. die Aufgabe von flush besteht darin den Buffer zu leeren und ein schreiben auf der Platte zu erzwingen. Damit kannst Du sicher stellen das eine Meldung von 20 Bytes im Logfile auch wirklich geschrieben werden.

Ja, aber ich meinte das so: Ich wollte die tatsächliche Schreibgeschwindigkeit ermitteln. Dazu sollte es anfangs nicht schneller sein, sondern immer gleich schnell. Wenn #flush blockiert (weiß ich auch nicht genau), dann muss das Dateisystem an irgendeiner Stelle eine Zusicherung machen: ja, deine Daten werden auf jeden Fall sicher geschrieben werden, aber bitte nicht sofort… Wann, entscheide ich.

Vielleicht ist Java zu high dafür, das wäre möglich…

Außerdem gibt es neben Festplatten cache und Hardware cache wohl noch einen cache (nicht Software) - und das will ich alles “umgehen”.

Es ist ja gut, das man nur noch sagen muss:
Schreibe sinnvoll viele Daten.
Aber manchmal ist das auch nicht gewünscht.

Imho blockiert flush nicht wirklich. Flush leert den Buffer des verwendeten Streams. Nich mehr und nich weniger.

Was genau bei einem FileOutputStream passiert, muesste man im Source nachsehen (ich tipp auf JNI Call?). Vermutlich sendet das den Buffer ans OS mit der Meldung “Speicher das ma”. Was damit passiert ist dann also betriebssystemabhaengig.

Von Windows/NTFS kann ich bestaetigen, dass z.B. das Kopieren auf einen USB Stick zuerst mal gar nix kopiert, der Anwendung aber der Fortschritt beim Kopieren zurueckgemeldet (extrem schnell) wird. Erst wenn also die OS internen Buffer voll sind, wird ueberhaupt was auf die Platte/Stick geschrieben.

So ist es. Daher bleibt als einzige Möglichkeit, die “echte” Schreibperformance zu testen, alle vorhandenen Puffer voll zu machen und dann erst die Geschwindigkeit zu errechnen.
Und das über einen möglichst großen Zeitraum, um ein realistisches Ergebnis zu erhalten.

Und dann noch etwas (VIELLEICHT lehne ich mich zu weit aus dem Fenster): Je höher die Kompression, je höher die Entropie, je niedriger die Schreibgeschwindigkeit, je weiter nähern sich die Daten der Bitfolge 01010101 an! Stimmt das?

Hat irgendjemand Interesse an meinem Proggi zum Ermitteln der Schreibgeschwindigkeit nach ganz vielen “Durchläufen”?

Ich kann dir nicht folgen.

Warum sollte jemand daran Interesse haben? Wer seine Festplattenperformance messen möchte, kann auf das erprobte h2benchw, das in der c’t-Redaktion entwickelt wurde und dort für Festplattentests verwendet wird, einsetzen. Ohne dein Programm gesehen zu haben, würde ich einfach mal behaupten, dass die Ergebnisse deutlich realistischer sein dürften, als die von deiner Anwendung.

Wozu ?? Festplatten sind immer zu langsam

Funktioniert jetzt, wie ich mir das dachte:

            if (f.getName().endsWith(".rar")) {
                Archive ar = new Archive(f);
                ar.getMainHeader().print();
                FileHeader fh = ar.nextFileHeader();
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                while (fh != null) {
                    File out = new File(f.getParent() + File.separator + fh.getFileNameString().trim());

                    ar.extractFile(fh, baos);

                    RandomAccessFile rf = new RandomAccessFile(out, "rw");
                    rf.setLength(baos.size());
                    rf.write(baos.toByteArray());
                    rf.close();
                    baos.reset();

                    fh = ar.nextFileHeader();
                }
            }```

zu importieren sind:

```import com.github.junrar.*;
import com.github.junrar.exception.*;
import com.github.junrar.rarfile.*;
import java.io.*;
import javax.swing.*;```
sowie
Apache Commons Logging(TM)

Es speichert es einfach im RAM ;) .* Leider muss ich das aus der IDE heraus starten, da:


java -Xms2048m -Xmx2048m -jar Unzipper.jar
Error occurred during initialization of VM
Could not reserve enough space for 2097152KB object heap



ich hab noch die 32 Bit-Version der VM o.O .

.*: RAM mit den 16 gb schon ausreichend, hrhr.

---

ERGEBNIS: KEINE Fragmentierung der betrefflichen Dateien.