텍스트 파일의 인코딩 / 코드 페이지를 감지하는 방법


295

우리의 응용 프로그램에서, 우리는 텍스트 파일 (수신 .txt, .csv다양한 소스 등). 읽을 때 다른 / 알 수없는 코드 페이지에서 작성된 파일 때문에 이러한 파일에는 가비지가 포함되는 경우가 있습니다.

텍스트 파일의 코드 페이지를 (자동으로) 감지하는 방법이 있습니까?

detectEncodingFromByteOrderMarks의에 StreamReader생성자, 작동 UTF8 및 기타 유니 코드 표시 파일,하지만 난 같은 코드 페이지를 감지 할 수있는 방법을 찾고 있어요 ibm850, windows1252.


답변 해 주셔서 감사합니다. 이것이 제가 한 일입니다.

우리가받는 파일은 최종 사용자가 제공 한 것으로 코드 페이지에 대한 실마리는 없습니다. 수신자는 최종 사용자이기도합니다. 이제는 코드 페이지에 대해 알고 있습니다. 코드 페이지가 존재하며 성가 시게합니다.

해결책:

  • 받은 파일을 메모장에서 열고 깨진 텍스트를보십시오. 누군가 프랑수아 (François)라고 불리는 사람이 있다면 인간의 지능으로 추측 할 수 있습니다.
  • 사용자가 파일을 여는 데 사용할 수있는 작은 앱을 만들고 올바른 코드 페이지가 사용될 때 파일에 표시 될 텍스트를 입력합니다.
  • 모든 코드 페이지를 반복하고 사용자가 제공 한 텍스트로 솔루션을 제공하는 코드 페이지를 표시하십시오.
  • 하나 이상의 코드 페이지가 나타나면 사용자에게 더 많은 텍스트를 지정하도록 요청하십시오.

답변:


260

코드 페이지를 감지 할 수 없으므로 알려야합니다. 바이트를 분석하고 추측 할 수는 있지만 기괴한 (때로는 재미있는) 결과를 줄 수 있습니다. 나는 지금 그것을 찾을 수 없지만 메모장이 중국어로 영어 텍스트를 표시하도록 속일 수 있다고 확신합니다.

어쨌든, 이것은 당신이 읽어야 할 것입니다 : 절대 최소 모든 소프트웨어 개발자는 절대적으로, 유니 코드와 문자 세트에 대해 알아야합니다 (변명 없음!) .

구체적으로 Joel은 말합니다.

인코딩에 관한 가장 중요한 사실

방금 설명한 모든 것을 완전히 잊어 버린 경우 매우 중요한 사실을 기억하십시오. 어떤 인코딩을 사용하는지 모른 채 문자열을 갖는 것은 의미가 없습니다. 더 이상 머리를 모래에 붙일 수 없으며 "일반"텍스트가 ASCII 인 것처럼 가장 할 수 없습니다. 일반 텍스트와 같은 것은 없습니다.

문자열, 메모리, 파일 또는 전자 메일 메시지가있는 경우 어떤 인코딩인지 알고 있어야합니다. 그렇지 않으면 해석하거나 사용자에게 올바르게 표시 할 수 없습니다.


43
나는 두 가지 이유로이 답변을 하향 투표했다. 첫째, "알아야 할 필요가있다"고 말하는 것은 도움이되지 않습니다. 누가 나에게 말 하겠는가? 그들은 어떤 매체를 통해 그렇게 할 것입니까? 파일을 저장 한 사람이라면 누구에게 물어 볼까요? 자기? 둘째,이 기사는 질문에 대한 답변을 제공하는 자료로는 특별히 도움이되지 않습니다. 이 기사는 David Sedaris 스타일로 작성된 인코딩의 역사에 더 가깝습니다. 나는 이야기를 고맙게 생각하지만 단순히 / 직접 질문에 대답하지는 않습니다.
geneorama

