기본 콘텐츠로 건너뛰기

C# - 파일 입출력


1. 파일 입출력(File Input/Output)

이번에는 파일(File)을 다루는 클래스와 메소드들을 살펴보려고 합니다. 이 파일의 사전적 의미로는 '하나의 단위로서 처리되는 서로 관련 있는 레코드의 집합'라는 의미를 가지고 있습니다. System.IO 네임스페이스를 살펴보면 파일을 읽고 쓸 수 있는 클래스가 있는데, 오늘 배우게 될 클래스를 아래에 정리해두었습니다.

클래스설명
File파일에 대한 생성, 복사, 삭제, 이동 및 열기를 위한 정적 메소드를 제공
FileInfo 파일에 대한 생성, 복사, 삭제, 이동 및 열기를 위한 속성 및 인스턴스 메소드를 제공
FileStream 파일에 대한 스트림을 제공하여 동기 및 비동기 읽기/쓰기 작업을 모두 지원
StreamReader 문자열에서 읽어오는 TextReader를 구현함
StreamWriter TextWriter를 구현하여 특정 인코딩의 스트림에 문자를 씀

이 말고도 클래스는 다양하니, 더 참고하고 싶으신 분들은 아래의 MSDN를 방문하시기 바랍니다.

우선은 File, FileInfo, FileStream 클래스부터 알아보도록 할까요?

2. File, FileInfo, FileStream

위에서 말했듯이 File, FileInfo 클래스 내에는 파일 생성, 복사, 삭제, 이동 및 열기 등 다양한 메소드를 제공하고 있습니다. 그런데 '정적 메소드'와 '인스턴스 메소드'라는게 보이죠? 우리가 여태까지 C# 강좌를 보면서, 메소드 앞에 static 한정자가 붙은 메소드를 본적이 있는데 이런 메소드를 '정적 메소드(static method)' 라고 합니다. 정적 메소드의 특징은 클래스의 인스턴스를 따로 생성하지 않아도 호출이 가능하다는 특징을 가지고 있습니다. 반면에 인스턴스 메소드는 클래스의 인스턴스를 생성해야만 호출할 수 있는 메소드겠죠?

자, 이제는 File 클래스와 FileInfo 클래스의 생성, 복사, 삭제, 이동에서 어떠한 차이점을 보이는지 표로 정리해 두었습니다.

기능File FileInfo
생성FileStream fs = File.Create("test.txt");FileInfo file = new FileInfo("test.txt");
FileStream fs = file.Create(); 
복사 File.Copy("a.txt", "b.txt"); FileInfo src = new FileInfo("a.txt");
FileInfo dst = src.CopyTo("b.txt"); 
삭제 File.Delete("a.txt"); FileInfo file = new FileInfo("a.txt");
file.Delete(); 
이동 File.Move("a.txt", "b.txt");FileInfo file = new FileInfo("a.txt");
file.MoveTo("b.txt");

위 표를 잘보시면 File의 생성 부분에 FileStream이라는 클래스가 쓰였죠? FIleStream 클래스에 대해 알아보기 전에, 스트림(Stream)이란 C#에서의 입출력 작업을 도와주는 중간 매개체 역할을 하는 녀석입니다. 우리가 파일을 주고 받을때도, 모니터, 키보드 등으로 데이터를 주고 받는 작업 등 이 모든게 스트림(Stream)을 이용한 것입니다. 만약에, 스트림을 이용하지 않는다면 얼마나 끔찍할지 상상이 안갑니다. 그럼 FileStream 클래스는 무슨 역할을 하는 것일까요? 이 FileStream 클래스는 파일에서 스트림을 생성할때 사용되며, 바이트 배열로 읽고 쓰기 위해 사용되는 클래스입니다. (입출력의 성능 향상을 위해 버퍼링을 지원합니다.)

