Java에서 File을 다루는데 가장 많이 사용하는 클래스 중 하나가 BufferedReader일 것이다.
그러나 쓰다보니 몇가지 문제점을 발견하게 되어서 적어보고자 한다.
1. BufferedReader의 장단점(?)
- 장점
가장 쓰기 좋았던 점은 쓰기 쉽다는 점이다.
InputStreamReader를 이용하면 UTF-8 Encoding을 통한 한글 처리가 쉽다.
ex) BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(strFileName),"UTF-8"));
또한 readLine()함수를 지원함으로써 파일을 읽어들이기도 편하다.
skip()함수를 통한 position 이동도 가능하며 Buffer를 이용(기본 사이즈는 16384Byte라고 함)하
기 때문에 읽는 속도도 다른 클래스에 비해서 빠르다.
- 단점
대용량의 데이터를 다루는 경우 BufferedReader의 한계를 느낄 수 있었다.
단순히 file을 읽어들이는 속도는 문제가 아닌데 skip()함수가 문제가 되었다.
skip()함수는 seek처럼 file pointer만을 이동시키는 것이 아닌 실제로 데이터를 읽어들인다.
즉, 사용은 하지 않더라도 데이터를 실제 메모리에 올려서 skip을 수행한다.
생각에는 skip이 byte단위가 아닌 character기준으로 수행되므로 실제 character수를 count하기
위해서는 실제로 읽어서 캐릭터 처리를 해야하는 것 같다.
여튼 이런 문제로 인해 실제 프로젝트에서 500MB 이상에 대해 skip을 수행하자 상당한 성능 저하
를 일으켰다.
테스트 해본 결과 BufferedReader에서 데이터를 읽어서 가공하는 경우 초당 30MB정도 (프로그
램에서의 데이터 가공시간 포함) 처리가능한데 비해 100MB skip당 1초정도의 시간이 걸렸다.
데이터 가공시간을 생각하지 않는다고 하면 BufferedReader를 통해서 데이터를 읽어들이는 속도
의 1/2정도의 시간이 skip에 소모된다. 이는 대용량 데이터를 seek를 통해서 처리해야하는 경우
BufferedReader를 사용하기 어려운 제약 사항이 되어 버렸다.
2. RandomAccessFile의 장단점(?)
위의 BufferedReader의 skip 한계를 해결하기 위해서 RandomAccessFile에 대해 알아봤다.
- 장점
RandomAccessFile의 seek을 제공하며 테스트 해본 결과 seek은 file pointer만을 이동시킴으
로써 seek에 걸리는 시간은 사실상 0이다.
또한 getChannel()함수를 통해서 FileChannel을 얻을 수 있어 NIO방식의 File IO 지원이 가능
하다.
- 단점
성능이 떨어지고 한글 처리가 어렵다.
RandomAccessFile도 readLine()을 지원한다. 그러나 readLine()을 통해서 데이터를 읽을 경
우 데이터의 인코딩 타입이 ISO-8859-1이 된다. 즉, ISO-8859-1외의 인코딩 방식을 사용하고
있는 경우에는 이의 변환이 필요하게 된다.
ex) RandomAccessFile reader = new RandomAccessFile(strFileName, "r");
String strLine = new String(reader.readLine().getBytes("ISO-8859-1"),"UTF-8");
위에서 보다시피 bytes변환후 다시 string으로 만들어야 한다. 이는 당연히 엄청난 성능 저하를
가져온다. 그러나 위와 같은 변환을 거치지 않는다면 한글의 처리를 불가능하다.
또한 성능 면에서도 엄청 느리다. 간단히 테스트 해본 결과 BufferedReader에 비해 10배 느리다.
이는 1 Byte씩 읽어들이는 방식의 한계라고 하겠다.
즉, 성능적인 측면 때문에 BufferedReader의 대체 클래스로는 사용이 불가능 하다.
위의 두 클래스들의 한계(문제?)에 의해 Java를 통해서 대용량 파일을 처리하는데 있어서 성능의
문제가 발생하고 말았다.
실제 프로젝트에서의 맞닥뜨린 문제와 그 해결책은 글이 너무 길어진 관계로 다음 글에서 다루고자 한다.
'Language > Java' 카테고리의 다른 글
Retry JDBC Query execution under specified sql error code (Vendor specific) (0) | 2012.05.24 |
---|---|
[펌] BufferedReader와 RandonAccessFile을 연계한 대용량 파일 처리 (0) | 2012.05.21 |
Start java application in background mode on Window (0) | 2012.05.06 |
[펌] 프로그램의 프로세스를 하나만 허용하기 (0) | 2012.05.05 |
[펌] Interrupting Java threads (0) | 2012.04.03 |