9
@geneorama, Joel의 기사가 귀하의 질문을 내가 할 수있는 것보다 더 잘 해결한다고 생각합니다. 그러나 여기서는 ... 매체는 반드시 텍스트가 수신되는 환경에 달려 있습니다. 파일 (또는 기타)에 해당 정보가 포함되어있는 것이 좋습니다 (HTML과 XML을 생각하고 있습니다). 그렇지 않으면 텍스트를 보내는 사람이 해당 정보를 제공 할 수 있어야합니다. 파일을 만든 사람이라면 어떤 인코딩을 사용하는지 어떻게 알 수 없습니까?
JV.

4
@geneorama, 계속 ... 마지막으로, 기사가 단순히 질문에 대답하지 않는 주된 이유는 그 질문에 대한 간단한 대답이 없기 때문이라고 생각합니다. 질문이 "어떻게 추측 할 수 있을까 ..."였다면 다르게 대답했을 것입니다.
JV.

1
@JV 나는 나중에 유용한 tidbit를 언급했기 때문에 xml / html이 문자 인코딩을 지정할 수 있다는 것을 배웠다.
geneorama

1
@JV "파일 만들기"는 단어를 잘못 선택했을 수 있습니다. 사용자가 생성 한 파일의 인코딩을 사용자가 지정할 수 있다고 가정합니다. 최근에 Hive를 사용하여 Hadoop 클러스터에서 파일을 "만들어"여러 클라이언트 컴퓨터로 다운로드하기 전에 FTP로 전달했습니다. 결과에는 유니 코드 가비지가 있었지만 어느 단계에서 문제가 발생했는지 알 수 없습니다. 인코딩을 명시 적으로 지정하지 않았습니다. 각 단계에서 인코딩을 확인할 수 있기를 바랍니다.
geneorama

31

비 UTF 인코딩 (예 : BOM 없음)을 감지하려는 경우 기본적으로 텍스트의 휴리스틱 및 통계 분석을 따릅니다. 범용 문자셋 감지 ( Wayback Machine을 통한 더 나은 형식의 동일한 링크) 대한 Mozilla 백서를 살펴볼 수 있습니다 .


9
재미있게도 내 Firefox 3.05 설치는 해당 페이지를 UTF-8로 감지하여 다이아몬드에 많은 물음표 모양을 표시하지만 소스에는 Windows-1252의 메타 태그가 있습니다. 문자 인코딩을 수동으로 변경하면 문서가 올바르게 표시됩니다.
devstuff

5
"UTF가 아닌 인코딩을 감지하려는 경우 (예 : BOM 없음)"문장이 약간 잘못되었습니다. 유니 코드 표준은 utf-8 문서에 BOM을 추가하지 않는 것이 좋습니다! (이 권장 사항 또는 부족한 것이 많은 두통의 원인입니다). 참조 : en.wikipedia.org/wiki/Byte_order_mark#UTF-8
Tao

이는 중복 BOM을 누적하지 않고 UTF-8 문자열을 연결할 수 있도록하기위한 것입니다. 또한 UTF-16과 달리 바이트 순서 표시는 UTF-8에 필요하지 않습니다.
sashoalm

26

Mozilla Universal Charset Detector에 C # 포트를 사용해 보셨습니까?

http://code.google.com/p/ude/의

public static void Main(String[] args)
{
    string filename = args[0];
    using (FileStream fs = File.OpenRead(filename)) {
        Ude.CharsetDetector cdet = new Ude.CharsetDetector();
        cdet.Feed(fs);
        cdet.DataEnd();
        if (cdet.Charset != null) {
            Console.WriteLine("Charset: {0}, confidence: {1}", 
                 cdet.Charset, cdet.Confidence);
        } else {
            Console.WriteLine("Detection failed.");
        }
    }
}    

1
Windows-1252 유형에서 완벽하게 작동했습니다.
seebiscuit 2016