이제, File 클래스와 FileInfo 클래스를 직접 사용해보도록 합시다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication46
{
    class Program
    {
        static void Main(string[] args)
        {
            FileStream fsa = File.Create("a.txt");
            FileInfo file = new FileInfo("b.txt");
            FileStream fsb = file.Create();
            fsa.Close();
            fsb.Close();
            File.Copy("a.txt", "c.txt");
            FileInfo dst = file.CopyTo("d.txt");
        }
    }
}
코드를 보시면 14~16행에서 a.txt와 b.txt를 생성(Create) 합니다. 그런데 그 다음 줄을 보시면 Close라는 메소드가 보이는데, 이 Close 메소드는 현재 스트림을 닫는 역할을 합니다. 만약 스트림을 다 사용하고 닫아주지 않으면, 이미 사용중이기 때문에 파일에 액세스 할 수 없다는 예외가 발생합니다. 그렇기 때문에 파일을 만들고 스트림을 닫고, 20~21행에서 a.txt는 c.txt로 복사하고, b.txt는 d.txt로 복사했습니다.

프로그램을 실행한 경로를 따라가보면 a.txt, b.txt, c.txt, d.txt가 생성되었음을 보실 수 있습니다. 이번에는, 파일을 쓰고 읽을 수 있는 프로그램을 만들어 보도록 합시다.

3. StreamReader, StreamWriter

자 이번에는 특정 인코딩으로 입력된 문자를 읽도록 하는 StreamReader 클래스와, 특정 인코딩에서의 문자 출력을 위한 StreamWriter 클래스를 알아보려고 합니다. (StreamReader는 TextReader로부터, StreamWriter는 TextWriter로 부터 파생되었습니다.) 아래는 StreamReader, StreamWriter에서 주로 쓰이는 메소드를 표로 정리한 것입니다.

메소드설명사용 예
Read입력 스트림의 다음 문자를 읽습니다.Console.Write((char)sr.Read());
ReadLine 현재 스트림에서 한 줄의 문자를 읽고 데이터를 문자열로 반환합니다.Console.WriteLine(sr.ReadLine());
Peek 파일 끝에 도달하거나 다른 오류가 발생했는지 확인하기 위한 정수 값을 반환합니다. 문자가 더이상 없으면 -1를 반환합니다.while (sr.Peek() >= 0) {
   ...
}
Close스트림을 닫고 관련된 시스템 리소스를 모두 해제합니다.sr.Close();
<StreamReader>

메소드설명 사용 예 
Write 스트림에 씁니다.sw.Write("The date is: ");
WriteLine 스트림에 쓰고, 마지막에 개행되어 나옵니다.sw.WriteLine("header for the file.");
Close 스트림을 닫고 관련된 시스템 리소스를 모두 해제합니다. sw.Close(); 
<StreamWriter>

이것 말고도 여러개의 메소드를 지원하니 아래의 MSDN를 방문하여 참고하실분은 참고하세요.

이제 위의 두 클래스를 이용하여 파일을 쓰고 읽는 프로그램을 만들어 봅시다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication46
{
    class Program
    {
        static void Main(string[] args)
        {
            // StreamWriter
            StreamWriter sw = new StreamWriter("a.txt");
            sw.Write("sw.Write()");
            sw.Write(" sw.Write()");
            sw.WriteLine(" sw.WriteLine()");
            sw.WriteLine("sw.WriteLine()");
            sw.Close();
            // StreamReader
            StreamReader sr = new StreamReader("a.txt");
            while (sr.Peek() >= 0)
            {
                Console.WriteLine(sr.ReadLine());
            }
            sr.Close();
        }
    }
}
결과:
sw.Write() sw.Write() sw.WriteLine()
sw.WriteLine()
계속하려면 아무 키나 누르십시오 . . .

