سؤال

وأنا أقرأ الملفات في مختلف الأشكال واللغات وأنا حاليا باستخدام مكتبة ترميز الصغيرة لتأخذ محاولة للكشف عن ترميز الصحيح (<لأ href = "http://www.codeproject.com/KB/recipes/DetectEncoding .aspx اتصال "يختلط =" نوفولو noreferrer "> http://www.codeproject.com/KB/recipes/DetectEncoding.aspx ).

وهذا جيد جدا، لكنه لا يزال يفتقد بعض الأحيان. (ملفات متعددة اللغات)

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

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

وماذا سيكون أفضل وسيلة لتنفيذ شيء من هذا القبيل؟


وتحرير: يبدو أنني لم أعبر بوضوح عن نفسي بما فيه الكفاية. بواسطة "ركوب الدراجات من خلال ترميز"، وأنا لا أقصد "كيفية يتكرر خلال ترميزات؟"

ما قصدته هو "كيفية السماح للمستخدم محاولة ترميزات مختلفة في تسلسل دون إعادة تحميل الملف؟"

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

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

وعلى سبيل المثال، إذا كان هناك طريقة من شأنها أن قراءة سلسلة وإعادته باستخدام ترميز مختلف، شيء من هذا القبيل "تقديم (سلسلة، ترميز)".


وشكرا جزيلا لأجوبة!

هل كانت مفيدة؟

المحلول

وقراءة ملف كما بايت ثم استخدم أسلوب Encoding.GetString.

        byte[] data = System.IO.File.ReadAllBytes(path);

        Console.WriteLine(Encoding.UTF8.GetString(data));
        Console.WriteLine(Encoding.UTF7.GetString(data));
        Console.WriteLine(Encoding.ASCII.GetString(data));

وهكذا كان لديك لتحميل الملف مرة واحدة فقط. يمكنك استخدام كل الترميز على أساس بايت الأصلية للملف. يمكن للمستخدم اختيار واحدة صحيحة اوند يمكنك استخدام نتيجة Encoding.GetEncoding (...). GetString (بيانات) لمزيد من المعالجة.

نصائح أخرى

و(إزالة الجواب الأصلي التحديث التالي السؤال)

<اقتباس فقرة>   

وعلى سبيل المثال، إذا كان هناك طريقة   التي من شأنها أن قراءة سلسلة وإعادته   باستخدام ترميز مختلف، شيء   مثل "تقديم (سلسلة، ترميز)".

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

إذا كنت سعيدا لخطر عليه (لن أكون)، هل يمكن أن مجرد إعادة ترميز سلسلة المحلية مع الترميز الماضي:

// I DON'T RECOMMEND THIS!!!!
byte[] preamble = lastEncoding.GetPreamble(),
    content = lastEncoding.GetBytes(text);
byte[] raw = new byte[preamble.Length + content.Length];
Buffer.BlockCopy(preamble, 0, raw, 0, preamble.Length);
Buffer.BlockCopy(content, 0, raw, preamble.Length, content.Length);
text = nextEncoding.GetString(raw);

في الواقع، وأعتقد أن أفضل ما يمكن القيام به هو الحفاظ على byte[] الأصلي - نستمر بتقديم الأداءات المختلفة (عبر ترميزات مختلفة) حتى مثل واحد. شيء من هذا القبيل:

using System;
using System.IO;
using System.Text;
using System.Windows.Forms;
class MyForm : Form {
    [STAThread]
    static void Main() {
        Application.EnableVisualStyles();
        Application.Run(new MyForm());
    }
    ComboBox encodings;
    TextBox view;
    Button load, next;
    byte[] data = null;

    void ShowData() {
        if (data != null && encodings.SelectedIndex >= 0) {
            try {
                Encoding enc = Encoding.GetEncoding(
                    (string)encodings.SelectedValue);
                view.Text = enc.GetString(data);
            } catch (Exception ex) {
                view.Text = ex.ToString();
            }
        }
    }
    public MyForm() {
        load = new Button();
        load.Text = "Open...";
        load.Dock = DockStyle.Bottom;
        Controls.Add(load);

        next = new Button();
        next.Text = "Next...";
        next.Dock = DockStyle.Bottom;
        Controls.Add(next);

        view = new TextBox();
        view.ReadOnly = true;
        view.Dock = DockStyle.Fill;
        view.Multiline = true;
        Controls.Add(view);

        encodings = new ComboBox();
        encodings.Dock = DockStyle.Bottom;
        encodings.DropDownStyle = ComboBoxStyle.DropDown;
        encodings.DataSource = Encoding.GetEncodings();
        encodings.DisplayMember = "DisplayName";
        encodings.ValueMember = "Name";
        Controls.Add(encodings);

        next.Click += delegate { encodings.SelectedIndex++; };

        encodings.SelectedValueChanged += delegate { ShowData(); };

        load.Click += delegate {
            using (OpenFileDialog dlg = new OpenFileDialog()) {
                if (dlg.ShowDialog(this)==DialogResult.OK) {
                    data = File.ReadAllBytes(dlg.FileName);
                    Text = dlg.FileName;
                    ShowData();
                }
            }
        };
    }
}

هل يمكن أن تسمح للمستخدم إدخال بعض الكلمات (مع الأحرف "الخاصة") التي من المفترض أن تحدث في الملف؟

ويمكنك البحث عن ترميزات نفسك لمعرفة ما إذا كان هذه الكلمات موجودة.

وحذار من سيئة السمعة " المفكرة علة . انه سيكون لدغة لك مهما حاولت، على الرغم من ... يمكنك العثور على بعض <لأ href = "http://blogs.msdn.com/oldnewthing/archive/2007/04/17/2158334.aspx" يختلط = "نوفولو noreferrer "> مناقشات جيدة عن ترميزات والتحديات التي تواجهها على MSDN (وغيرها).

لديك للحفاظ على البيانات الأصلية كما صفيف بايت أو MemoryStream يمكنك ثم تترجم إلى الترميز الجديد، بمجرد بالفعل تحويل البيانات إلى سلسلة لا يمكنك العودة موثوق بها إلى التمثيل الأصلي.

وماذا عن شيء مثل هذا:

public string LoadFile(string path)
{
    stream = GetMemoryStream(path);     
    string output = TryEncoding(Encoding.UTF8);
}

public string TryEncoding(Encoding e)
{
    stream.Seek(0, SeekOrigin.Begin) 
    StreamReader reader = new StreamReader(stream, e);
    return reader.ReadToEnd();
}

private MemoryStream stream = null;

private MemorySteam GetMemoryStream(string path)
{
    byte[] buffer = System.IO.File.ReadAllBytes(path);
    return new MemoryStream(buffer);
}

استخدم LoadFile في المحاولة الأولى. ثم استخدم TryEncoding في وقت لاحق.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top