{"id":4455,"date":"2024-03-22T16:00:33","date_gmt":"2024-03-22T16:00:33","guid":{"rendered":"https:\/\/msgprogramator.sk\/?p=4455"},"modified":"2025-07-07T11:36:28","modified_gmt":"2025-07-07T11:36:28","slug":"java-dateien-lesen","status":"publish","type":"post","link":"https:\/\/msgprogramator.sk\/de\/java-dateien-lesen\/","title":{"rendered":"Java-Dateien schnell und effizient lesen."},"content":{"rendered":"<p>Es gibt viele verschiedene M\u00f6glichkeiten, Dateien in Java zu lesen.  Bei der Suche nach einem Java-Beispiel f\u00fcr das einfache Laden von Dateien kannst du beispielsweise auf die folgenden Java-Klassen f\u00fcr die Arbeit mit Dateien sto\u00dfen <strong><em> InputStream<\/em><\/strong>, <strong><em>FileInputStream<\/em><\/strong>, <strong><em>DataInputStream<\/em><\/strong>, <strong><em>SequenceInputStream<\/em><\/strong>, <strong><em>Reader<\/em><\/strong>, <strong><em>InputStreamReader<\/em><\/strong>, <strong><em>FileReader<\/em><\/strong>,        <strong><em>BufferedReader<\/em><\/strong>, <strong><em>FileChannel<\/em><\/strong>, <strong><em>SeekableByteChannel<\/em><\/strong>, <strong><em>Scanner, StreamTokenizer<\/em><\/strong>, <strong><em>Files<\/em><\/strong> und \u00e4hnliche. Wir sind uns ziemlich sicher, dass es noch mehr Klassen gibt und einige davon es nicht in diese Liste geschafft haben. Nat\u00fcrlich erw\u00e4hnen wir noch nicht die externen Drittanbieter-Bibliotheken zur Dateiverarbeitung, die ebenfalls verf\u00fcgbar sind. Die meisten der vorgefertigten Klassen zum Lesen und Schreiben von Dateien in Java befinden sich in den Paketen <strong>java.io<\/strong> und <strong>java.nio.file<\/strong>. Mit der Einf\u00fchrung der neuen API f\u00fcr Java-Dateien, Java NIO.2 (New I\/O), wurde die Situation noch komplizierter. Selbst erfahrene Programmierer stellen sich oft auf Foren die Frage, wie man mit Dateien schnell und effizient arbeitet. Bei der Arbeit mit Dateien sollten wir im Voraus wissen, mit welchen Dateitypen wir arbeiten werden, also ob wir Bin\u00e4rdateien (z.B. Musik im MP3-Format) oder Textdateien lesen m\u00fcssen. Ebenso, ob die Dateien klein genug sind, um sie vollst\u00e4ndig in den Speicher zu laden, oder ob wir mit Dateien arbeiten, die nicht in den Speicher passen und eine andere Verarbeitungsweise erfordern, wie z.B. das Lesen und Verarbeiten zeilenweise. Jede der oben genannten Klassen hat ihre spezifische Verwendung f\u00fcr bestimmte Anwendungsf\u00e4lle.         Im Allgemeinen verwenden wir jedoch bin\u00e4re Datenabrufe <strong><em>Stream<\/em><\/strong> Klassen und Text <strong><em>Reader<\/em><\/strong> Klassen. Klassen, die diese beiden Begriffe in ihrem Namen tragen, kombinieren den Abruf von Bin\u00e4r- und Textdaten.  Zum Beispiel. Klassen <strong><em>InputStreamReader<\/em><\/strong> konsumiert <strong><em>InputStream<\/em><\/strong>, verh\u00e4lt sich aber selbst wie <strong><em>Reader<\/em><\/strong>. <strong><em>FileReader<\/em><\/strong> ist im Grunde eine Kombination aus <strong><em>FileInputStream<\/em><\/strong> mit <strong><em>InputStreamReader<\/em><\/strong>. Wie wir aus dem vorangegangenen Text ersehen k\u00f6nnen, kann das Laden von Daten in Java ziemlich kompliziert werden. In unserem Artikel konzentrieren wir uns daher auf drei grundlegende Szenarien zum Laden von Daten, die 90 Prozent der Anwendungsf\u00e4lle abdecken:  <\/p>\n<ul>\n<li>Der einfachste Weg, die gesamte Textdatei in eine Variable vom Typ <strong>String<\/strong> bzw. Liste zu laden. Liste (und eine Bin\u00e4rdatei in ein Byte-Array). <\/li>\n<li>Laden und Verarbeiten gro\u00dfer Dateien, die nicht vollst\u00e4ndig in den Speicher passen.<\/li>\n<li>Lesen von Dateien, deren Inhalt durch ein Trennzeichen geteilt werden kann, z.B. CSV-Dateien. <\/li>\n<\/ul>\n<h2>Eine kurze Geschichte des Ladens von Dateien in Java<\/h2>\n<p> Das Laden von Dateien mit Hilfe von Java-Bibliotheken war bis Java 7 recht umst\u00e4ndlich. Die am h\u00e4ufigsten verwendete Klasse zum Laden einer Datei war die <strong><em>FileInputStream<\/em><\/strong>Klasse, die neben der Behandlung von Ausnahmen daf\u00fcr sorgen musste, dass der Stream sowohl im Falle eines erfolgreichen Ladens als auch im Falle eines Fehlers geschlossen wurde. Ein automatisches Schlie\u00dfen von verwendeten Ressourcen (wie wir es heute mit <em>try-with-resources<\/em> kennen) gab es damals noch nicht. Daher bevorzugten viele Java-Programmierer Bibliotheken von Drittanbietern wie <a href=\"https:\/\/commons.apache.org\/\" target=\"_blank\" rel=\"nofollow noopener\">Apache Commons<\/a> oder <a href=\"https:\/\/en.wikipedia.org\/wiki\/Google_Guava\" target=\"_blank\" rel=\"nofollow noopener\">Google Guava<\/a>, die viel bequemere Optionen boten. Dies \u00e4nderte sich mit der Einf\u00fchrung von Java 7, das die lang erwartete     <em>NIO.2 Datei-API <\/em>die neben einer Vielzahl von Funktionalit\u00e4ten auch die Hilfsklasse <strong>java.nio.file.Files<\/strong> eingef\u00fchrt hat, mit der man eine gesamte Text- oder Bin\u00e4rdatei mit einer einzigen Methode einlesen kann. <\/p>\n<h2>Laden einer Bin\u00e4rdatei in ein Byte-Array<\/h2>\n<p> Mit der Methode <em>Files.readAllBytes()<\/em> k\u00f6nnen wir den Inhalt der gesamten Datei in das Byte-Array einlesen: <\/p>\n<pre><code class=\"language-java\" data-line=\"\">import java.nio.file.Files;\nimport java.nio.file.Path;\n\nString fileName = &quot;fileName.dat&quot;;\nbyte[] bytes = Files.readAllBytes(Path.of(fileName));\n<\/code><\/pre>\n<p> Die Klasse <em>Path<\/em> stellt eine Abstraktion einer Datei dar und enth\u00e4lt den Pfad zur Datei im Dateisystem. <\/p>\n<h2>Laden einer Textdatei in eine Variable vom Typ String<\/h2>\n<p> Seit Java 11 ist es m\u00f6glich, den Inhalt einer ganzen Textdatei mit der Methode <em>Files.readString()<\/em> einfach in eine Variable vom Typ String einzulesen, wie folgt: <\/p>\n<pre><code class=\"language-java\" data-line=\"\">import java.nio.file.Files;\nimport java.nio.file.Path;\n\nString fileName = &quot;fileName.dat&quot;;\nString text = Files.readString(Path.of(fileName));\n<\/code><\/pre>\n<p> Die Methode <em>readString()<\/em> verwendet intern die Methode <em>readAllBytes()<\/em> und konvertiert dann die Bin\u00e4rdaten in die gew\u00fcnschte Zeichenkette vom Typ String. <\/p>\n<h2>Laden einer Textdatei Zeile f\u00fcr Zeile<\/h2>\n<p> Textdateien bestehen in der Regel aus mehreren Zeilen. Wenn wir den Text zeilenweise lesen und verarbeiten m\u00f6chten, k\u00f6nnen wir eine seit Java 8 verf\u00fcgbare Methode verwenden &#8211; readAllLines(), die dies automatisch tut.  <\/p>\n<pre><code class=\"language-java\" data-line=\"\">import java.nio.file.Files;\nimport java.nio.file.Path;\nimport java.util.List;\n\nString fileName = &quot;fileName.dat&quot;;\nList&lt;String&gt; lines = Files.readAllLines(Path.of(fileName));\n<\/code><\/pre>\n<p> Dann iterieren wir einfach klassisch durch die Liste und verarbeiten jede Zeile. <\/p>\n<h2>Laden einer Textdatei Zeile f\u00fcr Zeile mit String stream<\/h2>\n<p> Mit Java 8 wurden Streams als wichtige Sprachverbesserung eingef\u00fchrt. In derselben Version wurde die Klasse <em>Files<\/em> um eine neue Methode <em>lines()<\/em> erweitert, die die gelesenen Zeilen einer Textdatei als Stream von Strings des Typs String zur\u00fcckgibt. So k\u00f6nnen wir die Funktionalit\u00e4t von Streams z.B. nutzen Beim Filtern von Daten.    <\/p>\n<pre><code class=\"language-java\" data-line=\"\">import java.nio.file.Files;\nimport java.nio.file.Path;\n\nString fileName = &quot;fileName.dat&quot;;\nFiles.lines(Path.of(fileName))\n        .filter(line -&gt; line.contains(&quot;ERROR&quot;))\n        .forEach(System.out::println);\n<\/code><\/pre>\n<p> In diesem Beispiel werden wir alle Zeilen der geladenen Datei, die die Zeichenfolge &#8222;ERROR&#8220; enthalten, auf der Konsole ausgeben. Diese Methoden decken die g\u00e4ngigsten Szenarien f\u00fcr das Laden kleinerer Dateien ab und haben gemeinsam, dass sie vollst\u00e4ndig in den RAM geladen werden. Bei gro\u00dfen Dateien ist es ratsam, sie in St\u00fccken zu laden und sie sofort zu verarbeiten. Wir werden dies weiter unten demonstrieren.    <\/p>\n<h2>Laden einer gro\u00dfen Bin\u00e4rdatei mit BufferedInputStream<\/h2>\n<p> Die Bin\u00e4rdatei wird \u00fcber <em>InputStream<\/em> Byte f\u00fcr Byte geladen (bis zum Ende der Datei, wenn -1 zur\u00fcckgegeben wird), was bei gro\u00dfen Dateien recht lang ist. Dies kann durch das Laden von Daten \u00fcber <em>BufferedInputStream<\/em> beschleunigt werden. Diese Klasse umh\u00fcllt die Klasse <em>FileInputStream<\/em> und l\u00e4dt die Daten vom Betriebssystem nicht mehr Byte f\u00fcr Byte, sondern in 8 KB-Bl\u00f6cken, die im Speicher gepuffert werden. Das Lesen einer Datei erfolgt dann zwar auch Byte f\u00fcr Byte, ist aber viel schneller, weil es direkt aus dem Speicher erfolgt.   <\/p>\n<pre><code class=\"language-java\" data-line=\"\">import java.io.BufferedInputStream;\nimport java.io.FileInputStream;\n\nString fileName = &quot;fileName.dat&quot;;\ntry (FileInputStream is = new FileInputStream(fileName);\n     BufferedInputStream bis = new BufferedInputStream(is)) {\n    int b;\n    while ((b = bis.read()) != -1) {\n        \/\/ TODO: process b\n    }\n}\n<\/code><\/pre>\n<p> Das blockweise Laden einer Datei (sog. buffering) ist wesentlich schneller als das byteweise Lesen. <\/p>\n<h2>Laden einer gro\u00dfen Textdatei mit BufferedReader<\/h2>\n<p> Klasse <strong><em>FileReader<\/em><\/strong> kombiniert <strong><em>FileInputStream<\/em><\/strong> a <strong><em>InputStreamReader<\/em><\/strong>. Zum schnelleren Laden von Dateien verwenden wir die Klasse <strong><em>BufferedReader<\/em><\/strong>die die Klasse <strong><em>FileReader<\/em><\/strong> umh\u00fcllt und die Verwendung eines 8 KB gro\u00dfen Puffers zusammen mit einem zus\u00e4tzlichen Puffer f\u00fcr 8192 dekodierte Zeichen erm\u00f6glicht. Der Vorteil der Klasse <strong><em>BufferedReader<\/em><\/strong> ist, dass sie uns auch erlaubt, die Textdatei zeilenweise zu laden und zu verarbeiten (anstatt sie Zeichen f\u00fcr Zeichen zu laden und zu verarbeiten).   <\/p>\n<pre><code class=\"language-java\" data-line=\"\">import java.io.BufferedReader;\nimport java.io.FileReader;\n\nString fileName = &quot;fileName.dat&quot;;\ntry (FileReader reader = new FileReader(fileName);\n     BufferedReader bufferedReader = new BufferedReader((reader))) {\n    String line;\n    while ((line = bufferedReader.readLine()) != null) {\n        System.out.println(&quot;Line: &quot; + line);\n    }\n}\n<\/code><\/pre>\n<h2>Laden einer Datei in Teilen mit Scanner<\/h2>\n<p> Manchmal m\u00fcssen wir eine Datei in Teilen lesen, anstatt sie Zeile f\u00fcr Zeile zu lesen. Klasse <strong><em>Scanner<\/em><\/strong> teilt den Inhalt einer Datei mit Hilfe eines Trennzeichens, das ein beliebiger konstanter Wert sein kann, in Teile auf. \u00dcblicherweise wird diese Klasse f\u00fcr <strong>CSV-Dateien<\/strong> (comma-separated values) verwendet, d.h. f\u00fcr Dateien, die ein bestimmtes Format haben, bei dem die Daten durch Kommas getrennt sind und die Datei als Tabellenkalkulation in Excel verwendet werden kann. <\/p>\n<pre><code class=\"language-java\" data-line=\"\">import java.nio.file.Path;\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Scanner;\n\nList&lt;String&gt; words = new ArrayList&lt;&gt;();\nString fileName = &quot;fileName.csv&quot;;\nScanner scanner = new Scanner(Path.of(fileName));\nscanner.useDelimiter(&quot;,&quot;);\n\nwhile (scanner.hasNext()) {\n    String next = scanner.next();\n    words.add(next);\n}\nscanner.close();\n<\/code><\/pre>\n<p> In diesem Beispiel haben wir die CSV-Datei nach einzelnen Token geladen (anstelle des klassischen kommagetrennten zeilenweisen Ladens) und diese in einer Liste zur weiteren Verarbeitung gespeichert. In diesem Artikel haben wir die g\u00e4ngigsten Szenarien f\u00fcr das Abrufen von Daten aus einer Datei gezeigt. In Java k\u00f6nnen kleine Dateien einfach durch den Aufruf einer einzigen Funktion in den Speicher geladen und gespeichert werden, und selbst das Lesen und Verarbeiten gro\u00dfer Dateien kann in Java mithilfe von Pufferklassen effizient durchgef\u00fchrt werden.     Wenn du ein <a href=\"https:\/\/msg-life.sk\/de\/stellenangebote\/java-entwickler-senior\/\" target=\"_blank\" rel=\"noopener\">Java Programmierer<\/a> bist und nach Arbeit suchst, schau dir unsere <a href=\"https:\/\/msg-life.sk\/de\/mitarbeiter-benefits\/\" target=\"_blank\" rel=\"noopener\">Mitareiterbenefits <\/a> an und reagiere auf die <a href=\"https:\/\/msg-life.sk\/de\/stellenangebote\/\" target=\"_blank\" rel=\"noopener\">neuesten Stellenangebote.<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In unserer Arbeit konzentrieren wir uns auf 3 grundlegende Szenarien der Datenabfrage, die 90 Prozent der F\u00e4lle abdecken.<\/p>\n","protected":false},"author":14,"featured_media":3066,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[62],"tags":[],"class_list":["post-4455","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-java"],"acf":[],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/msgprogramator.sk\/de\/wp-json\/wp\/v2\/posts\/4455","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/msgprogramator.sk\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/msgprogramator.sk\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/msgprogramator.sk\/de\/wp-json\/wp\/v2\/users\/14"}],"replies":[{"embeddable":true,"href":"https:\/\/msgprogramator.sk\/de\/wp-json\/wp\/v2\/comments?post=4455"}],"version-history":[{"count":3,"href":"https:\/\/msgprogramator.sk\/de\/wp-json\/wp\/v2\/posts\/4455\/revisions"}],"predecessor-version":[{"id":8023,"href":"https:\/\/msgprogramator.sk\/de\/wp-json\/wp\/v2\/posts\/4455\/revisions\/8023"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/msgprogramator.sk\/de\/wp-json\/wp\/v2\/media\/3066"}],"wp:attachment":[{"href":"https:\/\/msgprogramator.sk\/de\/wp-json\/wp\/v2\/media?parent=4455"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/msgprogramator.sk\/de\/wp-json\/wp\/v2\/categories?post=4455"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/msgprogramator.sk\/de\/wp-json\/wp\/v2\/tags?post=4455"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}