-
[C#] StreamReader : 대용량 텍스트 파일 읽기프로그래밍/C# 2020. 9. 22. 07:20
StreamReader 생성자
우선 StreamReader는 간편하게 파일을 읽어오고 싶을 때 사용하는 클래스입니다.
아래와 같이 생성하셔서 사용하시면 됩니다. 또한, 한글을 사용하자 하실 때는 인코딩 UTF8을 설정해주세요.
StreamReader sr = new StreamReader(FilePath, Encoding.UTF8);
StreamReader 속성
1. EndOfStream
: 현재 스트림 위치가 스트림의 끝에 있으면 true이고, 없으면 false입니다. 보통 속성은 " () " 를 사용하지 않고 메서드는 " () " 를 사용합니다.
StreamReader 주요 메서드
1. Read()
: 입력 스트림에서 다음 문자를 읽고 문자 위치를 한 문자씩 앞으로 이동합니다.
매개변수 없이 Read() 를 사용하는 경우 개체로 표시되는 입력 스트림의 다음 문자를 반환하게 되고, 사용할 수 있는 문자가 더 이상 없는 경우에는 -1을 반환하게 됩니다.
while(sr.EndOfStream == false) { Console.WriteLine(sr.Read()); }
2. Read( Char [], Int32, Int32 )
: 현재 스트림에서 지정된 최대 문자를 지정된 인덱스부터 버퍼로 읽어 들입니다.
Read 함수에 인자를 설정할 경우 읽어드린 문자의 수를 반환하고 매개변수인 Buffer에 읽어드린 내용을 저장합니다.
- Char [] : buffer 변수
- int32 : buffer의 시작 인덱스
- int32 : buffer에 한 번에 담을 문자의 크기
int bufferSize = 4096; char[] buffer = new char[bufferSize]; while (sr.EndOfStream == false) { int CharCount = sr.Read(buffer, 0, bufferSize); Console.WriteLine("글자수 : " + CharCount + ", 내용 : " + buffer); }
3. ReadLine()
: 현재 스트림에서 한 줄의 문자를 읽고 데이터를 문자열로 반환합니다.
읽어드린 내용을 String으로 반환하기 때문에 즉시 출력이 가능합니다.
while (sr.EndOfStream == false) { Console.WriteLine(sr.ReadLine()); }
4. ReadToEnd()
: 가장 자주 사용하는 메서드로 현재 위치에서 마지막까지의 전체 내용을 String으로 반환해줍니다.
string allOfContents = sr.ReadToEnd(); Console.WriteLine(allOfContents);
대용량 텍스트 파일 읽기
이제 대용량 텍스트를 읽는 방법입니다. 보통 ReadToEnd() 메서드를 사용하면 1GB 정도의 내용도 한 번에 읽는 것이 가능합니다. 하지만 10Gb, 100GB 로 내용이 커지면 OutOfMemory라는 오류가 발생하게 됩니다.
결론만 말하자면 반복문을 사용하면서 읽어온 내용을 바로 쓰고 내용을 비워주는 작업이 필요합니다. 그러기 위해서는 StreamReader 와 StreamWriter 를 동시에 선언해서 사용해야 하는데, 코드를 보시면서 이해하시면 편할 것 같습니다.
참고 : StreamWriter 의 생성자에서 파일 경로에 지정한 파일이 없는 경우 텍스트 파일을 만들어 저장하게 됩니다.
StreamWriter sw = new StreamWriter(textBoxSnpFilePath.Text + ".new", false); StreamReader sr = new StreamReader(textBoxSnpFilePath.Text, Encoding.UTF8); int bufferSize = 4096; // Basic Stream Size int remainBuffer = 0; char[] buffer = new char[bufferSize]; while(sr.EndOfStream == false) { remainBuffer = sr.Read(buffer, 0, bufferSize); if (sr.EndOfStream) break; sw.Write(buffer); } // write reamin contents for(int i=0; i< remainBuffer; i++) { sw.Write(buffer[i]); }
주의해야 할 부분은 Read() 메서드를 통해서 매번 4096개의 글자를 읽어드립니다. 하지만 마지막 부분은 정확히 나누어 떨어지는 글자 수가 아니라면 4096 보다 작은 문자 수를 읽어드리게 됩니다. 이때 직전에 읽어드렸던 내용들이 남아있게 되는데, 이 부분을 따로 for문을 돌려 처리해줄 필요가 있습니다. 언제나 질문은 댓글에 달아주시면 감사하겠습니다. ㅎㅎ
'프로그래밍 > C#' 카테고리의 다른 글
[C#] virtual, abstract, interface (2) 2020.11.05 [C#] Delegate 를 이용해 폼 간 데이터 전송하기 (0) 2020.10.08 [C#] TextBox 에 찾기바꾸기 기능 활용 (0) 2020.09.29 [C#] Column editing function in TextBox (0) 2020.09.29 [C#] Scintillanet 이란 ? (0) 2020.09.25