c# string - Comment convertir un octet UTF-8[]en chaîne?




to byte[] (11)

J'ai un tableau d' byte[] qui est chargé à partir d'un fichier que je connais connu contient UTF-8 . Dans un code de débogage, j'ai besoin de le convertir en une chaîne. Y a-t-il un seul paquebot qui va le faire?

Sous les couvertures, il ne devrait s'agir que d'une allocation et d'un mémo , donc même si ce n'est pas le cas, cela devrait être possible.


Answers

Un doublure Linq pour convertir un tableau d'octets byteArrFilename lu à partir d'un fichier en une chaîne terminée par un zéro de style C ascii pur serait ceci: Pratique pour lire des choses comme des tables d'index de fichiers dans les anciens formats d'archives.

String filename = new String(byteArrFilename.TakeWhile(x => x != 0)
                              .Select(x => x < 128 ? (Char)x : '?').ToArray());

J'utilise '?' comme char par défaut pour tout ce qui n'est pas pur ascii ici, mais cela peut être changé, bien sûr. Si vous voulez être sûr de pouvoir le détecter, utilisez '\0' place, puisque le TakeWhile au début s'assure qu'une chaîne construite de cette manière ne peut pas contenir '\0' valeurs '\0' de la source d'entrée.


Convertir un byte[] en une string semble simple, mais tout type d'encodage est susceptible de gâcher la chaîne de sortie. Cette petite fonction fonctionne simplement sans résultats inattendus:

private string ToString(byte[] bytes)
{
    string response = string.Empty;

    foreach (byte b in bytes)
        response += (Char)b;

    return response;
}

string result = System.Text.Encoding.UTF8.GetString(byteArray);

BitConverter classe BitConverter peut être utilisée pour convertir un byte[] en string .

var convertedString = BitConverter.ToString(byteAttay);

La documentation de la classe BitConverter peut être trouvée sur MSDN


Définition:

public static string ConvertByteToString(this byte[] source)
{
    return source != null ? System.Text.Encoding.UTF8.GetString(source) : null;
}

En utilisant:

string result = input.ConvertByteToString();

Une solution générale pour convertir un tableau d'octets en chaîne lorsque vous ne connaissez pas l'encodage:

static string BytesToStringConverted(byte[] bytes)
{
    using (var stream = new MemoryStream(bytes))
    {
        using (var streamReader = new StreamReader(stream))
        {
            return streamReader.ReadToEnd();
        }
    }
}

Il y a au moins quatre manières différentes de faire cette conversion.

  1. Encoding's GetString
    , mais vous ne pourrez pas récupérer les octets d'origine si ces octets ont des caractères non-ASCII.

  2. BitConverter.ToString
    La sortie est une chaîne délimitée par "-", mais il n'y a pas de méthode intégrée .NET pour convertir la chaîne en tableau d'octets.

  3. Convert.ToBase64String
    Vous pouvez facilement convertir la chaîne de sortie en tableau d'octets en utilisant Convert.FromBase64String .
    Remarque: La chaîne de sortie peut contenir '+', '/' et '='. Si vous souhaitez utiliser la chaîne dans une URL, vous devez l'encoder explicitement.

  4. HttpServerUtility.UrlTokenEncode
    Vous pouvez facilement convertir la chaîne de sortie en tableau de byte en utilisant HttpServerUtility.UrlTokenDecode . La chaîne de sortie est déjà compatible avec les URL! L'inconvénient est qu'il a besoin de l'assembly System.Web si votre projet n'est pas un projet web.

Un exemple complet:

byte[] bytes = { 130, 200, 234, 23 }; // A byte array contains non-ASCII (or non-readable) characters

string s1 = Encoding.UTF8.GetString(bytes); // ���
byte[] decBytes1 = Encoding.UTF8.GetBytes(s1);  // decBytes1.Length == 10 !!
// decBytes1 not same as bytes
// Using UTF-8 or other Encoding object will get similar results

string s2 = BitConverter.ToString(bytes);   // 82-C8-EA-17
String[] tempAry = s2.Split('-');
byte[] decBytes2 = new byte[tempAry.Length];
for (int i = 0; i < tempAry.Length; i++)
    decBytes2[i] = Convert.ToByte(tempAry[i], 16);