어떻게 그것을 사용하여 텍스트 파일을 문자열로 읽을 수 있습니까? CharsetDetector는 인코딩 형식을 문자열 형식으로 반환합니다.
Bartosz

@Bartosz private Encoding GetEncodingFromString(string encoding) { try { return Encoding.GetEncoding(encoding); } catch { return Encoding.ASCII; } }
PrivatePyle

15

코드 페이지를 감지 할 수 없습니다

이것은 분명히 거짓입니다. 모든 웹 브라우저에는 어떤 종류의 인코딩도 표시하지 않는 페이지를 처리하는 일종의 범용 문자 집합 검출기가 있습니다. Firefox에는 하나가 있습니다. 코드를 다운로드하여 코드가 어떻게 작동하는지 확인할 수 있습니다. 여기에서 일부 문서를 참조 하십시오 . 기본적으로 휴리스틱이지만 실제로는 잘 작동합니다.

적당한 양의 텍스트가 주어지면 언어를 감지하는 것조차 가능합니다.

방금 Google을 사용하여 찾은 또 다른 것이 있습니다.


39
"휴리스틱"-브라우저가이를 감지하지 못하여 교육적인 추측을하고 있습니다. "정말 잘 작동합니다"-그래도 항상 작동하지 않습니까? 우리가 동의하는 것처럼 들립니다.
JV.

10
HTML 표준에 따르면 문서에서 문자 집합을 정의하지 않으면 UTF-8로 인코딩 된 것으로 간주해야합니다.
Jon Trauntvein

5
비표준 HTML 문서를 읽지 않으면 멋지다. 또는 HTML이 아닌 문서.
Kos

2
이 답변은 잘못되었으므로 공감해야했습니다. 코드 페이지를 감지 할 수 없다는 것이 거짓이라고 말하는 것은 잘못입니다. 추측 할 수 있고 추측은 다소 좋지만 코드 페이지를 "감지"할 수는 없습니다.
z80crew

1
@JonTrauntvein HTML5 사양 에 따르면 a character encoding declaration is required even if the encoding is US-ASCII선언이 없으면 UTF8로 돌아 가지 않고 휴리스틱 알고리즘을 사용합니다.
z80crew

9

나는이 질문에 매우 늦었다는 것을 알고 있으며 (영어 중심의 편견과 통계 / 실험 테스트가 없기 때문에)이 솔루션에 호소하지 않지만 특히 업로드 된 CSV 데이터를 처리하는 데 매우 효과적입니다.

http://www.architectshack.com/TextFileEncodingDetector.ashx

장점 :

  • BOM 감지 내장
  • 사용자 정의 가능한 기본 / 대체 인코딩
  • UTF-8과 라틴 1 스타일 파일이 혼합 된 이국적인 데이터 (예 : 프랑스어 이름)가 포함 된 서유럽 기반 파일에 대해 상당히 신뢰할 만합니다 (기본적으로 미국과 서유럽 환경).

참고 : 저는이 수업을 썼던 사람이므로 소금 한 덩어리로 가져 가십시오! :)



7

다른 솔루션을 찾고 있는데

https://code.google.com/p/ude/

이 솔루션은 다소 무겁습니다.

4 바이트와 xml 문자 세트를 기반으로 한 기본적인 인코딩 감지가 필요했습니다. 그래서 인터넷에서 샘플 소스 코드를 가져 와서 약간 수정 된 버전을 추가했습니다.

http://lists.w3.org/Archives/Public/www-validator/2002Aug/0084.html

