본문 바로가기
메타버스기반게임콘텐츠기획/스터디(C#이 보이는 그림책)

7장, 파일과 스트림 (7-1)

by Queenut 2021. 12. 6.

 * 파일

 - 텍스트 파일: 사람이 인식할 수 있는 언어.

 - 바이너리 파일: 기계가 인식하는 언어. 문자로 읽을 수 없음. .exe, .com 등. 우리가 작성한 것을 컴파일러로 바이너리 파일로 만든다.

 

 

 * 스트림

 : 파일의 읽기 및 쓰기에 대한 데이터의 흐름.

 C#언어에서는 파일의 읽기 쓰기에 스트림 전용 클래스에서 생성한 객체를 사용한다.

system.IO 네임스페이스에는 스트림을 위한 클래스가 준비되어 있다. 프로그램 맨 앞에 다음과 같이 선언해야 한다.

using System.IO;

 - 문자 스트림 : Unicode 문자의 데이터를 취급한다. 입출력 시 OS의 사양이나 설정에 기초해 문자나 줄바꿈 코드가 변환된다.

 - 바이트 스트림: 바이너리 데이터를 취급한다. 입출력 시 변환이 수행되지 않는다.

 

 

 

 * 예외처리

 : 프로그램 실행 시 일어나는 오류(예외: exception)를 미리 대응하는 대책. 비정상 종료를 막을 수 있다.

 

 - 방법

1. try~ catch~ finally~

try                                       // 내포해 사용 가능
{
       (예외가 발생할지도 모르는 처리)
}
catch (예외 클래스명 변수명)     // 인수로 예외
{
       (예외 발생 시 실행하는 처리)
}
finally                                  // { } 안의 처리는 예외 발생 여부와 관계 없이 실행된다.
{
       (뒷마무리 작업)
}

하나의 try중 여러 예외가 발생할 경우, catch를 계속 명시함으로써 예외 종류마다 처리를 분배할 수 있다.

try {
...
}
catch (DivideByZeroException e1) {
...
}
catch (FileNotFoundException e2) {
...
}

 

 

2. throw

 : 예외를 의도적으로 일으키고 싶은 경우 사용. 인수는 예외 객체를 지정하고, 이것이 catch의 인수가 된다.

try {
       ...

       try
       {
             ... (오류를 포함한 처리)
       }
       catch (Exception e1)      // 예외 클래스 객체를 생성하고 throw한다.
       {
             Exception e1 = new Exception();
             e1. Message = "오류!";
             throw e1;
       }
}
catch (Exception e2)            // throw된 예외를 바깥 블록이 캐치한다.
{
       Console.WriteLine(e2.Message);
}

throw 하지 않으면 바깥쪽 catch는 호출되지 않는다.

(e.Message는 에러 이유를 나타내는 메시지?)

 

 

C#이 보이는 그림책 p197.

try로 z를 출력하려고 했지만,

에러가 나 catch가 실행되고 e.Massage로 오류 이유를 알려준 후,

"종료했습니다."를 출력한다.

 

 

 

 

 * 텍스트 파일 읽는 순서

예시: file1.txt, UFD-8 형식.

 

1. 파일을 연다

FileStream fs = new FileStream("file1.txt", FileMode.Open);   // 스트림을 만듦.
StreamReader r = new StreamReader(fs);                          // StreamReader라는 읽기용 클래스에 전달.

file1.txt : 파일명

FileMode.Open : 열기 모드. 파일 여는 방법 지정.

 

 - 오픈 모드 일람

처리 의미
FileMode.Open 기존의 파일을 연다.
FileMode.OpenOrCreate 파일이 없으면 만든 후 연다.
FileMode.Append 추가 기록 모드로 연다. 파일이 없으면 만든다.
FileMode.Create 파일을 만든다. 같은 이름의 파일이 있으면 이전 걸 지운다.
FileMode.CreateNew 파일을 만든다. 같은 이름의 파일이 있으면 예외가 발생한다.

 

 

2. 데이터를 읽는다.

string s = r.ReadLine();   // StreamReader의 클래스 ReadLine() 메소드를 사용한다.

s : 읽은 문자열을 저장하는 변수.

ReadLine() : 한 행 분량의 문자열을 읽어 반환한다. 읽을 수 없을 땐 null을 반환한다.

 

 

3. 파일을 닫는다.

r.Close();   // StreamReader 클래스의 Close() 메소드를 사용한다.

 

 

예제를 풀기 전, 텍스트 파일에 예제에서 지정하는 대로 저장한다.

위치는 프로젝트가 위치한 폴더의 bin\Debug\net5.0 안에 넣었다.

 

p199.

IOEeception : 입출력과 관련된 오류가 발생했을 때의 예외 클래스

 

 

 * 텍스트 파일 쓰는 순서

예시: "안녕하세요?" 라는 문자열을 file2.txt에 써넣어 본다.

 

1. 파일을 연다.

FileStream fs = new FileStream("file2.txt", FileMode.Create);   // 스트림을 만듦.
StreamWriter w = new StreamWriter(fs);                          // StreamWriter라는 쓰기용 클래스에 전달.

file2.txt : 파일명

FileMode.Create : 열기 모드. 새로 파일을 만든다. 

 

 

2. 데이터를 쓴다.

w.Write("안녕하세요?");   // StreamWriter의 클래스 Write() 메소드를 사용한다.

Write() : 인수로 전달한 데이터를 (UTF-8형식으로) 파일에 써 넣는다.

 

 

3. 파일을 닫는다.

w.Close();   // StreamWriter 클래스의 Close() 메소드를 사용한다.

 

 

파일을 미리 만들 필요는 없다.

p201.

 

 

 

 

 * 바이너리 읽고 쓰기

 

- 바이너리 파일 읽기 순서

예시: file3.dat에 3바이트 데이터 읽어 들이기.

 

1. 파일을 연다.

FileStream fs = new FileStream("file3.dat", FileMode.Open);   // 스트림을 만듦.

BinaryReader r = new BinaryReader(fs);                          // BinaryReader라는 바이너리 읽기용 클래스에 전달.

 

 

2. 데이터를 읽는다.

int n = r.Read(buf, 0, 3);   // BinaryReader 클래스 Read() 메소드를 사용한다.

n : 읽어들인 바이트 수

Read() : 배열에 데이터를 읽어 들인다.

buf : 데이터를 받은 byte형의 배열.

0 : 읽어 들이기 시작 위치.

3 : 읽어 들이는 바이트 수.

 

 

3. 파일을 닫는다.

r.Close();   // BinaryReader 클래스의 Close() 메소드를 사용한다.

 

 

 - 바이너리 파일 쓰기 순서

예시: file4.dat에 3바이트 데이터 쓰기.

 

1. 파일을 연다.

FileStream fs = new FileStream("file4.dat", FileMode.Create);   // 스트림을 만듦.
BinaryWriter w = new BinaryWriter(fs);                              // BinaryWriter라는 쓰기용 클래스에 전달.

 

 

2. 데이터를 쓴다.

int n = w.Write(buf, 0, 3);   // BinaryWriter의 클래스 Write() 메소드를 사용한다.

n : 기록된 바이트 수

Write() : 배열(데이터)을 쓴다.

buf : 쓴 데이터가 들어간 byte형의 배열.

0 : buf의 쓰기 시작 위치.

3 : 쓸 바이트 수.

 

 

3. 파일을 닫는다.

w.Close();   // BinaryWriter 클래스의 Close() 메소드를 사용한다.

 

 

 

 

 * 키보드 입력

 : 키보드에서 입력한 문자나 숫자를 입력 스트림으로 읽어 들인다.

 키보드에서 한 행 분량의 데이터를 입력하려면 아래 메소드를 사용한다.

string s = Console.ReadLine();

 

p205
숫자 외의 것을 입력하면 에러.

 

 

 

 

예제 프로그램

 : 입력한 명령에 의해 텍스트 파일에 출퇴근 시간을 등록한다.

 

 

 

 * 예외 클래스

 : 예외가 발생한 경우를 대비해 준비된 클래스.

 System 네임스페이스의 Exception 클래스에서 모두 파생된다.

 예외가 발생할 것 같은 코드에는 예외 처리를 미리 포함시켜 둔다.

 

 - 자주 사용되는 예외 클래스

예외 클래스 의미
DivideByZeroException 0으로 나누었습니다.
IndexOutRangeException 첨자가 배열의 범위를 초과했습니다.
InvalidCastException 실행할 때 형 변환이 올바르지 않습니다.
NullReferenceException 값이 null인 객체 변수를 참조했습니다.
OutOfMemoryException 메모리 여유 공간이 부족하여 호출에 실패했습니다.
OverflowException 오버플로가 발생했습니다.
FileNotFoundException 존재하지 않는 파일에 액세스하는 데 실패했습니다.
Exception 모종의 예외가 발생했습니다.