سؤال

في التطبيق لدينا ، تتلقى ملفات نصية (.txt, .csv, إلخ.) من مصادر متنوعة.عند قراءة هذه الملفات في بعض الأحيان تحتوي على القمامة ، لأن الملفات حيث تم إنشاؤها في مختلف/غير معروف الشفرة.

هل هناك طريقة (تلقائيا) الكشف عن مخطط الشفرة من ملف نصي ؟

على detectEncodingFromByteOrderMarks, على StreamReader منشئ ، UTF8 وغيرها unicode ملحوظ الملفات, ولكن أنا أبحث عن وسيلة للكشف عن صفحات التعليمات البرمجية مثل ibm850, windows1252.


شكرا على إجاباتك ، هذا هو ما فعلته.

الملفات التي نتلقاها من المستخدمين ليس لديهم فكرة عن codepages.أجهزة الاستقبال أيضا المستخدمين النهائيين, الآن هذا هو ما يعرفونه عن codepages:Codepages موجودة ، المزعجة.

الحل:

  • فتح تلقى الملف في "المفكرة" ، أنظر مشوه جزء من النص.إذا كان شخص ما يدعى فرانسوا أو شيء من هذا ، مع الذكاء البشري يمكنك تخمين ذلك.
  • لقد خلق التطبيق الصغيرة التي يمكن للمستخدم استخدام لفتح الملف ثم أدخل النص الذي يعلم المستخدم وسوف تظهر في الملف الصحيح عند الشفرة المستخدمة.
  • حلقة من خلال كل codepages ، وعرض تلك التي تعطي الحل مع المستخدم النصية.
  • إذا كان أكثر واحد الشفرة للملوثات العضوية الثابتة ، يطلب من المستخدم تحديد أكثر من نص.
هل كانت مفيدة؟

المحلول

لا يمكن الكشف عن مخطط الشفرة, تحتاج إلى أن يكون قال ذلك.يمكنك تحليل بايت أعتقد ذلك, ولكن هذا يمكن أن تعطي بعض غريبة (في بعض الأحيان مسلية) النتائج.أنا لا يمكن العثور عليه الآن, ولكن أنا متأكد من المفكرة يمكن أن تنخدع في عرض نص باللغة الإنجليزية في الصينية.

على أي حال, هذا هو ما تحتاج إلى قراءة:الحد الأدنى المطلق كل مطور برامج على الاطلاق, إيجابي يجب أن تعرف عن Unicode و مجموعات الأحرف (لا أعذار!).

على وجه التحديد جويل يقول:

الحقيقة الأكثر أهمية حول ترميزات

إذا كنت قد نسيت تماما كل شيء أنا فقط أوضح يرجى تذكر واحدة في غاية الأهمية الواقع.فإنه لا معنى أن يكون سلسلة من دون معرفة ما ترميز يستخدم.يمكنك لم يعد رأسك في الرمال وندعي أن "عادي" نص ASCII.لا يوجد شيء مثل النص العادي.

إذا كان لديك سلسلة في الذاكرة في ملف أو في رسالة بريد إلكتروني ، عليك أن تعرف ماذا الترميز هو في أو لا يمكن تفسير ذلك أو عرضه على المستخدمين بشكل صحيح.

نصائح أخرى

إذا كنت تبحث عن الكشف عن غير UTF ترميزات (أيلا BOM) أنت في الأساس وصولا إلى الاستدلال الإحصائي في تحليل النص.قد ترغب في إلقاء نظرة على موزيلا ورقة العالمي charset الكشف (نفس الرابط ، مع تحسين التنسيق عبر Wayback Machine).

هل حاولت C# ميناء موزيلا العالمية Charset كاشف

على سبيل المثال من 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.");
        }
    }
}    

لا يمكن الكشف عن مخطط الشفرة

هذا هو واضح كاذبة.كل متصفح ويب لديها بعض نوع من العالمية charset للكشف عن التعامل مع الصفحات التي تملك أي إشارة من أي نوع من الترميز.فايرفوكس لديه واحد.يمكنك تحميل الكود ونرى كيف يفعل ذلك.ترى بعض الوثائق هنا.وهي في الأساس مجريات الأمور ، ولكن واحد أن يعمل بشكل جيد حقا.

بالنظر إلى كمية معقولة من النص بل من الممكن الكشف عن اللغة.

هنا واحد آخر أنا فقط وجدت باستخدام جوجل:

أنا أعلم أنه في وقت متأخر جدا عن هذا السؤال و هذا الحل لن يروق للبعض (بسبب اللغة الإنجليزية التي تركز على التحيز و عدم الإحصائية/الاختبارات التجريبية), لكنه يعمل بشكل جيد جدا بالنسبة لي ، وخاصة بالنسبة المعالجة تحميل البيانات CSV:

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

المزايا:

  • بوم الكشف المدمج في
  • افتراضي/تراجع الترميز القابلة للتخصيص
  • موثوق بها جدا (من خلال تجربتي) الغربية-الأوروبية المستندة إلى الملفات التي تحتوي على بعض الغريبة البيانات (على سبيل المثال أسماء الفرنسية) مع خليط من UTF-8 و اللاتينية-1-أسلوب الملفات - في الأساس الأكبر من الولايات المتحدة و أوروبا الغربية البيئات.

ملاحظة:أنا من كتب هذه الفئة ، حيث من الواضح أن تأخذ ذلك مع حبة الملح!:)

