Domanda

Sto lavorando su una porta seriale, trasmettendo e ricevendo dati su alcuni hardware a 8 bit. Vorrei memorizzarlo come stringa per facilitare il confronto, e i dati preimpostati vengono memorizzati come formato stringa o esadecimale in file XML. Ho scoperto che solo quando si utilizza Encoding.Default che è la codifica ANSI, i dati a 8 bit vengono convertiti correttamente e facilmente reversibili. La codifica ASCII funziona solo per i dati a 7 bit e UTF8 o UTF7 non funziona bene, dato che sto usando un carattere compreso tra 1-255. Encoding.Default andrebbe bene, ma ho letto su MSDN che dipende dall'impostazione della tabella codici del sistema operativo, il che significa che potrebbe comportarsi in modo diverso su una diversa tabella codici configurata. Uso GetBytes () e GetString utilizzando ampiamente la codifica, ma vorrei un metodo sicuro e portatile che funzioni sempre con qualsiasi configurazione. Qualche idea o suggerimento migliore per questo?

È stato utile?

Soluzione

Latin-1 aka ISO-8859-1 aka codepage 28591 è una tabella codici utile per questo scenario, poiché mappa i valori nell'intervallo 128-255 invariati. Sono intercambiabili:

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

Il codice seguente mostra il fatto che per Latin1, diversamente da Encoding.Default, tutti i caratteri nell'intervallo 0-255 sono mappati invariati:

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

Altri suggerimenti

Perché non usare semplicemente una matrice di byte? Non avrebbe nessuno dei problemi di codifica che potresti soffrire con l'approccio testuale.

Penso che dovresti usare invece un array di byte. Per un confronto puoi usare un metodo come questo:

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

Utilizza la tabella codici ebraica per Windows-1255. È a 8 bit.
Encoding enc = Encoding.GetEncoding (" windows-1255 ");

Ti ho sbagliato a scriverti quando hai scritto "1-255", pensandoti dove ti riferivi ai personaggi nella tabella codici 1255.

È possibile utilizzare la codifica base64 per convertire da byte a stringa e viceversa. Nessun problema con le pagine di codice o caratteri strani in quel modo, e sarà più efficiente in termini di spazio di hex.

byte[] toEncode; 
string encoded = System.Convert.ToBase64String(toEncode);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top