281

신청서에는 텍스트 파일 (.txt,.csv, 등). 이 파일을 읽을 때 다른 / 알 수없는 코드 페이지에서 작성된 파일이기 때 문에 가비지가 포함되는 경우가 있습니다.

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

그만큼detectEncodingFromByteOrderMarks,에StreamReader생성자, 작품UTF8및 기타 유니 코드 표시된 파일,하지만 코드 페이지를 검색 할 수있는 방법을 찾고 있어요.ibm850,windows1252.


귀하의 답변을 주셔서 감사합니다, 이것은 내가 한 짓입니다.

우리가받는 파일은 최종 사용자가 제공하는 코드 페이지에 대한 단서가 없습니다. 리시버는 최종 사용자이기도합니다. 지금은 코드 페이지에 대해 알고있는 내용입니다. 코드 페이지가 있고 성가시다.

해결책:

  • 받은 파일을 메모장에서 열고 텍스트가 깨져 보이는지 확인하십시오. 누군가가 프랑수아라고 부르는 사람이라면, 당신의 인간 정보와 함께 이것을 추측 할 수 있습니다.
  • 필자는 사용자가 파일을 열 때 사용할 수있는 작은 응용 프로그램을 만들었으며 올바른 코드 페이지가 사용되면 사용자가 파일에 표시 할 텍스트를 입력합니다.
  • 모든 코드 페이지를 반복하고 사용자가 제공 한 텍스트로 솔루션을 제공하는 코드 페이지를 표시하십시오.
  • 하나 이상의 코드 페이지가 팝업되면 사용자에게 더 많은 텍스트를 지정하도록 요청하십시오.

20 답변


252

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

어쨌든, 이것은 당신이 읽을 필요가있는 것입니다 :절대적으로 모든 소프트웨어 개발자가 절대적으로, 절대적으로 유니 코드와 문자 집합에 대해 알아야 함 (변명의 여지가 없음).

특히 요엘은 이렇게 말합니다.

인코딩에 대한 가장 중요한 단일 사실

방금 설명한 모든 것을 완전히 잊어 버린 경우 매우 중요한 사실 하나를 기억하십시오. 어떤 인코딩을 사용하는지 알지 못한 채 문자열을 갖는 것은 이치에 맞지 않습니다. 더 이상 머리를 모래에 붙이지 않고 "일반"텍스트를 ASCII로 가장 할 수 있습니다.   그러한 것은 일반 텍스트로 존재하지 않습니다.

문자열, 메모리, 파일 또는 전자 메일 메시지가있는 경우 해당 인코딩이 무엇인지 알거나 해석하거나 사용자에게 올바르게 표시 할 수 없습니다.


  • 그것을 발견:en.wikipedia.org/wiki/Bush_hid_the_facts - JV.
  • 나는이 대답을 두 가지 이유로 downvoted. 먼저, " 말할 필요가 있습니다 " 도움이되지 않습니다. 누가 나에게 말할 것이며, 어떤 매체를 통해 그렇게 할 수 있을까요? 파일을 저장 한 사람이 누구인지 물어볼 수 있습니까? 자기? 둘째,이 기사는 질문에 대답하기위한 자료로 특히 도움이되지 않습니다. 이 기사는 데이비드 세다리스 (David Sedaris) 스타일로 쓰여진 인코딩의 역사에 관한 것입니다. 내러티브를 고맙게 생각하지만 단순히 질문에 직접 대답하지는 않습니다. - geneorama
  • @geneorama, Joel의 기사가 내가 할 수있는 것보다 더 나은 질문을 제기한다고 생각하지만, 여기에 있습니다 ... 매체는 반드시 텍스트가 수신되는 환경에 따라 다릅니다. 파일 (또는 무엇이든)에 해당 정보가 포함되어있는 것이 더 낫습니다 (HTML 및 XML을 생각하고 있습니다). 그렇지 않으면 텍스트를 보내는 사람은 그 정보를 제공 할 수 있어야합니다. 파일을 만든 사람이라면 사용하는 인코딩을 어떻게 알 수 있습니까? - JV.
  • @geneorama, 계속 ... 마지막으로, 그 기사에 대한 간단한 대답이 없기 때문에 기사가 단순히 대답하지 못하는 주된 이유가 있다고 생각합니다. 질문이 " 어떻게 알 수 있습니까? " 그러면 나는 다르게 대답했을 것입니다. - JV.
  • @JV 나중에 xml / html에서 문자 인코딩을 지정할 수 있음을 알게되었습니다. 유용한 tidbit를 언급 해 주셔서 감사합니다. - geneorama

