System.IO 네임스페이스
- File, Directory 클래스: 파일(디렉토리) 처리를 위한 정적 메소드 제공
- FileInfo, DirectoryInfo 클래스: 파일(디렉토리) 처리를 위한 인스턴스 메소드 제공
- File과 FileInfo, Directory와 DirectoryInfo 클래스는 서로 거의 같은 기능을 제공
- 하나의 파일(디렉토리)에 한두가지 작업을 할 땐 정적 메소드를, 여러가지 작업을 할 땐 인스턴스 메소드를 주로 사용
- File, Directory 예제는 다음 소스코드 참고
class Program { public static void Main(string[] args) { /* 파일 생성 */ FileStream fs = File.Create("a.txt"); fs.Close(); /* 파일 복사 */ File.Copy("a.txt", "b.txt"); /* 파일 삭제 */ File.Delete("b.txt"); /* 파일 이동 */ File.Move("a.txt", "b.txt"); /* 파일 속성 조회 */ Console.WriteLine(File.GetAttributes("b.txt")); /* 파일 존재 여부 확인 */ if (File.Exists("a.txt")) File.Delete("a.txt"); if (File.Exists("b.txt")) File.Delete("b.txt"); /* ##### 디렉토리 ##### */ /* 디렉토리 생성 */ Directory.CreateDirectory("A"); Directory.CreateDirectory("B"); /* 디렉토리 삭제 */ Directory.Delete("B"); /* 디렉토리 이동 */ Directory.Move("A", "B"); /* 디렉토리 존재 여부 확인 */ if (Directory.Exists("A")) Directory.Delete("A"); if (Directory.Exists("B")) Directory.Delete("B"); /* 하위 디렉토리 조회 */ string[] dirs = Directory.GetDirectories("C:\"); foreach (string s in dirs) Console.WriteLine(s); /* 하위 파일 조회 */ string[] files = Directory.GetFiles("c:\"); foreach (string s in files) Console.WriteLine(s); } }
- FileInfo, DirectoryInfo 예제는 다음 소스드 참고
class Program { public static void Main(string[] args) { /* 파일 생성 */ FileInfo src = new FileInfo("a.txt"); FileStream fs = src.Create(); fs.Close(); /* 파일 복사 */ FileInfo dsc = src.CopyTo("b.txt"); /* 파일 삭제 */ dsc.Delete(); /* 파일 속성 조회 */ Console.WriteLine(src.Attributes); /* 파일 존재 여부 확인 */ if (src.Exists) src.Delete(); if (dsc.Exists) dsc.Delete(); /* ##### 디렉토리 ##### */ /* 디렉토리 생성 */ DirectoryInfo dirA = new DirectoryInfo("A"); dirA.Create(); DirectoryInfo dirB = new DirectoryInfo("B"); dirB.Create(); /* 디렉토리 삭제 */ dirB.Delete(); /* 디렉토리 이동 */ dirA.MoveTo("B"); /* 디렉토리 존재 여부 확인 */ if (dirA.Exists) dirA.Delete(); if (dirB.Exists) dirB.Delete(); /* 하위 디렉토리 조회 */ DirectoryInfo dirC = new DirectoryInfo("C:\"); DirectoryInfo[] dirs = dirC.GetDirectories(); foreach (var v in dirs) Console.WriteLine(v.FullName); /* 하위 파일 조회 */ FileInfo[] files = dirC.GetFiles(); foreach (var v in files) Console.WriteLine(v.FullName); } }
LINQ를 이용한 파일, 디렉토리 정보 조회
class Program { public static void Main(string[] args) { /* 디렉토리 정보 조회 */ string directory = "C:\"; var directories = (from dir in Directory.GetDirectories(directory) let info = new DirectoryInfo(dir) // let: LINQ의 var select new { Name = info.Name, Attributes = info.Attributes }).ToList(); foreach (var v in directories) Console.WriteLine("{0}: {1}", v.Name, v.Attributes); /* 파일 정보 조회 */ var files = (from file in Directory.GetFiles(directory) let info = new FileInfo(file) select new { Name = info.Name, Attributes = info.Attributes }).ToList(); foreach (var v in files) Console.WriteLine("{0}: {1}", v.Name, v.Attributes); } }
System.IO.Stream
- 스트림: 바이트(Byte) 단위로 데이터가 흐르는 통로
- 순차접근 방식이 보통: n번째 바이트를 읽어야 n+1번째 바이트 읽기가 가능
- System.IO.Stream은 입/출력 스트림과 순차/임의접근 방식 등을 지원
- Stream은 추상 클래스이므로 이 클래스로부터 파생된 클래스를 사용
- 다양한 장치를 스트림 모델 하나로 다루기 위함
- 주요 파생 클래스: FileStream, NetworkStream, BufferedStream 등
- FileStream 예제는 다음 소스코드 참고
class Program { public static void Main(string[] args) { /* ##### 파일 쓰기 ##### */ long someValue = 0x123456789ABCDEF; // 쓸 데이터 /* 파일 스트림 생성(Create 모드) */ Stream outStream = new FileStream("a.txt", FileMode.Create); /* long 형식 -> byte 배열 변환 */ byte[] wBytes = BitConverter.GetBytes(someValue); /* 파일 스트림을 통해 파일에 기록 * Write(byte 배열, 시작 오프셋, 기록할 데이터 길이) */ outStream.Write(wBytes, 0, wBytes.Length); /* 파일 스트림 닫기 */ outStream.Close(); Console.WriteLine("쓰기 완료: {0:X16}", someValue); /* ##### 파일 읽기 ##### */ byte[] rBytes = new byte[8]; /* 파일 스트림 생성(Read 모드) */ Stream inStream = new FileStream("a.txt", FileMode.Open); /* 데이터 읽기 * Read(byte 배열, 시작 오프셋, 기록할 데이터 길이) */ inStream.Read(rBytes, 0, rBytes.Length); /* byte 배열 -> long 형식 변환 */ long readValue = BitConverter.ToInt64(rBytes, 0); /* 파일 스트림 닫기 */ inStream.Close(); Console.WriteLine("읽기 완료: {0:X16}", readValue); } }
BinaryWriter/BinaryReader
- FileStream은 데이터 저장 시 byte 형식으로 변환해야 하므로 불편
- BinaryWriter/BinaryReader 클래스는 스트림에 이진 데이터(Binary Data)를 쓰기/읽기 위함
class Program { public static void Main(string[] args) { BinaryWriter bw = new BinaryWriter(new FileStream("a.txt", FileMode.Create)); /* BinaryWriter의 Write() 메소드는 C#이 제공하는 모든 기본 데이터 형식에 대해 오버로딩 */ bw.Write(12345); bw.Write(123.45); bw.Write("안녕요?ㅎ"); bw.Close(); BinaryReader br = new BinaryReader(new FileStream("a.txt", FileMode.Open)); long size = br.BaseStream.Length; int a = br.ReadInt32(); double b = br.ReadDouble(); string c = br.ReadString(); br.Close(); Console.WriteLine(a); Console.WriteLine(b); Console.WriteLine(c); } }
StreamWriter/StreamReader
- 텍스트 파일 처리용
class Program { public static void Main(string[] args) { StreamWriter sw = new StreamWriter(new FileStream("a.txt", FileMode.Create)); sw.Write(12345); sw.WriteLine("안녕요?ㅎ"); sw.Write(123.45); sw.Close(); StreamReader sr = new StreamReader(new FileStream("a.txt", FileMode.Open)); while (sr.EndOfStream == false) Console.WriteLine(sr.ReadLine()); Console.WriteLine("파일 사이즈: {0}", sr.BaseStream.Length); sr.Close(); } }
직렬화(Serialization)
- BinaryWriter/BinaryReader와 StreamWriter/StreamReader는 프로그래머가 정의한 복합 데이터 형식(클래스, 구조체 등)을 지원하지 않음
- 지원하게 하려면 데이터 형식의 필드 값을 일일이 저장하고 읽는 코드를 작성해야 함
- 이를 해결하기 위해 직렬화를 사용
- 클래스 선언부 앞에 [Serializable] 애트리뷰트를 붙여주면 직렬화 가능
- 필드 선언부 앞에 [NonSerialized] 애트리뷰트를 붙여주면 직렬화 안 함
- Stream 클래스와 BinaryFormatter를 사용하여 저장
- using System.Runtime.Serialization.Formatters.Binary;
- List 등의 컬렉션들도 직렬화 지원
[Serializable] class Student { public String Name { get; set; } public int Age { get; set; } } class Program { public static void Main(string[] args) { Student s = new Student() { Name = "김씨샵", Age = 18 }; /* 직렬화 */ Stream ws = new FileStream("a.dat", FileMode.Create); BinaryFormatter serializer = new BinaryFormatter(); serializer.Serialize(ws, s); ws.Close(); /* 역직렬화 */ Stream rs = new FileStream("a.dat", FileMode.Open); BinaryFormatter deserializer = new BinaryFormatter(); Student s2 = deserializer.Deserialize(rs) as Student; rs.Close(); Console.WriteLine("Name: {0}", s2.Name); Console.WriteLine("Age: {0}", s2.Age); } }