CodeGym /행동 /C# SELF /읽기/쓰기 시 인코딩 지정 ( Encoding

읽기/쓰기 시 인코딩 지정 ( Encoding)

C# SELF
레벨 37 , 레슨 2
사용 가능

1. 기본 인코딩

StreamReader나 StreamWriter로 작업할 때, 이들은 기본 인코딩을 사용합니다.

만약 이렇게 작성하면:

using var reader = new StreamReader("myfile.txt");

또는

using var writer = new StreamWriter("output.txt");

.NET기본 인코딩을 선택합니다. Windows에서는 보통 UTF-8(종종 BOM 없음)이지만, 오래된 앱이나 다른 시스템에서는 동작이 다를 수 있어요.

대부분의 경우 UTF-8이 좋은 선택입니다: 모든 언어를 지원하고 영어 텍스트(러시아어도 포함)에 대해 저장이 효율적이에요. 하지만 파일이 다른 인코딩(예: Windows-1251)으로 만들어졌거나, 특정 인코딩을 기대하는 다른 프로그램에서 파일을 읽을 경우에는 명시적으로 인코딩을 지정해야 합니다.

2. StreamReader와 StreamWriter에 인코딩 지정하기

생성자 옵션들

StreamReader와 StreamWriter 모두 System.Text.Encoding 타입의 객체를 전달할 수 있는 생성자를 지원합니다.

예:

using var reader = new StreamReader("myfile.txt", Encoding.UTF8);
using var writer = new StreamWriter("output.txt", false, Encoding.UTF8);

만약 ASCII, Windows-1251 또는 UTF-16로 작업하고 싶다면, 다른 인코딩을 넣어주면 됩니다:

using var reader = new StreamReader("myfile.txt", Encoding.Unicode); // UTF-16
using var reader2 = new StreamReader("rus.txt", Encoding.GetEncoding("windows-1251"));

자주 쓰이는 인코딩 간단 표:

인코딩 C# 표현식 설명
UTF-8
Encoding.UTF8
모든 언어 지원, 용량 효율적
UTF-16 (Unicode)
Encoding.Unicode
.NET 표준, 문자당 2바이트
ASCII
Encoding.ASCII
기본 문자(영어)만
Windows-1251
Encoding.GetEncoding("windows-1251")
러시아어, 오래된 Windows 프로그램용

주의! Windows-1251 같은 비표준 인코딩을 쓸 때는 Encoding.GetEncoding("windows-1251")를 사용하세요.

3. 인코딩을 명시해서 읽고 쓰기

작은 미니 앱에 기능 하나를 추가해봅시다: 지정한 인코딩으로 파일을 읽고, 결과를 다른 파일에 명시적으로 지정한 인코딩으로 쓰는 기능이에요. 이렇게 하면 시스템 간 텍스트 변환이 가능합니다.

예 1: Windows-1251 인코딩 파일을 읽어서 화면에 출력하기

// 예: 파일이 오래된 Windows-1251로 생성되었다고 가정
using var reader = new StreamReader("ru_text.txt", Encoding.GetEncoding("windows-1251"));

string line;
while ((line = reader.ReadLine()) != null)
{
    Console.WriteLine(line);
}

왜 중요한가: 인코딩을 지정하지 않으면 러시아어 문자 대신 끔찍한 기호들(예: "Учебник")이 나올 수 있습니다.

예 2: UTF-16 (Unicode)로 파일 쓰기

using var writer = new StreamWriter("utf16text.txt", false, Encoding.Unicode);
writer.WriteLine("안녕, 세상!");
writer.WriteLine("Hello, world!");
writer.WriteLine("こんにちは世界");

결과: 예를 들어 Notepad로 파일을 열어보면 모든 문자가 제대로 표시됩니다.

4. 인코딩 변환용 작은 유틸리티

자주 묻는 과제(면접에서 자주 나옵니다!): 텍스트 파일을 Windows-1251에서 UTF-8로 변환하라.

string sourcePath = "ru_text_1251.txt";
string destPath = "ru_text_utf8.txt";