30

비 UTF 인코딩 (즉, BOM 없음)을 검색하려는 경우 기본적으로 텍스트의 휴리스틱 및 통계 분석을 수행합니다. 당신은 당신의유니버설 문자셋 탐지에 대한 Mozilla 논문(Wayback Machine을 통한 더 나은 서식 지정을 통한 동일한 링크).


  • 우습게도 Firefox 3.05 설치는 UTF-8로 해당 페이지를 감지합니다.이 문서에는 Windows-1252 용 메타 태그가 있지만 다이아몬드 물음표가 많이 표시됩니다. 문자 인코딩을 수동으로 변경하면 문서가 올바르게 표시됩니다. - devstuff
  • " UTF가 아닌 인코딩 (즉, BOM 없음)을 감지하려는 경우 " " 약간 오해의 소지가있다. 유니 코드 표준은 utf-8 문서에 BOM을 추가하지 않는 것이 좋습니다! (그리고이 권고, 또는 그것의 부족은 많은 두통의 근원이다). 심판 :en.wikipedia.org/wiki/Byte_order_mark#UTF-8 - Tao
  • 이렇게하면 중복 BOM이 누적되지 않고 UTF-8 문자열을 연결할 수 있습니다. 게다가 Byte-Order Mark는 예를 들어 UTF-16과 달리 UTF-8에는 필요하지 않습니다. - sashoalm
  • 링크가 다운되었습니다. - Mateusz Piotrowski

21

시도해 봤어?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.");
        }
    }
}    


  • Windows-1252 유형에 완벽하게 작동했습니다. - seebiscuit
  • 그리고 어떻게 그것을 사용하여 문자열에 텍스트 파일을 읽을 수 있습니까? CharsetDetector는 문자열 형식의 인코딩 이름을 반환합니다. - Bartosz
  • @Bartoszprivate Encoding GetEncodingFromString(string encoding) { try { return Encoding.GetEncoding(encoding); } catch { return Encoding.ASCII; } } - PrivatePyle

15

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

이것은 분명히 거짓입니다. 모든 웹 브라우저에는 인코딩과 관련이 전혀없는 페이지를 처리 할 수있는 범용 문자 집합 감지기가 있습니다. Firefox에는 하나가 있습니다. 코드를 다운로드하고 코드를 확인하십시오. 몇 가지 문서보기이리. 기본적으로, 그것은 휴리스틱이지만, 실제로 잘 작동합니다.

합리적인 양의 텍스트가 주어지면 언어를 탐지 할 수도 있습니다.

또 하나가있다.방금 Google을 사용하여 찾았습니다.


  • "휴리스틱 스 (heuristics)" - 브라우저가이를 감지하지 못해 교양있는 추측을합니다. " 정말 잘 작동합니다 " - 그렇다면 항상 작동하지 않습니까? 우리가 동의하는 것처럼 들리네. - JV.
  • HTML의 표준은 문자 세트가 문서에 의해 정의되지 않은 경우 UTF-8로 인코딩되어야한다고 규정합니다. - Jon Trauntvein
  • 비표준 HTML 문서를 읽지 않는 한 멋있습니다. 또는 비 HTML 문서. - Kos
  • 이 대답은 잘못되었으므로 나는 downvote해야만했다. 코드 페이지를 감지 할 수 없다고 거짓이라고 말하면 잘못된 것입니다. 추측 할 수 있고 추측은 다소 좋을 수 있지만 "감지"할 수는 없습니다. 코드 페이지. - z80crew
  • @JonTrauntvein에 따르면HTML5 사양 a character encoding declaration is required even if the encoding is US-ASCII- 부족한 선언은 UTF8로 돌아가는 것이 아니라 휴리스틱 알고리즘을 사용합니다. - z80crew

