Javaでファイルのデータを読み書きするにはさまざまな方法があるようです。
ファイルからASCIIデータを読み取りたい。考えられる方法とその違いは何ですか?
ASCIIはTEXTファイルなので、読みには Readers
を使用します。 Javaは InputStreams
を使ったバイナリファイルからの読み込みもサポートしています。読み込むファイルが巨大な場合は、読み込みパフォーマンスを向上させるために BufferedReader
の上に FileReader
を使用します。
この記事 /を介してReader
の使い方
Thinking In Java という素晴らしい(まだ無料の)本をダウンロードして読むことをお勧めします。
Java 7の場合 :
new String(Files.readAllBytes(...))
(docs) または
Files.readAllLines(...)
Java 8の場合 :
Files.lines(..).forEach(...)
小さなファイルを読む私のお気に入りの方法は、BufferedReaderとStringBuilderを使うことです。それは非常に単純で要点までです(ただし、特に効果的というわけではありませんが、ほとんどの場合は十分に有効です)。
BufferedReader br = new BufferedReader(new FileReader("file.txt"));
try {
StringBuilder sb = new StringBuilder();
String line = br.readLine();
while (line != null) {
sb.append(line);
sb.append(System.lineSeparator());
line = br.readLine();
}
String everything = sb.toString();
} finally {
br.close();
}
Java 7以降は try-with-resources (自動クローズ)機能を使うべきだと言う人もいます。
try(BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
StringBuilder sb = new StringBuilder();
String line = br.readLine();
while (line != null) {
sb.append(line);
sb.append(System.lineSeparator());
line = br.readLine();
}
String everything = sb.toString();
}
私はこのように文字列を読むとき、私はとにかく行ごとにとにかくいくつかの文字列処理をしたいと思うので、この実装に行きます。
実際にファイルを文字列に読み込むだけの場合は、Apache Commons IO をクラスIOUtils.toString()メソッドで常に使用します。あなたはここでソースを見ることができます:
http://www.docjar.com/html/api/org/Apache/commons/io/IOUtils.Java.html
FileInputStream inputStream = new FileInputStream("foo.txt");
try {
String everything = IOUtils.toString(inputStream);
} finally {
inputStream.close();
}
そしてJava 7ではさらに簡単になります。
try(FileInputStream inputStream = new FileInputStream("foo.txt")) {
String everything = IOUtils.toString(inputStream);
// do something with everything string
}
最も簡単な方法は、JavaのScanner
クラスとFileReaderオブジェクトを使うことです。簡単な例:
Scanner in = new Scanner(new FileReader("filename.txt"));
Scanner
には、文字列、数字などを読み込むためのメソッドがいくつかあります。これについての詳細は、Javaのドキュメントページを参照してください。
たとえば、コンテンツ全体をString
に読み込むとします。
StringBuilder sb = new StringBuilder();
while(in.hasNext()) {
sb.append(in.next());
}
in.close();
outString = sb.toString();
また、特定のエンコーディングが必要な場合は、FileReader
の代わりにこれを使用できます。
new InputStreamReader(new FileInputStream(fileUtf8), StandardCharsets.UTF_8)
これが簡単な解決策です:
String content;
content = new String(Files.readAllBytes(Paths.get("sample.txt")));
外部ライブラリを使わずにこれを実行するもう1つの方法があります。
import Java.io.File;
import Java.io.FileReader;
import Java.io.IOException;
public String readFile(String filename)
{
String content = null;
File file = new File(filename); // For example, foo.txt
FileReader reader = null;
try {
reader = new FileReader(file);
char[] chars = new char[(int) file.length()];
reader.read(chars);
content = new String(chars);
reader.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(reader != null){
reader.close();
}
}
return content;
}
私はさまざまな方法をベンチマークしなければなりませんでした。私の調査結果についてコメントしますが、要するに、最速の方法はFileInputStreamの上に普通の古いBufferedInputStreamを使用することです。多くのファイルを読み込む必要がある場合、3つのスレッドで合計実行時間が約半分に短縮されますが、スレッドを追加すると、1つのスレッドよりも20スレッドで完了するまで3倍の時間がかかります。
仮定はあなたがファイルを読み、その内容で意味のあることをしなければならないということです。この例では、ログから行を読み取り、特定のしきい値を超える値を含む行を数えます。だから私はワンライナーのJava 8 Files.lines(Paths.get("/path/to/file.txt")).map(line -> line.split(";"))
はオプションではないと思っています。
私は、Java 1.8、Windows 7、およびSSDドライブとHDDドライブの両方でテストしました。
私は6つの異なる実装を書きました。
rawParse :FileInputStreamに対してBufferedInputStreamを使用してから、1バイトずつ読み込む行を切り取ります。これは他のシングルスレッドアプローチよりも優れていますが、非ASCIIファイルには非常に不便です。
lineReaderParse :FileReaderに対してBufferedReaderを使用し、1行ずつ読み取り、String.split()を呼び出して行を分割します。これは、rawParseよりも約20%遅くなります。
lineReaderParseParallel :これはlineReaderParseと同じですが、いくつかのスレッドを使用します。すべての場合において、これは全体的に最速のオプションです。
nioFilesParse :Java.nio.files.Files.lines()を使用する
nioAsyncParse :完了ハンドラとスレッドプールでAsynchronousFileChannelを使用してください。
nioMemoryMappedParse :メモリマップファイルを使用する。これは本当に悪い考えで、他のどの実装よりも実行時間が少なくとも3倍長くなります。
これらは、クアッドコアのi7およびSSDドライブで、それぞれ4 MBの204ファイルを読み取るための平均時間です。ファイルはディスクキャッシュを避けるためにその場で生成されます。
rawParse 11.10 sec
lineReaderParse 13.86 sec
lineReaderParseParallel 6.00 sec
nioFilesParse 13.52 sec
nioAsyncParse 16.06 sec
nioMemoryMappedParse 37.68 sec
SSDでの実行と、SSDであるHDDドライブでの実行との差が予想よりも約15%速いことがわかりました。これは、ファイルが断片化されていないHDD上に生成され、それらが順次読み取られるため、回転するドライブはほぼSSDと同じように動作する可能性があるためです。
NioAsyncParse実装のパフォーマンスが低いことに驚きました。間違った方法で実装したか、NIOと完了ハンドラを使用したマルチスレッド実装が、Java.io APIを使用したシングルスレッド実装と同じ(またはさらに悪い)動作をします。さらに、CompletionHandlerを使用した非同期構文解析は、コード行の長さがはるかに長く、古いストリームに対する単純な実装よりも正しく実装するのが面倒です。
現在では6つの実装とそれに続くそれらすべてを含むクラス、それに加えてファイル数、ファイルサイズ、および同時処理の程度で遊ぶことを可能にするパラメータ化可能なmain()メソッドが続きました。ファイルのサイズは、プラスマイナス20%の範囲で変化します。これは、すべてのファイルがまったく同じサイズであることによる影響を避けるためです。
rawParse
public void rawParse(final String targetDir, final int numberOfFiles) throws IOException, ParseException {
overrunCount = 0;
final int dl = (int) ';';
StringBuffer lineBuffer = new StringBuffer(1024);
for (int f=0; f<numberOfFiles; f++) {
File fl = new File(targetDir+filenamePreffix+String.valueOf(f)+".txt");
FileInputStream fin = new FileInputStream(fl);
BufferedInputStream bin = new BufferedInputStream(fin);
int character;
while((character=bin.read())!=-1) {
if (character==dl) {
// Here is where something is done with each line
doSomethingWithRawLine(lineBuffer.toString());
lineBuffer.setLength(0);
}
else {
lineBuffer.append((char) character);
}
}
bin.close();
fin.close();
}
}
public final void doSomethingWithRawLine(String line) throws ParseException {
// What to do for each line
int fieldNumber = 0;
final int len = line.length();
StringBuffer fieldBuffer = new StringBuffer(256);
for (int charPos=0; charPos<len; charPos++) {
char c = line.charAt(charPos);
if (c==DL0) {
String fieldValue = fieldBuffer.toString();
if (fieldValue.length()>0) {
switch (fieldNumber) {
case 0:
Date dt = fmt.parse(fieldValue);
fieldNumber++;
break;
case 1:
double d = Double.parseDouble(fieldValue);
fieldNumber++;
break;
case 2:
int t = Integer.parseInt(fieldValue);
fieldNumber++;
break;
case 3:
if (fieldValue.equals("overrun"))
overrunCount++;
break;
}
}
fieldBuffer.setLength(0);
}
else {
fieldBuffer.append(c);
}
}
}
lineReaderParse
public void lineReaderParse(final String targetDir, final int numberOfFiles) throws IOException, ParseException {
String line;
for (int f=0; f<numberOfFiles; f++) {
File fl = new File(targetDir+filenamePreffix+String.valueOf(f)+".txt");
FileReader frd = new FileReader(fl);
BufferedReader brd = new BufferedReader(frd);
while ((line=brd.readLine())!=null)
doSomethingWithLine(line);
brd.close();
frd.close();
}
}
public final void doSomethingWithLine(String line) throws ParseException {
// Example of what to do for each line
String[] fields = line.split(";");
Date dt = fmt.parse(fields[0]);
double d = Double.parseDouble(fields[1]);
int t = Integer.parseInt(fields[2]);
if (fields[3].equals("overrun"))
overrunCount++;
}
lineReaderParseParallel
public void lineReaderParseParallel(final String targetDir, final int numberOfFiles, final int degreeOfParalelism) throws IOException, ParseException, InterruptedException {
Thread[] pool = new Thread[degreeOfParalelism];
int batchSize = numberOfFiles / degreeOfParalelism;
for (int b=0; b<degreeOfParalelism; b++) {
pool[b] = new LineReaderParseThread(targetDir, b*batchSize, b*batchSize+b*batchSize);
pool[b].start();
}
for (int b=0; b<degreeOfParalelism; b++)
pool[b].join();
}
class LineReaderParseThread extends Thread {
private String targetDir;
private int fileFrom;
private int fileTo;
private DateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private int overrunCounter = 0;
public LineReaderParseThread(String targetDir, int fileFrom, int fileTo) {
this.targetDir = targetDir;
this.fileFrom = fileFrom;
this.fileTo = fileTo;
}
private void doSomethingWithTheLine(String line) throws ParseException {
String[] fields = line.split(DL);
Date dt = fmt.parse(fields[0]);
double d = Double.parseDouble(fields[1]);
int t = Integer.parseInt(fields[2]);
if (fields[3].equals("overrun"))
overrunCounter++;
}
@Override
public void run() {
String line;
for (int f=fileFrom; f<fileTo; f++) {
File fl = new File(targetDir+filenamePreffix+String.valueOf(f)+".txt");
try {
FileReader frd = new FileReader(fl);
BufferedReader brd = new BufferedReader(frd);
while ((line=brd.readLine())!=null) {
doSomethingWithTheLine(line);
}
brd.close();
frd.close();
} catch (IOException | ParseException ioe) { }
}
}
}
nioFilesParse
public void nioFilesParse(final String targetDir, final int numberOfFiles) throws IOException, ParseException {
for (int f=0; f<numberOfFiles; f++) {
Path ph = Paths.get(targetDir+filenamePreffix+String.valueOf(f)+".txt");
Consumer<String> action = new LineConsumer();
Stream<String> lines = Files.lines(ph);
lines.forEach(action);
lines.close();
}
}
class LineConsumer implements Consumer<String> {
@Override
public void accept(String line) {
// What to do for each line
String[] fields = line.split(DL);
if (fields.length>1) {
try {
Date dt = fmt.parse(fields[0]);
}
catch (ParseException e) {
}
double d = Double.parseDouble(fields[1]);
int t = Integer.parseInt(fields[2]);
if (fields[3].equals("overrun"))
overrunCount++;
}
}
}
nioAsyncParse
public void nioAsyncParse(final String targetDir, final int numberOfFiles, final int numberOfThreads, final int bufferSize) throws IOException, ParseException, InterruptedException {
ScheduledThreadPoolExecutor pool = new ScheduledThreadPoolExecutor(numberOfThreads);
ConcurrentLinkedQueue<ByteBuffer> byteBuffers = new ConcurrentLinkedQueue<ByteBuffer>();
for (int b=0; b<numberOfThreads; b++)
byteBuffers.add(ByteBuffer.allocate(bufferSize));
for (int f=0; f<numberOfFiles; f++) {
consumerThreads.acquire();
String fileName = targetDir+filenamePreffix+String.valueOf(f)+".txt";
AsynchronousFileChannel channel = AsynchronousFileChannel.open(Paths.get(fileName), EnumSet.of(StandardOpenOption.READ), pool);
BufferConsumer consumer = new BufferConsumer(byteBuffers, fileName, bufferSize);
channel.read(consumer.buffer(), 0l, channel, consumer);
}
consumerThreads.acquire(numberOfThreads);
}
class BufferConsumer implements CompletionHandler<Integer, AsynchronousFileChannel> {
private ConcurrentLinkedQueue<ByteBuffer> buffers;
private ByteBuffer bytes;
private String file;
private StringBuffer chars;
private int limit;
private long position;
private DateFormat frmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public BufferConsumer(ConcurrentLinkedQueue<ByteBuffer> byteBuffers, String fileName, int bufferSize) {
buffers = byteBuffers;
bytes = buffers.poll();
if (bytes==null)
bytes = ByteBuffer.allocate(bufferSize);
file = fileName;
chars = new StringBuffer(bufferSize);
frmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
limit = bufferSize;
position = 0l;
}
public ByteBuffer buffer() {
return bytes;
}
@Override
public synchronized void completed(Integer result, AsynchronousFileChannel channel) {
if (result!=-1) {
bytes.flip();
final int len = bytes.limit();
int i = 0;
try {
for (i = 0; i < len; i++) {
byte by = bytes.get();
if (by=='\n') {
// ***
// The code used to process the line goes here
chars.setLength(0);
}
else {
chars.append((char) by);
}
}
}
catch (Exception x) {
System.out.println(
"Caught exception " + x.getClass().getName() + " " + x.getMessage() +
" i=" + String.valueOf(i) + ", limit=" + String.valueOf(len) +
", position="+String.valueOf(position));
}
if (len==limit) {
bytes.clear();
position += len;
channel.read(bytes, position, channel, this);
}
else {
try {
channel.close();
}
catch (IOException e) {
}
consumerThreads.release();
bytes.clear();
buffers.add(bytes);
}
}
else {
try {
channel.close();
}
catch (IOException e) {
}
consumerThreads.release();
bytes.clear();
buffers.add(bytes);
}
}
@Override
public void failed(Throwable e, AsynchronousFileChannel channel) {
}
};
すべてのケースの完全に実行可能な実装
https://github.com/sergiomt/javaiobenchmark/blob/master/FileReadBenchmark.Java
これが3つの動作確認済みメソッドです。
BufferedReader
を使うpackage io;
import Java.io.*;
public class ReadFromFile2 {
public static void main(String[] args)throws Exception {
File file = new File("C:\\Users\\pankaj\\Desktop\\test.Java");
BufferedReader br = new BufferedReader(new FileReader(file));
String st;
while((st=br.readLine()) != null){
System.out.println(st);
}
}
}
Scanner
を使うpackage io;
import Java.io.File;
import Java.util.Scanner;
public class ReadFromFileUsingScanner {
public static void main(String[] args) throws Exception {
File file = new File("C:\\Users\\pankaj\\Desktop\\test.Java");
Scanner sc = new Scanner(file);
while(sc.hasNextLine()){
System.out.println(sc.nextLine());
}
}
}
FileReader
を使うpackage io;
import Java.io.*;
public class ReadingFromFile {
public static void main(String[] args) throws Exception {
FileReader fr = new FileReader("C:\\Users\\pankaj\\Desktop\\test.Java");
int i;
while ((i=fr.read()) != -1){
System.out.print((char) i);
}
}
}
Scanner
クラスを使用してループなしでファイル全体を読むpackage io;
import Java.io.File;
import Java.io.FileNotFoundException;
import Java.util.Scanner;
public class ReadingEntireFileWithoutLoop {
public static void main(String[] args) throws FileNotFoundException {
File file = new File("C:\\Users\\pankaj\\Desktop\\test.Java");
Scanner sc = new Scanner(file);
sc.useDelimiter("\\Z");
System.out.println(sc.next());
}
}
org.Apache.commons.io.FileUtils
内のメソッドもとても便利です。例えば:
/**
* Reads the contents of a file line by line to a List
* of Strings using the default encoding for the VM.
*/
static List readLines(File file)
あなたはそのテキストで何をしたいですか?ファイルはメモリに収まるくらい小さいですか?私はあなたの必要性のためにファイルを扱う最も簡単な方法を見つけることを試みるでしょう。 FileUtilsライブラリはこれを非常によく扱っています。
for(String line: FileUtils.readLines("my-text-file"))
System.out.println(line);
私は Javaでファイルを読む15の方法を文書化しました それからさまざまなファイルサイズでスピードをテストしました - 1 KBから1 GBまで、そしてこれを行うためのトップ3の方法は次のとおりです。
Java.nio.file.Files.readAllBytes()
Java 7、8、および9で動作することがテスト済み。
import Java.io.File;
import Java.io.IOException;
import Java.nio.file.Files;
public class ReadFile_Files_ReadAllBytes {
public static void main(String [] pArgs) throws IOException {
String fileName = "c:\\temp\\sample-10KB.txt";
File file = new File(fileName);
byte [] fileBytes = Files.readAllBytes(file.toPath());
char singleChar;
for(byte b : fileBytes) {
singleChar = (char) b;
System.out.print(singleChar);
}
}
}
Java.io.BufferedReader.readLine()
Java 7、8、9で動作することがテスト済み。
import Java.io.BufferedReader;
import Java.io.FileReader;
import Java.io.IOException;
public class ReadFile_BufferedReader_ReadLine {
public static void main(String [] args) throws IOException {
String fileName = "c:\\temp\\sample-10KB.txt";
FileReader fileReader = new FileReader(fileName);
try (BufferedReader bufferedReader = new BufferedReader(fileReader)) {
String line;
while((line = bufferedReader.readLine()) != null) {
System.out.println(line);
}
}
}
}
Java.nio.file.Files.lines()
これはJava 8および9で動作することがテストされていますが、ラムダ式が必要なためJava 7では動作しません。
import Java.io.File;
import Java.io.IOException;
import Java.nio.file.Files;
import Java.util.stream.Stream;
public class ReadFile_Files_Lines {
public static void main(String[] pArgs) throws IOException {
String fileName = "c:\\temp\\sample-10KB.txt";
File file = new File(fileName);
try (Stream linesStream = Files.lines(file.toPath())) {
linesStream.forEach(line -> {
System.out.println(line);
});
}
}
}
以下はJava 8の方法でそれを行うことのワンライナーです。 text.txt
ファイルがEclipseのプロジェクトディレクトリのルートにあると仮定します。
Files.lines(Paths.get("text.txt")).collect(Collectors.toList());
これは、 FileReader の代わりに File を使用し、さらにファイルの内容をステップスルーするという繰り返しを除いて、基本的にJesus Ramosの回答とまったく同じです。
Scanner in = new Scanner(new File("filename.txt"));
while (in.hasNext()) { // Iterates each line in the file
String line = in.nextLine();
// Do something with line
}
in.close(); // Don't forget to close resource leaks
... FileNotFoundException
をスローします
BufferedReaderを使用する:
import Java.io.BufferedReader;
import Java.io.FileNotFoundException;
import Java.io.FileReader;
import Java.io.IOException;
BufferedReader br;
try {
br = new BufferedReader(new FileReader("/fileToRead.txt"));
try {
String x;
while ( (x = br.readLine()) != null ) {
// Printing out each line in the file
System.out.println(x);
}
}
catch (IOException e) {
e.printStackTrace();
}
}
catch (FileNotFoundException e) {
System.out.println(e);
e.printStackTrace();
}
おそらく、バッファ付きI/Oほど速くはありませんが、かなり簡潔です。
String content;
try (Scanner scanner = new Scanner(textFile).useDelimiter("\\Z")) {
content = scanner.next();
}
\Z
パターンはScanner
に区切り文字がEOFであることを伝えます。
私はそれが今のところ他の答えでまだ言及されているのを見ません。しかし、「最高」がスピードを意味するのであれば、新しいJava I/O(NIO)が最速のパフォーマンスを提供する可能性がありますが、習得しやすい人にとっては必ずしも容易ではありません。
http://download.Oracle.com/javase/tutorial/essential/io/file.html
バッファ付きストリームクラスは実際にははるかに高性能であるため、NIO.2 APIには、これらのストリームクラスを特に返すメソッドが含まれているため、アプリケーションでバッファ付きストリームを常に使用することをお勧めします。
これが一例です。
Path path = Paths.get("/myfolder/myfile.ext");
try (BufferedReader reader = Files.newBufferedReader(path)) {
// Read from the stream
String currentLine = null;
while ((currentLine = reader.readLine()) != null)
//do your code here
} catch (IOException e) {
// Handle file I/O exception...
}
このコードを置き換えることができます
BufferedReader reader = Files.newBufferedReader(path);
と
BufferedReader br = new BufferedReader(new FileReader("/myfolder/myfile.ext"));
Java NIOとIOの主な使い方を学ぶには this の記事をお勧めします。
Javaでファイルからデータを読み取る最も簡単な方法は、ファイルの読み取りに File クラスを使用し、ファイルの内容の読み取りに Scanner クラスを使用することです。
public static void main(String args[])throws Exception
{
File f = new File("input.txt");
takeInputIn2DArray(f);
}
public static void takeInputIn2DArray(File f) throws Exception
{
Scanner s = new Scanner(f);
int a[][] = new int[20][20];
for(int i=0; i<20; i++)
{
for(int j=0; j<20; j++)
{
a[i][j] = s.nextInt();
}
}
}
シモンズ:Java.util。*をインポートすることを忘れないでください。スキャナーが動作するために。
これは質問に対する正確な答えではないかもしれません。 Javaコードでファイルへのパスを明示的に指定せずに、コマンドライン引数として読み込むという、ファイルを読み込む別の方法です。
次のコードでは、
import Java.io.BufferedReader;
import Java.io.InputStreamReader;
import Java.io.IOException;
public class InputReader{
public static void main(String[] args)throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String s="";
while((s=br.readLine())!=null){
System.out.println(s);
}
}
}
先に進み、次のように実行してください。
Java InputReader < input.txt
これはinput.txt
の内容を読み、あなたのコンソールにそれを印刷するでしょう。
次のようにコマンドラインからSystem.out.println()
を特定のファイルに書き込むようにすることもできます。
Java InputReader < input.txt > output.txt
これはinput.txt
から読み取り、output.txt
に書き込みます。
Guava これにワンライナーを提供します。
import com.google.common.base.Charsets;
import com.google.common.io.Files;
String contents = Files.toString(filePath, Charsets.UTF_8);
Cactoos 宣言的なワンライナーを教えてください:
new TextOf(new File("a.txt")).asString();
JSFベースのMaven Webアプリケーションの場合は、ClassLoaderとResources
フォルダを使用して、必要なファイルを読み込むだけです。
Apache Commons IO依存関係をあなたのPOMに入れてください:
<dependency>
<groupId>org.Apache.commons</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.2</version>
</dependency>
それを読むために下記のコードを使用してください(例えば、以下は.jsonファイルを読んでいます):
String metadata = null;
FileInputStream inputStream;
try {
ClassLoader loader = Thread.currentThread().getContextClassLoader();
inputStream = (FileInputStream) loader
.getResourceAsStream("/metadata.json");
metadata = IOUtils.toString(inputStream);
inputStream.close();
}
catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return metadata;
テキストファイル、.propertiesファイル、 _ xsd _ schemasなどについても同じことができます。
ReadAllLinesとjoin
メソッドを使用すると、ファイル全体の内容を1行で取得できます。
String str = String.join("\n",Files.readAllLines(Paths.get("e:\\text.txt")));
デフォルトではUTF-8エンコーディングが使用され、ASCIIデータが正しく読み取られます。
ReadAllBytesも使えます。
String str = new String(Files.readAllBytes(Paths.get("e:\\text.txt")), StandardCharsets.UTF_8);
私はreadAllBytesがより速くより正確であると思います、なぜならそれは新しい行を\n
で置き換えず、また新しい行が\r\n
であるかもしれないからです。どちらが適しているかはあなたのニーズによります。
これが構造の単純さに関するものである場合は、 Java kiss を使用してください。
import static kiss.API.*;
class App {
void run() {
String line;
try (Close in = inOpen("file.dat")) {
while ((line = readLine()) != null) {
println(line);
}
}
}
}