Programming with Java, part 8

記事
IT・テクノロジー

1.About BufferedReader class

This is a continuation of the previous file input. The
FileReader class is inefficient because it reads characters
from the file one by one. The java.io package provides a
BufferedReader class that reads line by line from a file,
so let's see how to use this class with the following program.

----------------------- ReadTest2.java -------------------------------------
import java.io.*;

public class ReadTest2 {
    public static void main(String[] args) throws Exception {
        BufferedReader br = null;
        try {
            File file = new File("c:¥¥test¥¥sample.txt");
            FileReader fr = new FileReader(file);
            br = new BufferedReader(fr);

            String strLine;
            while ((strLine = br.readLine()) != null) {
                // Display the character in the file.
                System.out.println(strLine);
            }

        } catch(FileNotFoundException e) {
            System.out.println(e);
        } catch (IOException e) {
            System.out.println(e);
        } finally {
             // Close the file.
            if(br != null) br.close();
        }
    }        
}
---------------------------------------------------------------------------------

It is the same as last time until you create a FileReader
object. Use this object to create a BufferedReader object
with new. BufferedReader has a readLine method that
reads one line. This method recognizes either a new line
('\ n'), a carriage return('\ r'), or a carriage return and a
new line that follows, and returns one line as the return
value as a String type. When the end of the file is reached,
it returns null, so it keeps reading the file line by line until
null is returned in the while loop. After reading, close the file.


2.Example of using BufferedReader

You can use it in various ways by reading the file line by line
with BufferedReader. For example, in the case of a CSV file,
it is possible to divide the read line with a comma and
extract the data one by one. Since the String class has a
split method, it can be easily split as shown below.

            String strLine;
            while ((strLine = br.readLine()) != null) {
                String[] strArray = strLine.split(",");
            }

If there is one line like this in the CSV file,
aaa,bbb,ccc
aaa will be stored in strArray[0], bbb will be stored in
strArray[1], and ccc will be stored in strArray[2].


3.Measurement of processing speed

I tried to find out how much speed difference there is
between reading character by character with FileReader
and reading line by line with BufferedReader.
Without evidence, it's not very convincing to recommend
BufferedReader, so I hope you'll be judged by this result.

----------------------- ReadTest.java -------------------------------------
import java.io.*;

public class ReadTest {
 public static void main(String args[]) throws Exception{
  FileReader fr = null;
  try {
   File file = new File("sample.txt");
   fr = new FileReader(file);
   int iFileData;

   // Measurement starts.
   long startTime = System.currentTimeMillis();
   while((iFileData = fr.read()) != -1) {
   }

   // Measurement ends.
   long endTime = System.currentTimeMillis();
   System.out.println("Time(ms):" + (endTime - startTime));

  } catch(FileNotFoundException e) {
   System.out.println(e);
  } catch(IOException e) {
   System.out.println(e);
  } finally {
   // Close the file.
   if(fr != null) fr.close();
  }
 }
}
---------------------------------------------------------------------------------

----------------------- ReadTest2.java ------------------------------------
import java.io.*;

public class ReadTest2 {
 public static void main(String args[]) throws Exception{
  BufferedReader br = null;
  try {
   File file = new File("sample.txt");
   FileReader fr = new FileReader(file);
   br = new BufferedReader(fr);
   String strLine;

   // Measurement starts. 
   long startTime = System.currentTimeMillis();
   while((strLine = br.readLine()) != null) {
   }

   // Measurement ends.
   long endTime = System.currentTimeMillis();
   System.out.println("Time(ms):" + (endTime - startTime));

  } catch(FileNotFoundException e) {
   System.out.println(e);
  } catch(IOException e) {
   System.out.println(e);
  } finally {
   // Close the file.
   if(br != null) br.close();
  }
 }
}
---------------------------------------------------------------------------------

■ The size of the read file(sample.txt)
120KB(10,000 lines ✕ 10 half width numbers per line)

■ Average of 5 measurement results(millisecond)
FileReader:25ms
BufferedReader:12ms


BufferedReader was reading about twice as fast as FileReader.
I think it is better to choose BufferedReader because of
the usability of reading line by line and processing speed.


[Japanese]

1.BufferedReaderクラスについて

前回のファイル入力の続きです。FileReaderクラスはファイルから1文字ずつ読み込むため、効率が悪いです。java.ioパッケージには、ファイルから1行ずつ読み込むBufferedReaderクラスが用意されていますので、このクラスの使い方を下記のプログラムで見ていきます。

----------------------- ReadTest2.java ------------------------------------
import java.io.*;

public class ReadTest2 {
    public static void main(String[] args) throws Exception {
        BufferedReader br = null;
        try {
            File file = new File("c:¥¥test¥¥sample.txt");
            FileReader fr = new FileReader(file);
            br = new BufferedReader(fr);

            String strLine;
            while ((strLine = br.readLine()) != null) {
                // Display the character in the file.
                System.out.println(strLine);
            }

        } catch(FileNotFoundException e) {
            System.out.println(e);
        } catch (IOException e) {
            System.out.println(e);
        } finally {
             // Close the file.
            if(br != null) br.close();
        }
    }        
}
---------------------------------------------------------------------------------

FileReaderオブジェクトを作るまでは前回と同じです。このオブジェクトを使って、newでBufferedReaderオブジェクトを作ります。BufferedReaderには1行を読み込むメソッドreadLineがあります。このメソッドは、改行('\n')か、復帰('\r')、または復帰とそれに続く改行のいずれかを認識して読み込んだ1行を戻り値としてString型で返します。ファイルの終わりに達した場合はnullを返しますので、while()のループ内でnullが返されるまでファイルを1行ずつ読み込み続けます。読み込みが終わった後、ファイルを閉じます。


2.利用例

BufferedReaderで1行ずつファイルを読み込めば、様々な使い方ができます。例えばCSVファイルであれば、読み込んだ1行をカンマで分割してデータを1つずつ取り出すことも可能です。Stringクラスにはsplitメソッドがありますので、下記のように容易に分割できます。

            String strLine;
            while ((strLine = br.readLine()) != null) {
                String[] strArray = strLine.split(",");
            }

もしCSVファイルに
aaa,bbb,ccc
のような1行が記述されていた場合、strArray[0]にはaaa、
strArray[1]にはbbb、strArray[2]にはcccが格納されることになります。


3.処理速度の計測

FileReaderで1文字ずつ読み込むのと、BufferedReaderで1行ずつ読み込むのでは、どのくらいの速度差があるのか、調べてみました。エビデンスが無いと、BufferedReaderをお勧めする説得力が欠けてしまいますので、この結果を見て納得していただけるのではと思います。下記が使用したプログラムです。

----------------------- ReadTest.java -------------------------------------
import java.io.*;

public class ReadTest {
 public static void main(String args[]) throws Exception{
  FileReader fr = null;
  try {
   File file = new File("sample.txt");
   fr = new FileReader(file);
   int iFileData;

   // Measurement starts.
   long startTime = System.currentTimeMillis();
   while((iFileData = fr.read()) != -1) {
   }

   // Measurement ends.
   long endTime = System.currentTimeMillis();
   System.out.println("Time(ms):" + (endTime - startTime));

  } catch(FileNotFoundException e) {
   System.out.println(e);
  } catch(IOException e) {
   System.out.println(e);
  } finally {
   // Close the file.
   if(fr != null) fr.close();
  }
 }
}
---------------------------------------------------------------------------------

----------------------- ReadTest2.java ------------------------------------
import java.io.*;

public class ReadTest2 {
 public static void main(String args[]) throws Exception{
  BufferedReader br = null;
  try {
   File file = new File("sample.txt");
   FileReader fr = new FileReader(file);
   br = new BufferedReader(fr);
   String strLine;

   // Measurement starts. 
   long startTime = System.currentTimeMillis();
   while((strLine = br.readLine()) != null) {
   }

   // Measurement ends.
   long endTime = System.currentTimeMillis();
   System.out.println("Time(ms):" + (endTime - startTime));

  } catch(FileNotFoundException e) {
   System.out.println(e);
  } catch(IOException e) {
   System.out.println(e);
  } finally {
   // Close the file.
   if(br != null) br.close();
  }
 }
}
---------------------------------------------------------------------------------

■ 読み込んだファイル(sample.txt)のサイズ
120KB(1行につき半角数字10文字を1万行)

■ 5回の計測結果の平均(単位はミリ秒)
FileReader:25ms
BufferedReader:12ms


BufferedReaderの方がFileReaderよりも約2倍の速さで読み込んでいました。1行ずつ読み込む使い勝手の良さと処理速度から、BufferedReaderを選んだ方が良いと思います。
サービス数40万件のスキルマーケット、あなたにぴったりのサービスを探す