8

나는이 질문에 대해 매우 늦다는 것을 알고 있으며,이 솔루션은 영어 중심의 편견과 통계 / 경험적 테스트의 부재로 인해 어떤 사람들에게 호소력을 발휘하지 못할 것이다. 그러나 특히 업로드 된 CSV 데이터를 처리하는 데 매우 효과적이다.

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

장점 :

  • BOM 감지 내장
  • 맞춤 설정 가능한 기본 / 대체 인코딩
  • UTF-8과 라틴 -1 스타일 파일 (기본적으로 미국과 서부 유럽 환경의 대부분)이 혼합 된 일부 이국적인 데이터 (예 : 프랑스어 이름)가 포함 된 서유럽 기반 파일의 경우 상당히 안정적입니다.

참고 : 나는이 수업을 쓴 사람이므로 분명히 소금 한 알씩 가져 가라. :)


7

메모장 + +이 기능을 즉시 사용할 수 있습니다. 또한 변경을 지원합니다.


7

다른 해결책을 찾고, 나는 그것을 발견했다.

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

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

4 바이트의 첫 번째 바이트와 아마도 XML charset 감지를 기반으로 기본적인 인코딩 감지가 필요했습니다. 그래서 인터넷에서 샘플 소스 코드를 가져 와서 약간 수정 된 버전을 추가했습니다.

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 바이트는 읽는 것으로 충분하지만 전체 파일을로드하고 있습니다.


5

누군가가 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();
        }
    }
}


  • 아주 좋은 해결책. 2 개 이상의 인코딩 (UTF-8 및 ASCI 1252)이 허용되어야하는 경우 허용 된 인코딩 루프에서 ReadAsString () 본문을 쉽게 래핑 할 수 있습니다. - ViRuSTriNiTy
  • 수 많은 예제를 시도한 후에 마침내 당신에게갔습니다. 나는 지금 행복한 곳에있다. 감사합니다 !!!!!!! - Sedrick

4

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

해당 사전 (해시)을 감안할 때 입력 텍스트를 가져 와서 다음을 수행하십시오.

  • BOM 문자 (UTF-16-BE의 경우 '\ xfe \ xff', UTF-16의 경우 '\ xff \ xfe', UTF-8의 경우 '\ xef \ xbb \ xbf')로 시작하면 그것을 제안대로 다루어 라.
  • 그렇지 않다면 큰 텍스트 샘플을 가져 와서 샘플의 모든 바이트 쌍을 가져 와서 사전에서 제안 된 가장 일반적인 인코딩을 선택하십시오.

UTF로 인코딩 된 텍스트도 샘플링 한 경우아니BOM으로 시작하면 두 번째 단계는 첫 번째 단계에서 미끄러 진 것을 처리합니다.

지금까지는 오류율이 줄어들어 샘플 데이터와 후속 입력 데이터가 다양한 언어의 자막으로 작동합니다.


3

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


  • 그것은 " 인코딩 "링크여기 .. 그리고 묘사는 우리가 Encoding을 제공해야한다고 말한다. - SurajS
  • @SurajS : 다른 과부하를 보라. - leppie
  • 원저자는 잠재적으로 BOM 마커가없는 파일의 인코딩을 검색하려고합니다. StreamReader는 서명 당 BOM 헤더에서 인코딩을 감지합니다. public StreamReader (스트림 스트림, bool detectEncodingFromByteOrderMarks) - ibondre

3

도구 "uchardet"은 각 문자 집합에 대한 문자 빈도 분포 모델을 사용하여이를 잘 수행합니다. 더 큰 파일과 더 많은 "전형적인"파일은 더 많은 확신을 가지고 있습니다 (분명히).

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

다른 시스템에서는 소스, 사용법 & docs here :https://github.com/BYVoid/uchardet


  • 자작곡을 통해 Mac에서 :brew install uchardet - Paul B

1

C 라이브러리에 링크 할 수 있으면 다음을 사용할 수 있습니다.libenca. 만나다http://cihar.com/software/enca/. man 페이지에서 :