Java 용으로 작성되었습니다.

    public static Encoding DetectEncoding(byte[] fileContent)
    {
        if (fileContent == null)
            throw new ArgumentNullException();

        if (fileContent.Length < 2)
            return Encoding.ASCII;      // Default fallback

        if (fileContent[0] == 0xff
            && fileContent[1] == 0xfe
            && (fileContent.Length < 4
                || fileContent[2] != 0
                || fileContent[3] != 0
                )
            )
            return Encoding.Unicode;

        if (fileContent[0] == 0xfe
            && fileContent[1] == 0xff
            )
            return Encoding.BigEndianUnicode;

        if (fileContent.Length < 3)
            return null;

        if (fileContent[0] == 0xef && fileContent[1] == 0xbb && fileContent[2] == 0xbf)
            return Encoding.UTF8;

        if (fileContent[0] == 0x2b && fileContent[1] == 0x2f && fileContent[2] == 0x76)
            return Encoding.UTF7;

        if (fileContent.Length < 4)
            return null;

        if (fileContent[0] == 0xff && fileContent[1] == 0xfe && fileContent[2] == 0 && fileContent[3] == 0)
            return Encoding.UTF32;

        if (fileContent[0] == 0 && fileContent[1] == 0 && fileContent[2] == 0xfe && fileContent[3] == 0xff)
            return Encoding.GetEncoding(12001);

        String probe;
        int len = fileContent.Length;

        if( fileContent.Length >= 128 ) len = 128;
        probe = Encoding.ASCII.GetString(fileContent, 0, len);

        MatchCollection mc = Regex.Matches(probe, "^<\\?xml[^<>]*encoding[ \\t\\n\\r]?=[\\t\\n\\r]?['\"]([A-Za-z]([A-Za-z0-9._]|-)*)", RegexOptions.Singleline);
        // Add '[0].Groups[1].Value' to the end to test regex

        if( mc.Count == 1 && mc[0].Groups.Count >= 2 )
        {
            // Typically picks up 'UTF-8' string
            Encoding enc = null;

            try {
                enc = Encoding.GetEncoding( mc[0].Groups[1].Value );
            }catch (Exception ) { }

            if( enc != null )
                return enc;
        }

        return Encoding.ASCII;      // Default fallback
    }

아마도 파일에서 처음 1024 바이트를 읽는 것으로 충분하지만 전체 파일을로드하고 있습니다.


7

누군가가 93.9 % 해결책을 찾고 있다면. 이것은 나를 위해 작동합니다 :

public static class StreamExtension
{
    /// <summary>
    /// Convert the content to a string.
    /// </summary>
    /// <param name="stream">The stream.</param>
    /// <returns></returns>
    public static string ReadAsString(this Stream stream)
    {
        var startPosition = stream.Position;
        try
        {
            // 1. Check for a BOM
            // 2. or try with UTF-8. The most (86.3%) used encoding. Visit: http://w3techs.com/technologies/overview/character_encoding/all/
            var streamReader = new StreamReader(stream, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true), detectEncodingFromByteOrderMarks: true);
            return streamReader.ReadToEnd();
        }
        catch (DecoderFallbackException ex)
        {
            stream.Position = startPosition;

            // 3. The second most (6.7%) used encoding is ISO-8859-1. So use Windows-1252 (0.9%, also know as ANSI), which is a superset of ISO-8859-1.
            var streamReader = new StreamReader(stream, Encoding.GetEncoding(1252));
            return streamReader.ReadToEnd();
        }
    }
}

아주 좋은 해결책입니다. 두 개 이상의 인코딩 (UTF-8 및 ASCI 1252)을 허용해야하는 경우 허용 된 인코딩 루프에서 ReadAsString () 본문을 쉽게 래핑 할 수 있습니다.
ViRuSTriNiTy 2016 년

수많은 예제를 시도한 후 마침내 나는 네게 도착했다. 나는 지금 행복한 장소에 있습니다. LOL 감사합니다 !!!!!!!!!
Sedrick

이것은 1252 대 1250을 감지하는 방법에 대한 대답은 아니지만 BOM이 있거나없는 "UTF-8을 감지하는 방법"에 대한 대답이어야합니다 !!
chuckc

4

