• 카테고리

    질문 & 답변
  • 세부 분야

    프로그래밍 언어

  • 해결 여부

    미해결

콘솔창에서 한글이 깨지는 이유

23.09.07 22:33 작성 23.09.07 22:37 수정 조회수 459

1

 #include <stdio.h>
#include <windows.h>

int main(int argc, char* argv[])
{
	int ch;

	FILE* fr, * fw;

	//const UINT default_cp = GetConsoleOutputCP();
	//printf("%u\n", default_cp);

	const char* in_filename = "원본.txt";
	const char* out_filename = "사본.txt";

	unsigned long count = 0;

	if ((fr = fopen(in_filename, "r")) == NULL)
	{
		printf("can't open %s\n", in_filename);
		exit(EXIT_FAILURE);
	} 
	if ((fw = fopen(out_filename, "w")) == NULL)
	{
		printf("can't open %s\n", out_filename);
		exit(EXIT_FAILURE);
	}
	
	//SetConsoleOutputCP(CP_UTF8);

	while ((ch = fgetc(fr)) != EOF)
	{
		fputc(ch, stdout);
		fputc(ch, fw);
		count++;
	}

	fclose(fr);
	fclose(fw);

	//SetConsoleOutputCP(default_cp);

	printf("file %s has %lu characters\n", in_filename, count);
	printf("copied to %s\n", out_filename);

	printf("한글 출력 확인");
	
	return 0;
}

 

제가 제대로 이해한건지 헷갈리네요...

강의 2:45 콘솔창에서 한글이 깨지는 이유는 텍스트 파일의 인코딩 방식은 UTF8(== 인코딩방식 == 코드페이지)인데 콘솔창의 인코딩 방식과 다르기 때문이 맞나요?


원본.txt에 담겨있는 데이터는 컴퓨터 내부에서 바이너리로 저장되어있습니다. (프로그램을 통해 인코딩을 해도 이 바이너리 데이터 자체는 바뀌지않음)

이 바이너리 데이터를 메모장은 UTF8 인코딩 방식을 통해서 인코딩 한 후 출력하기 때문에 메모장에서는 한글이 제대로 출력 되는 것이고,

프로그램은 이 바이너리 데이터를 그대로 읽어왔지만 콘솔창의 인코딩 방식은 UTF8이 아니기 때문에 인코딩 과정에서 한글은 제대로 인코딩이 안되고 그렇기에 한글은 깨지는것.

 그러므로 SetConsoleOutputCP(CP_UTF8);를 통해 콘솔창의 인코딩방식을 UTF8로 바꾸어 준 후 실행하면 한글이 제대로 출력 됨.

마지막으로 복사한 사본.txt파일의 데이터는 원본.txt에 담겨있는 바이너리 데이터 그 자체를 그대로 복사한 것이고 그것을 메모장에서 열면 인코딩방식이 일치하기에 사본.txt파일은 한글이 깨지지 않는다.

맞을까요?

 

감사합니다!!!

 

답변 1

답변을 작성해보세요.

1

Soobak님의 프로필

Soobak

2023.09.08

안녕하세요, 답변도우미 Soobak 입니다.

네, 잘 이해하고 계십니다.

텍스트 파일(원본.txt)의 인코딩 방식이 UTF-8 이라면, 그 파일은 UTF-8 방식으로 인코딩된 바이너리 데이터로 저장됩니다.

이 때 만약, 콘솔의 기본 인코딩 방식이 UTF-8과 다르면, 파일로부터 바이너리 데이터를 읽어올 때 콘솔에 그 데이터를 제대로 디코딩하여 표시할 수 없게 됩니다.
그 결과 한글이 깨져 보일 수 있습니다.

따라서, 말씀해주신 방법처럼 SetConsoleOutputCP(CP_UTF8); 을 통해 콘솔의 출력 인코딩 방식을 uTF-8 로 변경하면, 콘솔의 인코딩 방식과 파일의 인코딩 방식이 일치하게 되어 한글이 제대로 출력될 수 있게 됩니다.

복사된 사본.txt 에 대한 설명도 옳으십니다.
원본 파일의 바이너리 데이터를 그대로 복사하기 때문에, 메모장 등에서 파일을 열 때, 그 파일도 UTF-8 으로 인코딩 된 것으로 간주되어 제대로 데이터가 표시되는 것 입니다.

즉, 텍스트 데이터는 어떤 방식으로 인코딩되었는지, 그리고 그 인코딩된 데이터를 어떻게 해석(디코딩)하고 표시할 것인지에 따라 결과가 달라진다는 점이 중요한 부분입니다.

CJS님의 프로필

CJS

질문자

2023.09.14

감사합니다!!

용개형멋져님의 프로필

용개형멋져

2024.03.11

수박님 답변을 보고 이해가 잘 안되는 부분이 있어서 질문드립니다
정확한 표현인지는 모르겠지만 문자를 이진수로 변환하는게 인코딩이고
이진수를 문자로 변환하는게 디코딩이라면

 

이 때 만약, 콘솔의 기본 인코딩 방식이 UTF-8과 다르면, 파일로부터 바이너리 데이터를 읽어올 때 콘솔에 그 데이터를 제대로 디코딩하여 표시할 수 없게 됩니다.

 

여기서 콘솔의 기본 인코딩 방식에서 인코딩이 아니라 디코딩이 아닌가요?
콘솔은 이진수로 저장된 데이터를 디코딩해서 화면에 출력하는게 아닌가요?
문장 뒷부분에서는 디코딩이라고 말씀을 하시는데 앞의 인코딩과 뒤의 디코딩은 다른 것 인가요?

 

항상 좋은 답변 정말 감사합니다.

Soobak님의 프로필

Soobak

2024.03.12

안녕하세요, 질문&답변 도우미 Soobak 입니다.

 

네, 말씀하신 내용이 맞습니다.

문자를 이진수로 변환하는 과정을 '인코딩' 이라고 한다면, 이진수를 다시 문자로 변환하는 과정이 '디코딩'이 됩니다. 여기서, 중요한 점은 '인코딩' 과 '디코딩' 은 서로 반대 방향의 작업이며, 관점에 따라 다르게 표현될 수 있다는 점입니다.

본 답변의 설명에서 "콘솔의 기본 인코딩 방식이 UTF-8 과 다르면, 파일로부터 바이너리 데이터를 읽어올 때 콘솔에 그 데이터를 제대로 디코딩하여 표시할 수 없게 됩니다." 라고 말씀드린 부분은 '콘솔' 에서 데이터를 제대로 '읽어오고 해석(디코딩)하는 과정' 을 의미합니다.
즉, 콘솔이 파일로부터 바이너리 데이터를 읽어올 때, 이 데이터를 어떻게 해석할지는 콘솔의 기본 디코딩 방식에 의해 결정됨을 설명드린 것이었습니다.

이 때, '인코딩 방식' 이라고 표현한 것은, 말씀하시는 것처럼 '디코딩 방식' 을 의미하는 것이 더 정확합니다. 사용자의 관점에서 혼동을 드릴 수 있는 잘못된 표현을 사용하였네요.

좋은 지적해주셔서 진심으로 감사드립니다.