// Windows-1251 인코딩으로 읽기
using var reader = new StreamReader(sourcePath, Encoding.GetEncoding("windows-1251"));
// UTF-8로 쓰기
using var writer = new StreamWriter(destPath, false, Encoding.UTF8);

string? line;
while ((line = reader.ReadLine()) != null)
    writer.WriteLine(line);

이제 ru_text_utf8.txt는 VSCode, Linux, Mac 등에서 문제없이 열어 읽을 수 있습니다.

5. 유용한 팁

파일이 어떤 인코딩인지 어떻게 알까?

꽤 까다로운 문제입니다! 대부분의 파일은 내부에 인코딩 정보를 저장하지 않습니다(예외로 BOM이 있는 파일이 있긴 해요 — 이건 다음 강의에서 더 자세히 다룹니다). 잘못된 인코딩으로 열면 결과는 그냥 깨진 텍스트가 됩니다.

실무에서 흔히 쓰는 접근법:

  • 파일을 당신이 만든 프로그램이 생성했다면 — 쓰기 때 사용한 동일한 인코딩으로 읽어라.
  • 출처가 불명확한 파일이라면 — 여러 인코딩을 시도해보거나 전용 유틸리티로 인코딩을 검사해라.

이모지와 특이한 문자 다루기

UTF-8UTF-16은 이모지와 여러 언어의 문자를 자유롭게 사용할 수 있게 해줍니다. 이모지를 포함한 파일을 UTF-8로 저장한 뒤 오래된 단일 바이트 인코딩으로 열어보면 재밌는(또는 골치 아픈) 결과를 볼 수 있어요.

이모지 예제:

using var writer = new StreamWriter("emoji.txt", false, Encoding.UTF8);
writer.WriteLine("안녕 👋😀🌍");

StreamReader의 인코딩 자동 감지

StreamReader 생성자에는 detectEncodingFromByteOrderMarks 파라미터를 받는 오버로드가 있습니다:

new StreamReader(path, encoding, detectEncodingFromByteOrderMarks: true)

이 파라미터가 true이면(기본값입니다!), StreamReader는 파일 시작에 있는 BOM을 보고 인코딩을 추측하려 시도합니다. 다만 파일이 BOM 없이 만들어졌거나 진기한 인코딩을 쓴 경우에는 이 자동 감지가 실패할 수 있습니다.

언제/왜 명시적으로 인코딩을 지정해야 할까?

  • 다국어 데이터: 아랍어, 중국어, 이모지 등 다양한 문자를 지원해야 할 때.
  • 통합(Integration): 파일을 여러분 프로그램뿐 아니라 다른 시스템도 읽고 쓴다면, 상대가 기대하는 인코딩을 맞춰줘야 합니다.
  • 파일 크기 중요: 라틴 계열 텍스트는 ASCII/UTF-8가 더 공간 효율적이고, 한자 같은 경우는 UTF-16이 유리할 수 있습니다.
  • 호환성: 로그나 내보내기 파일을 다른 애플리케이션과 공유할 때.

6. 인코딩 작업에서 흔한 실수들

실수 #1: 파일을 읽을 때 인코딩을 명시하지 않음.
러시아어나 다른 비라틴 문자가 들어있는 파일을 인코딩 없이 읽으면 보통 읽을 수 없는 '깨진 문자열'이 나옵니다.

실수 #2: 쓰기와 읽기의 인코딩 불일치.
파일을 한 인코딩으로 썼는데 다른 인코딩으로 열면 텍스트가 왜곡됩니다. OS나 프로그램 간 이동할 때 자주 발생합니다.

실수 #3: 지원하지 않거나 부분적으로만 지원되는 인코딩 사용.
어떤 편집기는 BOM 없는 UTF-8을 제대로 못 보거나, 오래된 단일 바이트 인코딩(예: Windows-1251)을 제대로 처리하지 못할 때가 있습니다. 이럴 땐 수동으로 인코딩을 바꿔보고 실험해야 합니다.

코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION