홈으로 돌아가기

Ude 키릴 오류 C# 인코딩 감지

이 기사는 C#에서 Ude 라이브러리의 잘못된 키릴 인코딩 감지 문제를 분석합니다. Macintosh/Windows-1251을 수정하기 위해 '이상한' 바이트 기반 휴리스틱 방법을 제안합니다. 코드, 제한사항 및 수동 검증 권장사항이 설명됩니다.

Ude 오류 수정: C#에서 mojibake 없는 키릴
Advertisement 728x90

C#에서 Ude를 사용한 키릴 문자 인코딩 오류 해결 방법

C#의 Ude 라이브러리는 키릴 문자가 포함된 텍스트 파일의 인코딩을 때때로 잘못 판단하여, 올바른 Windows-1251 대신 'Macintosh'라고 보고합니다. 이로 인해 텍스트를 읽을 때 깨진 문자(모지바케)가 나타나며, 예상대로 읽히는 러시아어가 이상한 기호로 표시됩니다. 이 문제는 Notepad++에서도 발생하며, CharsetDetector를 사용하는 코드 내부에서도 나타납니다.

GetFileEncoding 메서드에서 Ude는 cdet.Charset를 'Macintosh'로 반환하여 이후 변환 과정에서 오류가 발생합니다:

public static Encoding GetFileEncoding(string filename)
{
    Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);

    using (FileStream fs = File.OpenRead(filename))
    {
        Ude.CharsetDetector cdet = new Ude.CharsetDetector();
        cdet.Feed(fs);
        cdet.DataEnd();

        if (cdet.Charset != null)
        {
            return Encoding.GetEncoding(cdet.Charset);
        }
    }

    return Encoding.GetEncoding(CodePages.Windows1251);
}

ChangeEncodingForMidFile에서 이 잘못된 인코딩을 적용하면 상황이 악화되며, 텍스트가 제대로 읽히지 않고 새로운 파일에 저장될 때 손상됩니다.

Google AdInline article slot
private static void ChangeEncodingForMidFile(string midFile, 
                                             Encoding midFileEncoding, 
                                             string newFullMidFileName)
{
    using StreamReader reader = new StreamReader(midFile, midFileEncoding);

    using StreamWriter writer = new StreamWriter(
        newFullMidFileName,
        false,
        Encoding.GetEncoding(CodePages.Windows1251)
    );

    writer.Write(reader.ReadToEnd());

    File.Delete(midFile);
    File.Move(newFullMidFileName, midFile);
}

MacCyrillic과 Windows-1251의 차이 분석

MacCyrillic(CodePages.Macintosh)와 Windows-1251은 키릴 문자에 대해 서로 다른 바이트 범위를 사용합니다. 일반적인 러시아어 텍스트(희귀 기호 없음)에서는 한 인코딩에 특유하지만 다른 인코딩에서는 흔한 '의심스러운' 바이트를 식별할 수 있습니다:

  • Macintosh에 의심스러운 바이트: Windows-1251에서 흔한 바이트 (0xAB, 0xB8–0xB9, 0xBB, 0xC0–0xC7, 0xC9, 0xCB–0xCF, 0xD2–0xDB, 0xFF).
  • Windows-1251에 의심스러운 바이트: Macintosh에서 흔한 바이트 (0x80–0x8F, 0x90–0x97, 0x99–0x9F).

이 두 집합은 휴리스틱 재검증에 사용됩니다.

private static readonly ArrayList<byte> StrangeForMacintoshBytes = new ArrayList<byte>
{
    0xAB, 
    0xB8, 0xB9, 0xBB,
    0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC9, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
    0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7, 0xD8, 0xD9, 0xDA, 0xDB,
    0xFF
};

private static readonly ArrayList<byte> StrangeForWindows1251Bytes = new ArrayList<byte>
{
    0x80, 0x81, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
    0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F
};

커스텀 인코딩 검출 구현: CustomGetEncoding

Macintosh 또는 MacCyrillic이 감지되면 CustomGetEncoding 메서드가 실행됩니다:

Google AdInline article slot
if (cdet.Charset != null)
{
    var encoding = Encoding.GetEncoding(cdet.Charset);
    if (encoding.CodePage == CodePages.Macintosh || encoding.CodePage == CodePages.MacCyrillic)
        return CustomGetEncoding(encoding, filename);
}

CustomGetEncoding의 로직은 다음과 같습니다:

  • 파일의 바이트를 스캔합니다.
  • StrangeForMacintoshBytes에 속하는 바이트가 발견되면 Windows-1251을 반환합니다.
  • 그렇지 않지만 StrangeForWindows1251Bytes에 속하는 바이트가 있으면 Macintosh를 반환합니다.
  • 의심스러운 바이트가 없으면 기본적으로 Windows-1251을 반환합니다.

이 방식은 단순한 러시아어 텍스트에는 효과적이지만, 모든 경우에 적용되지는 않습니다.

한계점과 권장 사항

이 접근법의 단점:

Google AdInline article slot
  • 희귀 기호가 없는 키릴 텍스트에만 적용 가능.
  • UTF-8이나 기타 인코딩은 처리 불가.
  • 휴리스틱 기반으로 신뢰성 있는 감지 메커니즘은 아님.

사용자에게 권장되는 절차:

  • 파일을 Notepad++에서 열기.
  • Windows-1251, UTF-8 등 다양한 인코딩을 시도해 깨짐이 없을 때까지 확인.
  • 텍스트를 복사하기.
  • 목표 인코딩으로 새 파일을 만들고 내용 붙여넣기.
  • 저장하기.

이 수동 작업조차도 Ude가 인코딩을 잘못 판단할 경우 완전히 성공하지 못할 수 있습니다.

다른 인코딩 감지 라이브러리들도 유사한 문제를 겪습니다. 자동 감지는 본질적으로 확률적이며, 텍스트의 바이트 빈도 패턴에 의존합니다.

핵심 요약

  • Ude는 키릴 파일에서 MacCyrillic과 Windows-1251을 자주 혼동합니다.
  • '의심스러운 바이트' 휴리스틱을 활용해 라이브러리 수정 없이 감지 오류를 해결할 수 있습니다.
  • 이 해결책은 기본적인 러시아어 텍스트에만 유효합니다.
  • 항상 처리 전에 Notepad++에서 인코딩을 수동으로 확인하세요.
  • 인코딩 감지는 확률적입니다. 오류는 피할 수 없습니다.

— Editorial Team

Advertisement 728x90

다음 읽기