2015년 3월 10일 화요일

뇌자극 C# 5.0 - 18 강

-파일 다루기-

18.1 파일 정보와 디렉토리 정보 다루기


파일 = 컴퓨터 저장 매체에 기록되는 데이터의 묶음
디렉토리 = 파일이 위치하는 주소

파일과 디렉토리 정보를 손쉽게 다루도록
System.IO 네임스페이스를 사용하고 다음과 같은 클래스를 제공한다

File = 파일의 생성, 복사, 삭제, 이동, 조회를 처리하는 정적 메소드를 제공한다
FileInfo = File 클래스와 하는 일은 동일하지만 정적 메소드 대신 인스턴스 메소드를 제공
Directory = 디렉토리의 생성,삭제,이동,조회를 처리하는 정적 메소드를 제공한다
DirectoryInfo = Directory 클래스와 하는 일은 동일하지만 인스턴스 메소드를 제공한다.

-File 클래스/ FileInfo 클래스 사용예제-

-File 클래스-

생성 - FileStream fs = File.Create("a.dat");
복사 - File.Copy("a.dat","b.dat");
삭제 - File.Delete("a.dat");
이동 - File.Move("a.dat", "b.dat");
존재 여부 확인 - if(File.Exists("a.dat"))
속성 조회 - Console.WriteLine(File.GetAttributes("a.dat"));

-FileInfo 클래스-

생성 - FlieInfo file = new FileInfo("a.dat");
        FileStream fs = File.Create();

복사 - FileInfo src = new FileInfo("a.dat");
        FileInfo dst = src.CopyTo("b.dat");

삭제 - FileInfo file = new FileInfo("a.dat");
        file.Delete();

이동 - FileInfo file = new FileInfo("a.dat");
        file.MoveTo("b.dat");

존재 여부 확인 - FileInfo file = new FileInfo("a.dat");
                    if(file.Exists())

속성 조회 - FileInfo file = new FileInfo("a.dat");
              Console.WriteLine(file.Attributes);

-Directory/DirectoryInfo 클래스 사용예제-

-Directory 클래스-

생성 - Directory dir = Directory.CreateDirectory("a");
삭제 - Directory.Delete("a");
이동 - Directory.Move("a","b");
존재 여부 확인 - if(Directory.Exists("a.dat");
속성 조회 - Console.WriteLine(Directory.GetAttributes("a");
하위 디렉토리 조회 -string[] dirs = Directory.GetDirectories("a");
하위 파일 조회 - string[] files = Directory.GetFiles("a");

-DirectoryInfo 클래스-

생성 - DirectoryInfo dir = new DirectoryInfo("a");
        dir.Create();
삭제 - DirectoryInfo dir = new DirectoryInfo("a");
        dir.Delete();
이동 - DirectoryInfo dir = new DirectoryInfo("a");
        dir.MoveTo("b");
존재 여부 확인 - Directory dir = new DirectoryInfo("a");
                   if(dir.Exists)
속성 조회 - DirectoryInfo dir  = new DirectoryInfo("a");
             Console.WriteLine(dir.Attributes);
하위 디렉토리 조회 - DirectoryInfo dir = new DirectoryInfo("a");
                        DirectoryInfo[] dirs = dir.GetDirectories();
하위 파일 조회 - DirectoryInfo dir = new DirectoryInfo("a");
                   FileInfo[] files = dir.GetFiles();

18.2 파일을 읽고 쓰기 위해 알아야 할 것들


먼저 스트림의 개념을 알아야 한다.
스트림은 데이터가 흐르는 통로를 뜻한다.
메미로에서 하드디스크로 데이터를 옮길 때(파일 쓰기)는
먼저 스트림을 만들어 둘 사이를 연결하고
메모리에 있는 데이터를 바이트 단위로 하드디스크로 옮겨 넣는다.

스트림은 데이터의 흐름이기 때문에 스트림을 이용하여
파일을 다룰 때는 처음부터 끝까지
순서대로 읽고 쓰는 것이 보통이다.(이것을 순차 접근 방식이라고 한다).

하지만 하드디스크는 암과 헤드를 움직어
디스크의 어떤 위치에 기록된 데이터라도 즉시, 찾아갈 수 있다.
이렇게 임의의 주소에 있는 데이터에 접근하는 것을 임의 접근 방식이라고 한다.

스트림을 쓰기 위해서는 System.IO.Stream 클래스를 사용해야 한다.
스트림 클래스는 그 자체로 입력/출력 스트림 역할을 모두 할 수 있고,
순차/임의 접근 방식 모두를 지원한다.

단, 스트림 클래스는 추상 클래스이기 때문에 인스턴스를 직접 만들어 사용할 수는 없고,
이 클래스로부터 파생된 클래스를 이용해야 한다.

파일을 쓰는데는 다음과 같은 과정이 필요하다

1) 파일 스트림 생성
2) 값을 byte 배열로 변환
3) 변환한 byte 배열을 파일 스트림을 통해 파일에 기록
4) 파일 스트림 닫기

