การอ่านไฟล์ขนาดใหญ่ด้วย Java

คำเตือน: บทความชุด best practice ไม่เหมาะสำหรับผู้ที่มีความคิดว่า “เขียนๆ ไปเถอะ มันก็ใช้งานได้เหมือนกัน”

ผมมีไฟล์ขนาดประมาณ 100 MB อยู่หนึ่งไฟล์ ด้วยความเคยชินผมก็ใช้ Scanner ทำการอ่านไฟล์แล้วมีความรู้สึกว่ามันทำงานช้ามาก ประมาณ 7 วินาที แต่ก็อาจจะเพราะไฟล์มีขนาดใหญ่ทำให้ใช้เวลานานเคยไม่ได้คิดอะไรมาก แต่ลองมาคิดดูแล้ว ผมเคยอ่าน log ที่มีขนาด 1 GB ใช้เวลาเป็นนาที ก็เลยคิดว่าน่าจะมีวิธีการอ่านไฟล์ที่มีประสิทธิภาพมากกว่านี้ ก็เลยทำการเขียนโปรแกรมทดสอบเวลาที่โปรแกรมทำงานกับการใช้ memory ว่ามีคลาสใหนที่ใช้ในการอ่านไฟล์แล้วเร็ว และกิน memory น้อยบ้าง

เตรียมพร้อม


ผมเขียน Java อ่านไฟล์โดยใช้คลาส Scanner และ Buffered และมีโค้ดในการวัดความเร็วและอัตราการใช้ memory แบบบ้านๆ ไว้ดังนี้

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Scanner;

public class App {

	private static final String filepath = "e:/workspace/data2.txt";

	public static void main(String[] args) throws Exception {

		long beginTime = System.currentTimeMillis();

		scanner();
		// bufferedReader();

		long endTime = System.currentTimeMillis();
		System.out.println("Used time: " + (endTime - beginTime) + " millisec");

		showUsedMemory();
	}

	private static void showUsedMemory() {
		Runtime runtime = Runtime.getRuntime();
		long usedMemory = runtime.totalMemory() - runtime.freeMemory();
		System.out.println("Used Memory: " + (usedMemory / 1024) + " kb");
	}

	private static void bufferedReader() throws FileNotFoundException,
			IOException {
		BufferedReader br = null;
		String line = "";
		int count = 0;
		try {
			br = new BufferedReader(new FileReader(new File(filepath)));
			while ((line = br.readLine()) != null) {
				count++;
			}
			System.out.println("Count: " + count);
		} finally {
			if (br != null) {
				br.close();
			}
		}
	}

	private static void scanner() throws FileNotFoundException {
		Scanner scan = new Scanner(new FileReader(new File(filepath)));
		try {
			int count = 0;
			while (scan.hasNextLine()) {
				String line = scan.nextLine();
				count++;
			}
			System.out.println("Count: " + count);
		} finally {
			scan.close();
		}
	}

}

Scanner


เมื่อผมรันเมธอดที่ใช้ Scanner ผลลัพธ์ที่ได้คือ

Count: 402780
Used time: 7786 millisec
Used Memory: 1817 kb

BufferedReader


เมื่อผมรันเมธอดที่ใช้ BufferedReader ผลลัพธ์ที่ได้คือ

Count: 402780
Used time: 587 millisec
Used Memory: 2734 kb

สรุป


อัตราการใช้ Memory ไม่ต่างกันมาก แต่เวลาที่ใช้ต่างกันลิบ ในโปรเจคต่อๆ ไปผมเลือก BufferedReader แทน Scanner แน่นอน

Class Time (millisec) Memory (kb)
Scanner 7786 1817
BufferedReader 587 2734

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s