본문 바로가기

C#/파일 처리

C#에서 텍스트 파일 읽기 (파일 입력)

1. 텍스트 파일 한 행씩 읽기

 

StreamReader 클래스를 사용

using System.IO;
...
var filePath = @"C:\Example.txt";
if (File.Exists(filePath))
{
    //파일을 사용한 후 닫아주기위해 using으로 묶어준다.
    using(var reader = new StreamReader(filePath, Encoding UTF8))
    {
        //파일의 마지막까지 읽어 들였는지를 EndOfStream 속성을 보고 조사
        while (!reader.EndOfStream)
        {
            //ReadLine 메서드로 한 행을 읽어 들여 line 변수에 대입
            var line = reader.ReadLine();
            Console.WriteLIne(line);
        }
    }
}

 

 

File.Exists이라는 정적 메서드를 통해 파일이 존재하는지 여부를 미리 확인하고 존재할 때만 읽어들이는 처리를 수행한다.

 

파일을 읽어 들이려면 일단 파일을 열어야 한다. 

StreamReader의 인스턴스를 생성하면 파일을 여는 처리도 함께 수행된다.

파일의 경로문자 인코딩을 인수에 전달해서 파일을 연다.

 

StreamReader의 생성자에 있는 두 번째 인수를 생략하면 UTF-8이 지정됐다고 간주한다.

euc-kr 형식으로 저장된 텍스트 파일을 읽을 경우에는 Encoding.GetEncoding(“euc-kr”)이라고 지정한다.

 

using문이 필요한 이유는 using문 밖으로 벗어났을 때 Dispose() 메서드를 자동으로 호출해서 리소스를 확실하게 삭제하기 위함이다.

이번 예에서는 파일을 닫는 역할을 한다.

 

 

2. 텍스트 파일 한꺼번에 읽기

 

/////////////////////////////////////////   추천하지 않는 방법   ////////////////////////////////////////////////////////

 

비교적 작은 파일이라면 File 클래스에 있는 ReadAllLInes라는 정적 메서드를 사용해 한꺼번에 메모리로 읽어 들이는 것이 편리하다.

var filePath = @"C:\Example.txt";
var lines = File.ReadAllLines(filePath, Encoding.UTF8);
foreach (var line in lines)
{
    Console.WriteLine(line);
}

ReadAllLines 메서드는 모든 행을 읽어 들이고 그 결과를 string[] 형으로 반환한다.
거대한 텍스트 파일이라면 끝까지 읽는 데 처리 지연이 발생하고 메모리를 압박하므로 주의해야 한다.
ReadAllLines 메서드는 작은 파일 전용이라고 생각하면 된다.

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

 

 

//추천하는 방법//>> .NET 프레임워크 4 이상의 환경에서는 IEnumerable<string>을 반환하는 ReadLines라는 정적 메서드를 이용할 수 있다.

var filePath = @"C:\Example.txt";
var lines = File.ReadLines(filePath, Encoding.UTF8);
foreach (var line in lines)
{
    Console.WriteLine(line);
}

 

 

[“ReadAllLines”, “ReadLines” 차이 : 읽어들이는 방법]


ReadAllLines : 모든 행을 읽어 들여 배열로 변환한다.

ReadLines : 호출한 시점에 읽기 작업이 실행된다. 코드의 겉모습은 ReadAllLines과 닮았지만 내부에서 실행되는 처리는 StreamReader 클래스에 있는 ReadLine 메서드를 사용한 예에 가깝다고 할 수 있다.

 

 

IEnumerable<string>을 반환하는 ReadLines 메서드는 LINQ를 조합해서 다채로운 처리를 깨끗하게 작성하게 해줍니다.

ReadLines 메서드는 ReadAllLines 메서드를 대체한 것이라고 말해도 될 것이다.

.NET 프레임워크 4 이상의 환경에서는 ReadLines  메서드를 사용하는게 좋다.

 

 

 

3. ReadLines 메서드LINQ의 조합

 

1) 첫 n행을 읽는다.

//첫 10행만 읽은 후 배열에 저장.
//ReadAllLines 메서드와 달리 파일 마지막까지 읽지 않는다.
var lines = File.ReadLines(filePath, Encoding.UTF8).Take(15).ToArray();

 

 

2) 조건에 일치하는 행의 개수를 센다.

//"Sword"라는 문자열이 포함되어 있는 행의 개수를 센다
var count = File.ReadLines(filePath, Encoding.UTF8).Count(s => s.Contains(“Sword”));

 

 

3) 조건에 일치한 행만 읽는다.

//빈 문자열이나 공백인 행 이외의 행을 읽은 후 배열에 저장.
var lines = File.ReadLines(filePath.Encoding.UTF8).Where(s => !String.IsNullOrWhiteSpace(s)).ToArray();

 

 

4) 조건에 일치하는 행이 존재하는지 여부 조사

 

아래 코드는 숫자로만 구성된 행이 존재하는지 조사한다.

//All 메서드는 빈 시퀀스에 대해 true를 반환하므로 숫자만으로 구성된 행이 존재하지 않아도 빈 행이 있으면 exists 변수에는 true가 대입된다.
//이를 방지하기 위해 Where 메서드를 통해 빈 행을 제외한 후에 Any 메서드를 호출
//Where 메서드를 사용하지 않으면 빈 행에 대해서도 s.All(c => Char.IsDigit(c))가 호출
var exists = File.ReadLines(filePath, Encoding.UTF8).Where(s => !String.IsNullOrEmpty(s)).Any(s => s.All(c => Char.IsDigit(c)));

 

 

5) 중복된 행을 제외하고 나열

//중복된 행을 제외하고 행의 길이가 짧은 순서로 정렬한 후 배열에 저장.
var lines = File.Readlines(filePath, Encoding.UTF8).Distinct().OrderBy(s => s.Length).ToArray();

 

 

6) 행마다 변환 처리 실행

//텍스트 파일에서 읽은 각 행에 행 번호를 붙이고 배열에 저장.
var lines = File.ReadLines(filePath).Select((s, ix) => String.Format(“{0, 4}: {1}”, ix+1, s)).ToArray();