Notepad++ هذه الميزة الخروج من مربع.وهو يدعم أيضا تغيير ذلك.

تبحث عن حل مختلف ، وجدت أن

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

هذا الحل هو نوع الثقيلة.

أنا في حاجة إلى بعض الأساسية ترميز الكشف على أساس 4 أول بايت وربما xml charset الكشف - حتى لقد أخذت بعض نموذج التعليمات البرمجية المصدر من الإنترنت و إضافة نسخة معدلة قليلا من

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

كتب جافا.

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

لقد فعلت شيئا من هذا القبيل في بيثون.في الأساس تحتاج إلى الكثير من بيانات عينة من مختلف ترميزات ، والتي يتم تفصيلها من قبل انزلاق اثنين بايت نافذة وتخزينها في القاموس (التجزئة) ، مقفول على بايت-أزواج توفير القيم قوائم ترميزات.

بالنظر إلى أن القاموس (التجزئة) ، إدخال النص:

  • إذا كان يبدأ مع أي بوم حرف ('\xfe\xff' ل UTF-16- ، '\xff\xfe' ل UTF-16-LE, '\xef\xbb\xbf' ل UTF-8 الخ) ، يمكنني التعامل معها كما اقترح
  • إن لم يكن, ثم تأخذ قطعة كبيرة بما يكفي عينة من النص ، اتخاذ جميع بايت-أزواج من العينة واختيار الترميز الذي هو الأقل شيوعا اقترح من القاموس.

إذا كنت قد أيضا عينات 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) لذلك؛) يعمل بشكل جيد

لأنه في الأساس يأتي إلى أسفل إلى الاستدلال ، قد تساعد على استخدام ترميز وردت سابقا الملفات من المصدر نفسه باعتباره أول تلميح.

معظم الناس (أو التطبيقات) هل الاشياء في حد كبير بنفس الترتيب في كل مرة, في كثير من الأحيان على نفس الجهاز, لذلك من المحتمل جدا أنه عندما بوب يخلق .ملف csv ويرسله إلى مريم انها سوف تكون دائما استخدام Windows-1252 أو ما شابه الجهاز الافتراضي.

حيث من الممكن قليلا من تدريب العملاء لا يضر إما :-)

في الحقيقة كنت أبحث عن عام ، وليس البرمجة طريقة الكشف عن ترميز الملف ولكن لم أجد ذلك حتى الآن.ما لم تجد طريق اختبار مع مختلف ترميزات كان أن النص هو UTF-7.

أين أنا أول من كان يفعله:StreamReader ملف = File.OpenText(fullfilename);

اضطررت إلى تغيير إلى:StreamReader file = new StreamReader(fullfilename النظام.النص.ترميز.UTF7);

OpenText يفترض انها UTF-8.

يمكنك أيضا إنشاء StreamReader مثل هذا new StreamReader(fullfilename, true), المعلمة الثانية وهذا يعني أنه ينبغي محاولة الكشف عن الترميز من byteordermark الملف ، ولكن ذلك لم ينجح في حالتي.

فتح ملف في AkelPad(أو مجرد نسخ/لصق نص مشوه) ، انتقل إلى تحرير> مختارة -> رمز...-> حدد "تلقائي".

كما الملحق ITmeze آخر ، لقد تستخدم هذه الدالة لتحويل الناتج من C# ميناء موزيلا العالمية Charset كاشف

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

MSDN

شكرا @إريك Aronesty بالنسبة بالذكر uchardet.

وفي الوقت نفسه (ذاته؟) أداة موجودة في لينكس: chardet.
أو على cygwin قد ترغب في استخدام: chardetect.

انظر: chardet رجل الصفحة: https://www.commandlinux.com/man-page/man1/chardetect.1.html

هذا سوف heuristically الكشف عن (تخمين) ترميز الأحرف لكل ملف معين و سوف التقرير اسم مستوى الثقة لكل ملف الكشف عن ترميز الأحرف.

10Y (!) وقد مرت هذه وطلب ما زلت لا أرى أي ذكر MS جيد ، غير GPL رائد الحل: IMultiLanguage2 API.

معظم المكتبات التي سبق ذكرها هي على أساس موزيلا أودي - ويبدو من المعقول أن المتصفحات بالفعل معالجة مشاكل مماثلة.أنا لا أعرف ما هو كروم هو الحل, ولكن منذ IE 5.0 MS وقد صدر ملكهم ، و هو:

  1. مجانا من جي بي ال-و--مثل الترخيص القضايا ،
  2. المدعومة و الحفاظ على الأرجح إلى الأبد ،
  3. يعطي الغني إخراج كل صالح المرشحين الترميز/codepages جنبا إلى جنب مع الثقة الدرجات ،
  4. المدهش أن من السهل استخدام (وهو واحد من استدعاء دالة).

هو من مواليد استدعاء COM, ولكن هنا بعض عمل رائع جدا قبل كارستن Zeumer أن يعالج إمكانية التشغيل المتداخل فوضى .صافي الاستخدام.هناك بعض الآخرين حولها ، ولكن إلى حد كبير هذه المكتبة لا تحصل على ما تستحقه من اهتمام.

أنا استخدم هذا الرمز إلى الكشف عن Unicode ويندوز ansi الافتراضي الشفرة عند قراءة الملف.أخرى codings التحقق من المحتوى ضروري يدويا أو عن طريق البرمجة.هذا دي يمكن استخدامها لحفظ النص مع نفس الترميز كما عند فتحها.(يمكنني استخدام 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()
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top