개발 노트

System.IO 파일입출력 텍스트모드 바이너리모드 본문

프로그래밍/C#

System.IO 파일입출력 텍스트모드 바이너리모드

알 수 없는 사용자 2022. 3. 10. 15:51

System.IO 네임스페이스

파일과 데이터 스트림에 대한 읽기 및 쓰기를 허용하는 형식과

기본 파일 및 디렉터리 지원을 제공하는 형식이 포함되어 있습니다.

 

디렉토리

파일이 위치하는 주소로 파일을 담는다는 의미에서 우리가 흔히 아는 폴더라고 부른다

1.디렉토리가 존재하는지 조사

특정 디렉토리가 존재하는지 조사하려면 Directory.Exit라는 정적 메서드를 사용한다

if (Directory.Exists(@”C:\Example”)) Console.WriteLine(“존재한다.”);
else Console.WriteLine(“존재하지 않는다.”);

2. 디렉터리 생성 삭제

	//매개변수에 입력된 경로/폴더명으로 새폴더 생성
			Directory.CreateDirectory("Exercise");
            	// 첫번째 매개변수에 입력된 폴더 삭제
            Directory.Delete("Exercise2");

 

파일

컴퓨터 저장매체에 기록되는 데이터의 묶음

 

 

C#

바이너리모드

텍스트모드

 

바이너리 : 기본적으로 두 조각, 두 부분을 의미하며 0과 1 두 숫자로만 이루어진 이진법을 의미한다

컴퓨터에서 정보는 이진 형태로 저장되며 바이너리는 이진 파일을 읨한다

이진 파일은 텍스트 형태가 아닌 이진 형태로 인코딩된 파일이다.

 

			using(BinaryWriter bw = new BinaryWriter(new FileStream("test.dat", FileMode.Create)))
			{
				bw.Write(12);
				bw.Write(3.14f);
				bw.Write("Hello World");
			}



			int var1;
			float var2;
			string str1;

			using (BinaryReader br = new BinaryReader(
				File.Open("test.dat", FileMode.Open)))
			{
				var1 = br.ReadInt32();
				var2 = br.ReadInt32();
				str1 = br.ReadString();
			}
			Console.WriteLine("{0} {1} {2}", var1, var2, str1);

파일입출력

스트림(Stream)

파일 네트워크 등에서 데이터를 바이트 단위로 읽고 쓰는 클래스

Stream class는 상위 기본 클래스임

 

- 상속 클래스들

FileStream, MemoryStream, NetworkStream, SqlFileStream 등

 

using System.IO 선언

 

FileStream?

파일입출력을 다루는 기본 클래스

System.Object

 + System.MarshalByRefObject + System.IO.Stream + System.IO.FileStream

 

byte[] 배열로 데이터를 읽거나 저장함

=>형변환이 요구됨

 

StreamWriter/StreamReader + BinaryWrter/BinaryReader 와 사용

 

파일 정보 설정에 사용

public FileStream(

string path,

FileMode mode,

FileAccess acees

)

 

FileMode

FileMode는 열거형으로 되어있다

Append, Create, Create New, Open, OpenOrCreate, Truncate

// 덧붙이기 ( 없으면 생성)
FileMode.Append

// 새로생성 ( 이미 있는경우 IOException 발생)
FileMode.Create

// 새로생성 ( 덮어쓰기 , 문제 있다)
FileMode.CreateNew

// 열기 (없으면 FileNotFoundException 발생)
FileMode.Open

// 열기 (없으면 생성)
FileMode.OpenOrCreate

//파일을 비우고 열기
FileMode.Truncate

 

FileAccess 열거형

Read, ReadWrite, Write

 

객체생성과해제

static void Main(string[] args)
{
	FileStream fs = new FileStream("test.txt",FileMode.Create);
    StreamWriter sw = new StreamWriter(fs);
    sw.Close();
}

 

using문