파이썬에서 비슷한 것을했습니다. 기본적으로 다양한 인코딩의 샘플 데이터가 많이 필요합니다.이 인코딩은 2 바이트 슬라이딩 창으로 분류되고 인코딩 목록 값을 제공하는 바이트 쌍을 기준으로 사전 (해시)에 저장됩니다.

해당 사전 (해시)이 주어지면 입력 텍스트를 가져 와서 다음을 수행하십시오.

  • BOM 문자로 시작하는 경우 (UTF-16-BE의 경우 '\ xfe \ xff', UTF-16-LE의 경우 '\ xff \ xfe', UTF-8의 경우 '\ xef \ xbb \ xbf'등) 그것을 제안대로 취급
  • 그렇지 않은 경우 충분한 양의 텍스트 샘플을 가져 와서 샘플의 모든 바이트 쌍을 가져 와서 사전에서 제안 된 최소 인코딩을 선택하십시오.

BOM으로 시작 하지 않는 UTF 인코딩 텍스트를 샘플링 한 경우 두 번째 단계는 첫 번째 단계에서 미끄러 진 텍스트를 다룹니다.

지금까지 오류율이 감소하면서 샘플 데이터와 후속 입력 데이터가 다양한 언어의 자막입니다.


4

"uchardet"도구는 각 문자셋에 대한 문자 빈도 분포 모델을 사용하여이를 잘 수행합니다. 더 큰 파일과 더 많은 "일반적인"파일은 더 확실합니다.

우분투에서, 당신은 단지 apt-get install uchardet.

다른 시스템의 경우 여기에서 소스, 사용법 및 문서를 얻으십시오. https://github.com/BYVoid/uchardet


Homebrew를 통해 Mac에서 :brew install uchardet
Paul B

3

StreamReader 클래스의 생성자는 '인코딩 감지'매개 변수를 사용합니다.


그것은 단지 "인코딩" 링크입니다 . 그리고 설명은 우리가 인코딩을 제공해야한다고 말합니다.
SurajS

@SurajS : 다른 과부하를보십시오.
leppie

원래 작성자는 파일에 대한 인코딩을 감지하려고하며 BOM 마커가 없을 수 있습니다. StreamReader는 서명별로 BOM 헤더에서 인코딩을 감지합니다. 공중에서는 StreamReader (스트림 스트림, 부울 detectEncodingFromByteOrderMarks)
ibondre

1

C 라이브러리에 연결할 수 있으면을 사용할 수 있습니다 libenca. http://cihar.com/software/enca/를 참조 하십시오 . 매뉴얼 페이지에서 :

Enca는 주어진 텍스트 파일 또는없는 경우 표준 입력을 읽고 해당 언어에 대한 지식 (사용자가 지원해야 함)과 구문 분석, 통계 분석, 추측 및 흑 마법을 혼합하여 인코딩을 결정합니다.

GPL v2입니다.


0

같은 문제가 있지만 자동으로 감지하는 좋은 해결책을 찾지 못했습니다. 이제 PsPad (www.pspad.com)를 사용하고 있습니다.)


0

기본적으로 휴리스틱에 따라 달라지기 때문에 첫 번째 힌트와 동일한 소스에서 이전에 수신 한 파일의 인코딩을 사용하는 데 도움이 될 수 있습니다.

대부분의 사람들 (또는 응용 프로그램)은 매번 거의 같은 컴퓨터에서 거의 같은 순서로 작업을 수행하므로 Bob이 .csv 파일을 만들어 Mary로 보낼 때 항상 Windows-1252를 사용하거나 그의 기계가 기본적으로 무엇이든.

가능한 경우 약간의 고객 교육은 다음 중 하나를 해치지 않습니다.


0

실제로 파일 인코딩을 감지하는 프로그래밍 방식이 아닌 일반적인 방법을 찾고 있었지만 아직 찾지 못했습니다. 다른 인코딩으로 테스트하여 찾은 것은 텍스트가 UTF-7이라는 것입니다.