Enca는 주어진 텍스트 파일을 읽지 않거나 표준 입력이 없으면 읽습니다.   해당 언어에 대한 지식을 사용합니다 (귀하가 지원해야 함).   파싱, 통계 분석, 추측 및 흑 마법의 혼합   인코딩을 결정합니다.

그것은 GPL v2입니다.


0

동일한 문제가 있었지만 자동으로 감지 할 수있는 좋은 해결책을 찾지 못했습니다. 지금 PsPad (www.pspad.com)를 사용하고 있습니다.) 잘 작동합니다.


0

기본적으로 휴리스틱 스 (heuristics)로 내려 가기 때문에 이전에받은 파일의 인코딩을 첫 번째 힌트와 동일한 소스에서 사용하는 것이 도움이 될 수 있습니다.

대부분의 사람들 (또는 응용 프로그램)은 매번 같은 순서로 매번 같은 순서로 물건을 처리하기 때문에 Bob이 .csv 파일을 만들어 Mary에게 보냈을 때 Windows-1252 또는 그의 기계가 무엇이던간에.

가능하다면 고객 교육을 조금도 해칠 수는 없습니다 :-)


0

나는 실제로 파일 인코딩을 탐지하는 프로그래밍 방식이 아닌 일반적인 것을 찾고 있었지만, 아직 찾지 못했습니다. 다른 인코딩을 사용하여 테스트 한 결과 내 텍스트는 UTF-7이었습니다.

그래서 내가 처음 일을하는 곳 : StreamReader 파일 = File.OpenText (fullfilename);

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

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

당신은 또한 이와 같은 StreamReader를 만들 수 있습니다. new StreamReader (fullfilename, true), 두 번째 매개 변수는 파일의 바이트 표시에서 인코딩을 검색해야하지만 내 경우에는 작동하지 않는다는 것을 의미합니다.


  • Yikes! 누가 UTF-7로 파일을 쓰고 있습니까 ??? - John Machin
  • @ 존 마틴 나는 그것이 드문 것에 동의하지만, 예를 들면 IMAP 프로토콜의 일부에서 그래도 그 위치에 있으면 추측 할 필요가 없습니다. - tripleee

0

AkelPad에서 파일 열기 (또는 왜곡 된 텍스트 복사 / 붙여 넣기), 편집 -> 선택 -> 레코딩 ... -> "자동 검색"을 선택하십시오.


0

ITmeze 포스트의 addon으로,이 함수를 사용하여 Mozilla Universal Charset Detector의 C #포트 출력을 변환했습니다.

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

MSDN


0

감사 @에릭 애런 스티언급uchardet.



한편 (같은?) 도구가 리눅스에 존재합니다 :chardet.

또는 cygwin에서 다음과 같이 사용할 수 있습니다 :chardetect.

만나다:chardet man 페이지 :https://www.commandlinux.com/man-page/man1/chardetect.1.html

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


0

이 질문 이후 10Y (!)가 지나갔고 여전히 MS의 좋은 GPL 솔루션에 대한 언급이 없습니다.국제어 2API.

이미 언급 된 대부분의 라이브러리는 모질라의 UDE를 기반으로하고 있습니다. 브라우저가 이미 비슷한 문제를 다루고있는 것은 합리적입니다. 나는 크롬의 해결책이 무엇인지 모르지만, IE 5.0 MS가 그것들을 발표 한 이래로 그것은 :

  1. GPL과 같은 라이선싱 문제가 없으며,
  2. 아마 영원히 뒷받침되고 유지 될 것이고,
  3. 풍부한 출력을 제공합니다 - 모든 유효한 인코딩 / 코드 페이지 후보와 함께 신뢰 점수,
  4. 놀랍게도 사용하기 쉽습니다 (단일 함수 호출).

네이티브 COM 호출이지만여기에 아주 좋은 작품이있다.Carsten Zeumer가 .net 사용을위한 interop mess을 처리합니다. 주변에 다른 사람들이 있지만,이 도서관은 가치가있는 주목을받지 못합니다.


-2

파일을 읽을 때이 코드를 사용하여 유니 코드 및 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()

연결된 질문


관련된 질문

최근 질문