// decBytes2 same as bytes

string s3 = Convert.ToBase64String(bytes);  // gsjqFw==
byte[] decByte3 = Convert.FromBase64String(s3);
// decByte3 same as bytes

string s4 = HttpServerUtility.UrlTokenEncode(bytes);    // gsjqFw2
byte[] decBytes4 = HttpServerUtility.UrlTokenDecode(s4);
// decBytes4 same as bytes

Alternativement:

 var byteStr = Convert.ToBase64String(bytes);

Il y a aussi la classe UnicodeEncoding, assez simple d'utilisation:

ByteConverter = new UnicodeEncoding();
string stringDataForEncoding = "My Secret Data!";
byte[] dataEncoded = ByteConverter.GetBytes(stringDataForEncoding);

Console.WriteLine("Data after decoding: {0}", ByteConverter.GetString(dataEncoded));

Utilisation de (byte)b.ToString("x2") , Sorties b4b5dfe475e58b67

public static class Ext {

    public static string ToHexString(this byte[] hex)
    {
        if (hex == null) return null;
        if (hex.Length == 0) return string.Empty;

        var s = new StringBuilder();
        foreach (byte b in hex) {
            s.Append(b.ToString("x2"));
        }
        return s.ToString();
    }

    public static byte[] ToHexBytes(this string hex)
    {
        if (hex == null) return null;
        if (hex.Length == 0) return new byte[0];

        int l = hex.Length / 2;
        var b = new byte[l];
        for (int i = 0; i < l; ++i) {
            b[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);
        }
        return b;
    }

    public static bool EqualsTo(this byte[] bytes, byte[] bytesToCompare)
    {
        if (bytes == null && bytesToCompare == null) return true; // ?
        if (bytes == null || bytesToCompare == null) return false;
        if (object.ReferenceEquals(bytes, bytesToCompare)) return true;

        if (bytes.Length != bytesToCompare.Length) return false;

        for (int i = 0; i < bytes.Length; ++i) {
            if (bytes[i] != bytesToCompare[i]) return false;
        }
        return true;
    }

}

La meilleure réponse que j'ai jamais entendue à propos de l'utilisation des alias de type fournis en C # provient de Jeffrey Richter dans son livre CLR Via C # . Voici ses 3 raisons:

  • J'ai vu un certain nombre de développeurs confus ne sachant pas s'il fallait utiliser string ou String dans leur code. Parce qu'en C #, la chaîne (un mot-clé) correspond exactement à System.String (un type FCL), il n'y a pas de différence et les deux peuvent être utilisés.
  • En C #, long est mappé sur System.Int64 , mais dans un langage de programmation différent, long peut être mappé sur un Int16 ou Int32 . En fait, C ++ / CLI traite en fait long comme un Int32 . Quelqu'un qui lit le code source dans une langue peut facilement mal interpréter l'intention du code s'il est habitué à programmer dans un langage de programmation différent. En fait, la plupart des langues ne traitent même pas le mot-clé et ne compilent pas le code qui l'utilise.
  • Le FCL a de nombreuses méthodes qui ont des noms de types dans leurs noms de méthodes. Par exemple, le type BinaryReader propose des méthodes telles que ReadBoolean , ReadInt32 , ReadSingle , etc., et le type System.Convert propose des méthodes telles que ToBoolean , ToInt32 , ToSingle , etc. Bien qu'il soit légal d'écrire le code suivant, la ligne avec float ne me semble pas très naturelle, et il n'est pas évident que la ligne soit correcte:
BinaryReader br = new BinaryReader(...);
float val  = br.ReadSingle(); // OK, but feels unnatural
Single val = br.ReadSingle(); // OK and feels good

Donc là vous l'avez. Je pense que ce sont tous de très bons points. Cependant, je ne me trouve pas en train d'utiliser les conseils de Jeffrey dans mon propre code. Peut-être que je suis trop coincé dans mon monde C # mais je finis par essayer de faire ressembler mon code au code-cadre.





c# .net arrays string type-conversion