그래서 내가 처음했던 곳 : StreamReader file = File.OpenText (fullfilename);

나는 그것을 다음과 같이 변경해야했다 : StreamReader file = new StreamReader (fullfilename, System.Text.Encoding.UTF7);

OpenText는 UTF-8이라고 가정합니다.

파일의 바이트 순서 표시에서 인코딩을 시도하고 감지해야하지만 두 번째 매개 변수 인이 새로운 StreamReader (fullfilename, true)와 같은 StreamReader를 만들 수도 있지만 제 경우에는 작동하지 않습니다.


@JohnMachin 나는 그것이 드물다는 것에 동의하지만, 그것은 예를 들어 IMAP 프로토콜의 일부에서 요구됩니다. 그것이 당신이 어디에 있다면, 당신은 추측 할 필요가 없습니다.
tripleee

0

AkelPad에서 파일을여십시오 (또는 잘못된 텍스트를 복사 / 붙여 넣기 만하십시오). 편집-> 선택-> 레코딩 ...-> "자동 감지"로 이동하십시오.


0

ITmeze 포스트의 애드온으로서이 기능을 사용하여 Mozilla Universal Charset Detector의 C # 포트 출력을 변환했습니다.

    private Encoding GetEncodingFromString(string codePageName)
    {
        try
        {
            return Encoding.GetEncoding(codePageName);
        }
        catch
        {
            return Encoding.ASCII;
        }
    }

MSDN


0

언급 해 주신 @ Erik Aronesty 에게 감사드립니다 uchardet.

한편 리눅스에는 (같은?) 도구가 있습니다 chardet.
또는 cygwin에서 다음을 사용할 수 있습니다 chardetect..

참조 : chardet 매뉴얼 페이지 : https://www.commandlinux.com/man-page/man1/chardetect.1.html

그러면 주어진 각 파일의 문자 인코딩을 경험적으로 감지 (추측)하고 각 파일의 감지 된 문자 인코딩에 대한 이름과 신뢰 수준을보고합니다.


-1

이 코드를 사용하여 파일을 읽을 때 유니 코드 및 Windows 기본 ANSI 코드 페이지를 감지합니다. 다른 코딩의 경우 수동 또는 프로그래밍을 통해 컨텐츠를 확인해야합니다. 텍스트를 열 때와 동일한 인코딩으로 텍스트를 저장하는 데 사용할 수 있습니다. (VB.NET을 사용합니다)

'Works for Default and unicode (auto detect)
Dim mystreamreader As New StreamReader(LocalFileName, Encoding.Default) 
MyEditTextBox.Text = mystreamreader.ReadToEnd()
Debug.Print(mystreamreader.CurrentEncoding.CodePage) 'Autodetected encoding
mystreamreader.Close()

-1

이것이 요청 된 후 10 년 (!)이 지났지 만 여전히 MS의 GPL이 아닌 좋은 솔루션 인 IMultiLanguage2 API에 대한 언급이 없습니다 .

이미 언급 된 대부분의 라이브러리는 Mozilla의 UDE를 기반으로합니다. 브라우저가 이미 유사한 문제를 해결 한 것이 합리적입니다. 크롬 솔루션이 무엇인지 모르지만 IE 5.0 MS가 릴리스 한 이후로 다음과 같습니다.

  1. GPL과 같은 라이센스 문제가 없으며,
  2. 아마 영원히 백업하고 유지
  3. 풍부한 결과를 제공합니다-신뢰 점수와 함께 인코딩 / 코드 페이지의 모든 유효한 후보,
  4. 놀랍게도 사용하기 쉽습니다 (단일 함수 호출입니다).

기본 COM 호출이지만 .net 사용에 대한 interop 혼란을 처리하는 Carsten Zeumer의 훌륭한 작업 이 있습니다. 주위에 다른 사람들이 있지만,이 라이브러리는 그만한 가치를 얻지 못합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.