IT

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

lottoking 2020. 3. 19. 08:27
반응형

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


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

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

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


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

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

해결책:

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

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

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

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

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

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

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


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


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.");
        }
    }
}    

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

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

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

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


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

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

장점 :

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

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


메모장 ++ 에는이 기능이 기본적으로 제공됩니다. 또한 변경을 지원합니다.


다른 솔루션을 찾고 있는데

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


누군가가 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 바이트 슬라이딩 창으로 분류되어 인코딩 목록 값을 제공하는 바이트 쌍을 기준으로 사전 (해시)에 저장됩니다.

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

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

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

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


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


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

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

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


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

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

GPL v2입니다.


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


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

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

가능한 한 약간의 고객 교육은 다음 중 어느 것도 해치지 않습니다 :-)


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

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

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

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

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


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


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

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

MSDN


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

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

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

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


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

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

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

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

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

참고 URL : https://stackoverflow.com/questions/90838/how-can-i-detect-the-encoding-codepage-of-a-text-file

반응형