سؤال

أنا أعمل على المنفذ التسلسلي، وأرسل وأستقبل البيانات إلى بعض الأجهزة ببيانات 8 بت.أرغب في تخزينها كسلسلة لتسهيل المقارنة، ويتم تخزين البيانات المحددة مسبقًا كسلسلة أو تنسيق سداسي عشري في ملف XML.لقد اكتشفت أنه فقط عند استخدام Encoding.Default وهو تشفير ANSI، يتم تحويل بيانات 8 بت بشكل صحيح ويمكن عكسها بسهولة.سيعمل ترميز ASCII فقط مع البيانات ذات 7 بت، ولا يعمل UTF8 أو UTF7 جيدًا أيضًا، نظرًا لأنني أستخدم بعض الأحرف من 1-255.سيكون Encoding.Default أمرًا جيدًا، لكنني قرأت على MSDN أنه يعتمد على إعداد صفحة الترميز اللغوي لنظام التشغيل، مما يعني أنه قد يتصرف بشكل مختلف عند تكوين صفحة الترميز اللغوي المختلفة.أستخدم GetBytes() وGetString على نطاق واسع باستخدام التشفير، ولكني أرغب في استخدام طريقة آمنة ومحمولة تعمل طوال الوقت في أي تكوين.أي فكرة أو اقتراح أفضل لهذا؟

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

المحلول

يعد Latin-1 والمعروف أيضًا باسم ISO-8859-1 والمعروف أيضًا باسم صفحة الرموز 28591 صفحة رموز مفيدة لهذا السيناريو، حيث يقوم بتعيين القيم في النطاق 128-255 دون تغيير.ما يلي قابلة للتبديل:

Encoding.GetEncoding(28591)
Encoding.GetEncoding("Latin1")
Encoding.GetEncoding("iso-8859-1")

يوضح التعليمة البرمجية التالية حقيقة أنه بالنسبة إلى Latin1، على عكس Encoding.Default، يتم تعيين كافة الأحرف الموجودة في النطاق من 0 إلى 255 دون تغيير:

static void Main(string[] args)
{

    Console.WriteLine("Test Default Encoding returned {0}", TestEncoding(Encoding.Default));
    Console.WriteLine("Test Latin1 Encoding returned {0}", TestEncoding(Encoding.GetEncoding("Latin1")));
    Console.ReadLine();
    return;
}

private static bool CompareBytes(char[] chars, byte[] bytes)
{
    bool result = true;
    if (chars.Length != bytes.Length)
    {
        Console.WriteLine("Length mismatch {0} bytes and {1} chars" + bytes.Length, chars.Length);
        return false;
    }
    for (int i = 0; i < chars.Length; i++)
    {
        int charValue = (int)chars[i];
        if (charValue != (int)bytes[i])
        {
            Console.WriteLine("Byte at index {0} value {1:X4} does not match char {2:X4}", i, (int) bytes[i], charValue);
            result = false;
        }
    }
    return result;
}
private static bool TestEncoding(Encoding encoding)
{
    byte[] inputBytes = new byte[256];
    for (int i = 0; i < 256; i++)
    {
        inputBytes[i] = (byte) i;
    }

    char[] outputChars = encoding.GetChars(inputBytes);
    Console.WriteLine("Comparing input bytes and output chars");
    if (!CompareBytes(outputChars, inputBytes)) return false;

    byte[] outputBytes = encoding.GetBytes(outputChars);
    Console.WriteLine("Comparing output bytes and output chars");
    if (!CompareBytes(outputChars, outputBytes)) return false;

    return true;
}

نصائح أخرى

لماذا لا تستخدم فقط مجموعة من البايتات بدلاً من ذلك؟لن تواجه أيًا من مشكلات الترميز التي من المحتمل أن تعاني منها مع أسلوب النص.

أعتقد أنه يجب عليك استخدام مصفوفة بايت بدلاً من ذلك.للمقارنة يمكنك استخدام بعض الطرق مثل هذا:

static bool CompareRange(byte[] a, byte[] b, int index, int count)
{
    bool res = true;
    for(int i = index; i < index + count; i++)
    {
        res &= a[i] == b[i];
    }
    return res;
}

استخدم صفحة الرموز العبرية لنظام التشغيل Windows-1255.انها 8 بت.
Encoding enc = Encoding.GetEncoding("windows-1255");

لقد أخطأت في فهمك عندما كتبت "1-255"، اعتقدت أنك تشير إلى الأحرف الموجودة في صفحة الرموز 1255.

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

byte[] toEncode; 
string encoded = System.Convert.ToBase64String(toEncode);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top