코드를 보시면, 15행에서 StreamWriter 객체를 생성하고, 생성함과 동시에 생성자에 스트림을 쓸 파일명을 넘깁니다. 그런 뒤에 16~19행에서는 문자열을 파일에 씁니다. 21행에선 이 스트림을 다 사용했으니 닫습니다. a.txt를 직접 열어보면 아래와 같이 입력되어 있습니다.

a.txt:
sw.Write() sw.Write() sw.WriteLine()
sw.WriteLine()


그 다음엔, 24행을 보시면 StreamReader 객체를 생성하고, 생성함과 동시에 생성자에 스트림을 읽을 파일명을 넘깁니다. 26행을 보시면 Peek 메소드가 쓰였는데, 위에서 말했듯이 파일의 끝에 도달하면 -1를 반환합니다. 파일의 끝에 도달할때까지 한줄 한줄씩 읽는것과 같습니다. 그런 뒤에 30행에서 이 스트림을 닫습니다.


출처: http://blog.eairship.kr/154 [누구나가 다 이해할 수 있는 프로그래밍 첫걸음]

댓글

이 블로그의 인기 게시물

C# - Serial Port ASCII/HEX Format

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO.Ports; namespace SerialTest1 {     public partial class Form1 : Form     {         delegate void MyDelegate();      //델리게이트 선언(크로스 쓰레드 해결하기 위한 용도)         bool SendForamt = true;          // true : ASCII   false : HEX         bool ReceiveFormat = true;       // true : ASCII   false : HEX         public Form1()         {             InitializeComponent();          ...

C# - Windows Form 에 있는 control 찾기

// 아래 코드는 form 의 최상위 control만 찾을 수 있음. // panle, groubbox ... 내부에 있는 control은 찾지 못함. Control GetControlByName(string Name) {     foreach (Control c in this.Controls)         if (c.Name == Name)             return c;     return null; } // form 의 모든 control을 찾을 수 있음. string name = "btnBit" + (i + 1).ToString("D2"); var tmpBtn = this.Controls.Find(name, true).FirstOrDefault(); if (tmpBtn != null) {     if (value == 1) tmpBtn.BackColor = Color.Lime;     else tmpBtn.BackColor = Color.Gray; }

C# - ARGB 색상

속성 A 이  Color  구조체의 알파 구성 요소 값을 가져옵니다. Alice Blue ARGB 값이  #FFF0F8FF 인 시스템 정의 색을 가져옵니다. Antique White ARGB 값이  #FFFAEBD7 인 시스템 정의 색을 가져옵니다. Aqua ARGB 값이  #FF00FFFF 인 시스템 정의 색을 가져옵니다. Aquamarine ARGB 값이  #FF7FFFD4 인 시스템 정의 색을 가져옵니다. Azure ARGB 값이  #FFF0FFFF 인 시스템 정의 색을 가져옵니다. B 이  Color  구조체의 파랑 구성 요소 값을 가져옵니다. Beige ARGB 값이  #FFF5F5DC 인 시스템 정의 색을 가져옵니다. Bisque ARGB 값이  #FFFFE4C4 인 시스템 정의 색을 가져옵니다. Black ARGB 값이  #FF000000 인 시스템 정의 색을 가져옵니다. Blanched Almond ARGB 값이  #FFFFEBCD 인 시스템 정의 색을 가져옵니다. Blue ARGB 값이  #FF0000FF 인 시스템 정의 색을 가져옵니다. Blue Violet ARGB 값이  #FF8A2BE2 인 시스템 정의 색을 가져옵니다. Brown ARGB 값이  #FFA52A2A 인 시스템 정의 색을 가져옵니다. Burly Wood ARGB 값이  #FFDEB887 인 시스템 정의 색을 가져옵니다. Cadet Blue ARGB 값이  #FF5F9EA0 인 시스템 정의 색을 가져옵니다. Chartreuse ARGB 값이  #FF7FFF00 인 시스템 정의 색을 가져옵니다. Chocolate ARGB 값이  #FFD2691E 인 시스템 정의 색을 가져옵니다. Coral ARGB ...