using(StreamWriter sw = new StreamWriter(new FileStream("test.txt",FileMode.Create))
{
	//파일 입출력 처리
}

 

 

 

 

C# 텍스트 파일처리

 

C# 에서 텍스트 파일을 읽고 쓰기 위해 가장 많이 쓰는 방법은

(1) StreamReader, StreamWriter 클래스를 사용하는 방법과

(2) File 클래스를 사용하는 방법이 있다.

StreamReader, StreamWriter 클래스는 텍스트 파일을 전문으로 처리하는 기능을 가진 클래스로서,

텍스트 파일을 읽을 때는 StreamReader를, 쓸 때는 StreamWriter를 사용한다.

또한, File 클래스는 텍스트 파일에서 텍스트나 라인들을 간단히 읽거나 쓰기 위한 유틸러티 메서드들을 가지고 있다.

예를 들어, File.ReadAllText() 는 텍스트 파일의 내용을 모두 읽어 string 으로 리턴하는 정적 메서드이며, File.ReadAllLines() 는 텍스트 파일의 각 라인들을 string[] 배열로 리턴하는 메서드이다.

이와 비슷하게 파일을 쓸 때는 File.WriteAllText(), File.WriteAllLines() 를 쓸 수 있다.

 

StreamReader를 사용한 텍스트 읽기

StreamReader를 사용해서 텍스트 파일을 읽기 위해서는 먼저 StreamReader 객체를 생성하고,

Read(), ReadLine() 등의 메서드를 사용하면 된다.

한 문자 혹은 여러 문자들을 읽기 위해서는 Read() 메서드를 사용하고, 한 라인씩 읽기 위해서는 ReadLine() 메서드를 사용한다.
ReadLine() 은 현재 위치에서 한 라인을 읽어 string 으로 리턴하는데, 만약 파일 끝을 만나면 null 을 리턴한다. Read() 메서드는 파라미터 없이 사용하면 한 문자를 읽게 되며, Read(버퍼, 버퍼시작인덱스, 문자갯수) 와 같이 사용하면 현재 파일 위치부터 지정된 문자갯수만큼 읽어 문자배열 버퍼에 넣게 된다.

 

using System;
using System.IO;

namespace FileApp
{
    class Program
    {
        static void Main(string[] args)
        { 
            string line;

            // 1. 샘플: 텍스트 라인별 읽기
            // StreamReader 객체를 생성한다. 입력파라미터로 File Path나 파일스트림 사용한다.
            using (StreamReader rdr = new StreamReader(@"C:\Temp\data.txt"))
            {
                // ReadLine()을 써서 한 라인을 읽어 들인다
                // 만약 파일 끝이면 null 이 리턴된다
                while ((line = rdr.ReadLine()) != null)
                {
                    Console.WriteLine(line);
                }
            }

            // 2. 샘플: 텍스트 문자 몇 개만 읽기
            using (StreamReader rdr = new StreamReader(@"C:\Temp\data.txt"))
            {
                // 한 문자 읽기
                int ch = rdr.Read();
                Console.Write(ch);

                // 현재 파일 포인터 위치에서 10개 문자를 읽기
                char[] buffer = new char[10];
                int readCount = rdr.Read(buffer, 0, 10);
                Console.WriteLine(buffer);
            }
        }
    }
}

StreamWriter를 사용한 텍스트 쓰기

StreamWriter를 사용해서 텍스트 파일에 문자들을 쓰기 위해서는 먼저 StreamWriter 객체를 생성하고, Write(), WriteLine() 등의 메서드를 사용하면 된다. Write() 혹은 WriteLine() 메서드는 거의 비슷한데, WriteLine() 은 마지막에 NewLine 을 넣는 것이 다르다. Write 메서드는 string 을 입력파라미터로 받을 뿐만 아니라, 거의 모든 타입의 데이타를 입력받을 수 있다. 아래 예제는 Write 메서드에서 문자열과 숫자, 문자배열 등을 입력파라미터로 받아 텍스트 파일에 쓰는 예이다.

using System;
using System.IO;

namespace FileApp
{
    class Program
    {
        static void Main(string[] args)
        { 
            // 텍스트 파일 쓰기            
            // StreamWriter 객체를 생성한다. 입력파라미터로 File Path나 파일스트림 사용한다.
            using (StreamWriter wr = new StreamWriter(@"C:\Temp\data.txt"))
            {
                // WriteLine()을 써서 한 라인씩 문자열을 쓴다.                
                wr.WriteLine("Line 1");
                wr.WriteLine("Line 2");

                // 숫자를 쓰기
                decimal val = 1024.10M;
                wr.WriteLine(val);

                // 문자배열을 쓰기
                char[] array = new char[5] { 'A', 'B', 'C', 'D', 'E' };
                wr.WriteLine(array);
            }

        }
    }
}

 

File 클래스에서 텍스트파일 읽고 쓰기

File 클래스는 개발자의 편리성을 위해 파일을 간단하게 읽고 쓰는 유틸러티성 메서드들을 제공하고 있다.

File.ReadAllText(파일명) 메서드는 파일 안의 모든 텍스트를 읽어 string 으로 리턴하고, File.ReadAllLines(파일명) 메서드는 파일 안의 모드 텍스트를 라인별로 읽어 문자열 배열에 리턴한다. 또한, File.ReadLines(파일명)는 라인별로 문자열을 하나씩 리턴하는 IEnumerable<string> 객체를 리턴한다.

텍스트를 쓰는 메서드는 File.WriteAllText(), File.WriteAllLines(), File.AppendAllText(), File.AppendAllLines() 이 있는데, WriteAllText() 는 파일에 문자열을 한꺼번에 쓰고, WriteAllLines() 은 문자열배열을 파일에 한꺼번에 쓴다. WriteAllText() 혹은 WriteAllLines() 메서드는 파일이 이미 있는 경우 이를 지우고 새로 파일을 생성하는 반면, AppendAllText() 혹은 AppendAllLines() 는 파일이 없으면 새로 만들지만 있으면 기존의 파일에 문자 데이타를 뒤에 추가하게 된다.

using System;
using System.Collections.Generic;
using System.IO;

namespace FileApp
{
    class Program
    {
        static void Main(string[] args)
        {
            // ###### 텍스트 파일 읽기  ######
            // 모든 텍스트 한꺼번에 읽기
            string data = File.ReadAllText(@"C:\Temp\data.txt");
            Console.WriteLine(data);

            // 모든 라인들을 읽어 문자열 배열에 넣기
            string[] allLines = File.ReadAllLines(@"C:\Temp\data.txt");

            // 한 라인씩 읽기
            IEnumerable<string> lines = File.ReadLines(@"C:\Temp\data.txt");
            foreach(string line in lines)
            {
                Console.WriteLine(line);
            }


            // ###### 텍스트 파일 쓰기  ######
            // 텍스트 파일에 모든 데이타 한꺼번에 쓰기
            File.WriteAllText("data.out", data);

            //// 텍스트 파일에 문자열배열 라인별로 쓰기
            string[] arrStr = { "I", "am", "a", "boy" };
            File.WriteAllLines("data.out", arrStr);

            // 텍스트 파일에 모든 데이타 한꺼번에 추가(append)
            File.AppendAllText("data.out", data);

            // 텍스트 파일에 문자열배열 한꺼번에 추가(append)
            File.AppendAllLines("data.out", allLines);           
        }
    }
}

 

C# 이진 파일 처리

 

C# 에서 이진 파일을 읽고 쓰기 위해 일반적으로

BinaryhReader, BinaryWriter 클래스를 사용한다

 

BinaryReader, BinaryWriter 클래스는 이진 파일을 처리하는 여러 기능을 가진 클래스로서 이진 파일을 읽을 때는 BinaryReader를 쓸 때는 BinaryWriter를 사용한다

 

BinaryWriter를 사용한 이진데이터쓰기

데이타를 이진파일에 쓰기 위해서는 BinaryWriter 클래스를 사용한다. BinaryWriter 객체를 생성하기 위해 먼저 File.Open()을 사용 (혹은 FileStream 클래스 사용)하여 파일스트림을 생성한 후 이를 BinaryWriter의 생성자에 전달한다

 

데이타를 이진파일에 쓰기 위해서는 BinaryWriter 클래스를 사용한다.

BinaryWriter 객체를 생성하기 위해 먼저 File.Open() 을 사용(혹은 FileStream 클래스 사용)하여 파일스트림을 생성한 후, 이를 BinaryWriter의 생성자에 전달한다.

BinaryWriter에서 데이타를 이진파일에 쓰기 위해서는 Write() 메서드를 사용하면 된다. Write() 메서드는 바이트, bool, 정수, 숫자, 문자열 등 다양한 종류의 데이타를 쓸 수 있는데, 이 메서드 하나가 18개의 서로 다른 메서드 오버로드 (.NET 4.5 기준)를 가지고 있다.

아래 예제는 Write 메서드를 사용하여 다양한 타입의 데이타를 이진파일에 쓰는 코드이다

 

using System.IO;

namespace FileApp
{
    class Program
    {
        static void Main(string[] args)
        {
            // 이진파일에 쓸 샘플데이타
            bool b = true;
            int i = 101;
            decimal d = 1024.05M;
            byte by = 0xA0;
            byte[] bytes = { 0xFF, 0x32, 0x11 };
            string s = "Hello";

            // 이진파일 생성
            FileStream fs = File.Open(@"C:\Temp\data.bin", FileMode.Create);

            // BinaryWriter는 파일스트림을 사용해서 객체를 생성한다
            using (BinaryWriter wr = new BinaryWriter(fs))
            {
                // 각각의 샘플데이타를 이진파일에 쓴다
                wr.Write(b);  // bool 
                wr.Write(i);  // 정수
                wr.Write(d);  // decimal
                wr.Write(by); // byte
                wr.Write(bytes); // bytes
                wr.Write(s);  // 문자열 (UTF8)
            }
    }
}

BinaryReader를 사용한 이진데이타 읽기

이진파일에 데이타를 위해서는 BinaryReader 클래스를 사용한다.

BinaryWriter와 마찬가지로 BinaryReader 클래스는 이진파일스트림을 통해 동작하므로,

이진파일을 오픈해서 파일스트림을 얻고 이를 통해 BinaryReader 객체를 생성한다.

BinaryReader 클래스는 이진데이타를 읽기 위해서 각 데이타 타입별로 다양한 메서드들을 가지고 있다.

예를 들어, 부울린 타입은 ReadBoolean()을, 32비트 정수는 ReadInt32(), 16비트 정수는 ReadInt16()을,

한 바이트는 ReadByte(), 여러 개의 바이트들은 ReadBytes(), 문자열을 ReadString() 등을 사용한다. BinaryWriter 클래스는 여러 데이타 타입에 대해 메서드 오버로딩을 사용해 하나의 Write() 메서드를 사용하지만, BinaryReader 클래스는 각 데이타 타입별로 다른 메서드를 사용한다.

BinaryReader 클래스의 Read 메서드들은 해당 타입의 데이타를 읽고 그 데이타 크기만큼 현재 파일위치에서 이동한다.

using System;
using System.IO;

namespace FileApp
{
    class Program
    {
        static void Main(string[] args)
        {            
            // BinaryReader는 스트림을 사용해서 객체를 생성한다
            using (BinaryReader rdr = new BinaryReader(File.Open(@"C:\Temp\data.bin", FileMode.Open)))
            {
                // 각 데이타 타입별로 다양한 Read 메서드를 사용한다
                bool b = rdr.ReadBoolean();
                int i = rdr.ReadInt32();
                decimal d = rdr.ReadDecimal();
                byte by = rdr.ReadByte();
                byte[] bytes = rdr.ReadBytes(3); // 3바이트 읽기
                string s = rdr.ReadString();

                Console.WriteLine("{0},{1},{2}", b, i, s);
            }
        }
    }
}

이진파일에서 문자열 인코딩

이진파일에 문자열 혹은 문자를 읽거나 쓸 때, BinaryReader / BinaryWriter 클래스는 디폴트로 UTF-8 인코딩을 사용한다. 만약 이진파일이 디폴트 인코딩과 인코딩을 사용한다면, BinaryReader / BinaryWriter 생성자에서 해당 인코딩을 지정해 주어야 한다. 아래 예제는 이진파일에 문자를 쓸 때는 UTF7 인코딩을 사용하고 이를 읽을 때는 디폴트 인코딩 (UTF8)을 사용해 본 코드이다. 이 예제의 결과는 깨진 문자가 읽혀지게 된다.

using System;
using System.IO;
using System.Text;

namespace FileApp
{
    class Program
    {
        static void Main(string[] args)
        {
            string datafile = "data.bin";

            FileStream fw = File.Open(datafile, FileMode.Create);
            using (BinaryWriter wr = new BinaryWriter(fw, Encoding.UTF7))
            {
                // 문자 데이타에 UTF7 인코딩이 사용됨
                wr.Write("안녕하세요?");
                wr.Write('한');
            }

            var fr = File.Open(datafile, FileMode.Open);
            // using (BinaryReader rdr = new BinaryReader(fr, Encoding.UTF7))  // 맞는 코드
            using (BinaryReader rdr = new BinaryReader(fr))  // 틀린코드 (디폴트 UTF8)
            {
                // 문자 데이타 읽기. 지정된 인코딩 사용함.
                string s = rdr.ReadString();
                char c = rdr.ReadChar();

                Console.WriteLine("{0},{1}", s, c);
            }
        }
    }
}

File 클래스를 통해 전체 바이트 읽고 쓰기

File 클래스는 이진파일 전체를 읽어 바이트배열로 리턴하는 File.ReadAllBytes() 메서드와 바이트 배열을 이진파일에 쓰는 File.WriteAllBytes() 메서드를 제공하고 있다. 이들 메서드는 바이트 전체를 간단하게 읽고 쓸 때 편리하게 사용할 수 있다.

using System.IO;

namespace FileApp
{
    class Program
    {
        static void Main(string[] args)
        {
            // 이미지 파일에서 전체 바이트 읽기
            byte[] bytes = File.ReadAllBytes(@"C:\Temp\source.png");

            // 이미지 파일에 모든 바이트 쓰기
            File.WriteAllBytes(@"C:\Temp\target.png", bytes);
        }
    }
}

FileStream 클래스를 통한 파일 읽고 쓰기

FileStream 클래스는 기본적인 Low 레벨의 파일 I/O 를 담당하는 클래스이다. 이 클래스는 파일스트림을 바이트 레벨에서 읽고 쓰는 기능을 가지고 있으며, 비동기 처리 기능도 가지고 있다. (위의 File 클래스는 파일 I/O 처리에서 내부적으로 FileStream을 사용한다). FileStream의 Read(), Write() 메서드는 파일의 바이트 데이타를 부분적으로 읽고 쓰는 기능을 가지고 있으며, 사이즈가 큰 파일을 일부씩만 읽어 처리할 때 특히 유용하다.

아래 예제는 이미지 파일을 10번에 걸쳐 나누어 읽는 예이다.

using System;
using System.IO;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            using (FileStream fs = new FileStream(@"C:\Temp\source.png", FileMode.Open))
            {
                int size = (int)fs.Length;                
                byte[] buff = new byte[size];

                // 이미지를 10번에 걸쳐 나누어 읽음
                for (int i = 0; i < 10; i++)
                {
                    int n = fs.Read(buff, 0, size / 10);
                    //....
                    Console.WriteLine(n);
                }
            }
        }
    }
}

 

 

 

파일열기

파일생성

파일읽기

 

C# 파일생성, 읽기

파일입출력

기본

바이너리모드

텍스트모드

 

 

 

 

활용

'프로그래밍 > C#' 카테고리의 다른 글

MSSQL - WITH 구문(임시테이블 만들기)  (0) 2022.03.14
SERIALIZE DESERIALIZE  (0) 2022.03.14
로그파일저장  (0) 2022.03.10
C# listbox 텍스트파일 저장후 불러오기  (0) 2022.03.07
C# 현재경로로 파일 저장하기  (0) 2022.03.07