파일 읽는 과정도 비슷하다

1) 파일 스트림 생성
2) 값의 길이 만큼 데이터를 읽어 변수에 저장
3) BitConverter를 이용하여 변수에 담겨 있는 값을 Long 형으로 변환
4) 파일 스트림 닫기

18.3 이진 데이터 처리를 위한 BinaryWriter/BinaryReader


FileStream 클래스는 파일 처리를 위한 모든 것을 가지고는 있지만 사용하기가 불편하다.
데이터 저장할 때는 반드시 byte 형식 또는 byte의 배열 형식으로
변환해야 한다는 문제가 있다.
파일로부터 데이터를 읽을 때도 마찬가지다.
이런 불편함을 해소하기 위해 BinaryWriter/BinaryReader 가 만들어졌다.

(예제 - BinaryWriter)

BinaryWriter bw = new BinaryWriter( new FileStream("a.dat", FileMode.Create) );

bw.Write(32);
bw.Write("Good Morning");
bw.Write(3.14);

bw.Close();

1)BinaryWriter 의 생성자를 호출 하면서 FileStream 의 인스턴스를 매개 변수로 넘긴다.
2)인스턴스에서 Write() 메소드를 호출하고 데이터를 넣는다.
3)스트림을 닫아준다.

(예제 - BinaryReader)

BinaryReader br = new BinaryReader( new FileStream("a.dat", FileMode.Open) );

int a = br.ReadInt32();
string b = br.ReadString();
double c = br.ReadDoble();
br.Close();

1) BinaryReader 의 생성자를 호출하면서 FileStream 의 인스턴스를 매개 변수로 넘긴다.
2) BinaryReader는 읽을 데이터의 형식별로 Readxxx() 메소드(xxx는 읽을 데이터 형식의 이름)를 제공한다.
3) 스트림을 닫는다.

18.4 텍스트 파일 처리를 위한 StreamWriter/StreamReader


텍스트 파일 처리 역시 비슷하다.

(예제 - StreamWriter)

StreamWriter sw = new StreamWriter( new FileStream("a.dat", FileMode.Create));

sw.Write(32);
sw.WriteLine("Good Morning!");
sw.WriteLine(3.14);

sw.Close();

(예제 - StreamReader)

StreamReader sr = new StreamReader( new FileStream("a.dat", FileMode.Open) );

while(sr.EndOfStream == false)
{
    Console.WriteLine(sr.ReadLine());
}

sr.Close();

18.5 객체 직렬화하기


BinaryWriter/Reader 와 StreamWriter/Reader 은
기본 데이터 형식을 스트림에 쓰고 읽을 수는 있지만

프로그래머가 직접 정의한 클래스나 구조체 같은
복합 데이터 형식은 지원하지 않는다.

복합 데이터 형식을 쉽게 스트림에 읽기/쓰기를 할 수 있게 하는 것이 직렬화 이다.

직렬화란?
객체의 상태를 메모리나 저장 장치에 저장 가능한 0과 1의 순서로 바꾸는 것이다.
C#에서는 객체를 직렬화 하는 방법이 쉽다.
그저 [Serializable]를 클래스 선언부 앞에 붙여주면,
그 클래스는 메모리나 저장장치에 저장이 가능한 형식이 된다.

(예제 - 직렬화)

[Serializable]
class MyClass
{
   //...
}

Stream ws = new FileStream("a.dat", FileMode.Create);

//BinaryFormatter는 객체를 직렬화 하거나 역직렬화 하는 클래스
BinaryFormatter serializer = new BinaryFormatter();

MyClass obj = new MyClass();

serializer.Serialize(ws, obj); //직렬화
ws.Close();

(예제 - 역직렬화)

Stream rs = new FileStream("a.dat", FileMode.Open);
BinaryFormatter deserializer = new BinaryFormatter();

MyClass obj = (MyClass)deserializer.Deserialize(rs);  //역직렬화
rs.Close();

만약 직렬화 하고 싶지 않은 필드가 있다면
그 필드에만 NonSerialzed 애트리뷰트로 수식하면 된다.
이렇게 하면 필드의 상태는 직렬화 할 때도 제외되고, 역직렬화 할 때도 복원되지 않는다.

(예제 - NonSerialzed)

[Serializable]
class MyClass
{
   public int myField1;
   public int myField2;
 
   [NonSerialized]
   pulblic int myField3; //이 필드만 직렬화 되지 않는다.

   public int myField4; //이 필드는 직렬화 된다
}


댓글 없음:

댓글 쓰기