web-dev-qa-db-fra.com

Conversion de chaîne en tableau d'octets en C #

Je suis assez nouveau en C #. Je convertis quelque chose de VB en C #. Avoir un problème avec la syntaxe de cette déclaration:

if ((searchResult.Properties["user"].Count > 0))
{
    profile.User = System.Text.Encoding.UTF8.GetString(searchResult.Properties["user"][0]);
}

Je vois alors les erreurs suivantes:

Argument 1: impossible de convertir d'objet en octet []

La meilleure méthode surchargée pour 'System.Text.Encoding.GetString (byte [])' contient des arguments non valides

J'ai essayé de corriger le code sur this post, mais toujours pas de succès

string User = Encoding.UTF8.GetString("user", 0);

Aucune suggestion?

436
nouptime

Si vous avez déjà un tableau d'octets, vous devez savoir quel type d'encodage a été utilisé pour le transformer en tableau d'octets.

Par exemple, si le tableau d'octets a été créé comme ceci:

byte[] bytes = Encoding.ASCII.GetBytes(someString);

Vous devrez le reconvertir en une chaîne comme celle-ci:

string someString = Encoding.ASCII.GetString(bytes);

Si vous pouvez trouver dans le code dont vous avez hérité, le codage utilisé pour créer le tableau d'octets, alors vous devriez être défini.

725
Timothy Randall

Tout d’abord, ajoutez l’espace de nom System.Text

using System.Text;

Alors utilisez ce code

string input = "some text"; 
byte[] array = Encoding.ASCII.GetBytes(input);

J'espère y remédier!

81
Shridhar

Vous pouvez aussi utiliser une méthode Extension pour ajouter une méthode au type string comme ci-dessous:

static class Helper
{
   public static byte[] ToByteArray(this string str)
   {
      return System.Text.Encoding.ASCII.GetBytes(str);
   }
}

Et utilisez-le comme ci-dessous:

string foo = "bla bla";
byte[] result = foo.ToByteArray();
33
combo_ci
static byte[] GetBytes(string str)
{
     byte[] bytes = new byte[str.Length * sizeof(char)];
     System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
     return bytes;
}

static string GetString(byte[] bytes)
{
     char[] chars = new char[bytes.Length / sizeof(char)];
     System.Buffer.BlockCopy(bytes, 0, chars, 0, bytes.Length);
     return new string(chars);
}
20
Eran Yogev
var result = System.Text.Encoding.Unicode.GetBytes(text);
14
Kuganrajh Rajendran

utilisez ceci 

byte[] myByte= System.Text.ASCIIEncoding.Default.GetBytes(myString);
10
alireza amini

L'approche suivante ne fonctionnera que si les caractères sont à 1 octet. (Unicode par défaut ne fonctionnera pas puisqu'il s'agit de 2 octets)

public static byte[] ToByteArray(string value)
{            
    char[] charArr = value.ToCharArray();
    byte[] bytes = new byte[charArr.Length];
    for (int i = 0; i < charArr.Length; i++)
    {
        byte current = Convert.ToByte(charArr[i]);
        bytes[i] = current;
    }

    return bytes;
}

Garder les choses simples

9
Mandar Sudame

Un raffinement du montage de JustinStolle (utilisation de BlockCopy par Eran Yogev).

La solution proposée est en effet plus rapide que d’utiliser Encoding . Le problème est que cela ne fonctionne pas pour encoder des tableaux d’octets de longueur inégale . Comme indiqué, il soulève une exception hors-limite . longueur par 1 laisse un octet de fin lors du décodage d'une chaîne.

Pour moi, le besoin est apparu lorsque je voulais encoder de DataTable à JSON. Je cherchais un moyen de coder des champs binaires en chaînes et de les décoder à partir de byte[].

J'ai donc créé deux classes - une qui englobe la solution ci-dessus (lors du codage à partir de chaînes, tout va bien, car les longueurs sont toujours égales) et une autre qui gère le codage byte[].

J'ai résolu le problème de longueur inégale en ajoutant un seul caractère qui indique si la longueur d'origine du tableau binaire était impair ('1') ou pair ('0').

Comme suit:

public static class StringEncoder
{
    static byte[] EncodeToBytes(string str)
    {
        byte[] bytes = new byte[str.Length * sizeof(char)];
        System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
        return bytes;
    }
    static string DecodeToString(byte[] bytes)
    {
        char[] chars = new char[bytes.Length / sizeof(char)];
        System.Buffer.BlockCopy(bytes, 0, chars, 0, bytes.Length);
        return new string(chars);
    }
}

public static class BytesEncoder
{
    public static string EncodeToString(byte[] bytes)
    {
        bool even = (bytes.Length % 2 == 0);
        char[] chars = new char[1 + bytes.Length / sizeof(char) + (even ? 0 : 1)];
        chars[0] = (even ? '0' : '1');
        System.Buffer.BlockCopy(bytes, 0, chars, 2, bytes.Length);

        return new string(chars);
    }
    public static byte[] DecodeToBytes(string str)
    {
        bool even = str[0] == '0';
        byte[] bytes = new byte[(str.Length - 1) * sizeof(char) + (even ? 0 : -1)];
        char[] chars = str.ToCharArray();
        System.Buffer.BlockCopy(chars, 2, bytes, 0, bytes.Length);

        return bytes;
    }
}
6
user4726577

Est-ce que quelqu'un voit une raison pour ne pas faire ça?

mystring.Select(Convert.ToByte).ToArray()
4
Lomithrani

Si le résultat de 'searchResult.Properties ["user"] [0] "est une chaîne:

if ( ( searchResult.Properties [ "user" ].Count > 0 ) ) {

   profile.User = System.Text.Encoding.UTF8.GetString ( searchResult.Properties [ "user" ] [ 0 ].ToCharArray ().Select ( character => ( byte ) character ).ToArray () );

}

Le point clé étant que la conversion d'une chaîne en octet [] peut être effectuée à l'aide de LINQ:

.ToCharArray ().Select ( character => ( byte ) character ).ToArray () )

Et l'inverse:

.Select ( character => ( char ) character ).ToArray () )
3
Janus

On a répondu à cette question suffisamment de fois, mais avec C # 7.2 et l'introduction du type Span, il existe un moyen plus rapide de le faire dans un code non sécurisé:

public static class StringSupport
{
    private static readonly int _charSize = sizeof(char);

    public static unsafe byte[] GetBytes(string str)
    {
        if (str == null) throw new ArgumentNullException(nameof(str));
        if (str.Length == 0) return new byte[0];

        fixed (char* p = str)
        {
            return new Span<byte>(p, str.Length * _charSize).ToArray();
        }
    }

    public static unsafe string GetString(byte[] bytes)
    {
        if (bytes == null) throw new ArgumentNullException(nameof(bytes));
        if (bytes.Length % _charSize != 0) throw new ArgumentException($"Invalid {nameof(bytes)} length");
        if (bytes.Length == 0) return string.Empty;

        fixed (byte* p = bytes)
        {
            return new string(new Span<char>(p, bytes.Length / _charSize));
        }
    }
}

Gardez à l'esprit que les octets représentent une chaîne codée UTF-16 (appelée "Unicode" en C #).

Certaines analyses rapides montrent que les méthodes ci-dessus sont environ 5 fois plus rapides que leurs implémentations Encoding.Unicode.GetBytes (...)/GetString (...) pour les chaînes de taille moyenne (30 à 50 caractères) et encore plus rapidement pour les chaînes plus volumineuses. Ces méthodes semblent également être plus rapides que l'utilisation de pointeurs avec Marshal.Copy (..) ou Buffer.MemoryCopy (...).

1
returnsvoid

Construire à partir de La réponse d'ALi , je recommanderais une méthode d'extension qui vous permet de transmettre éventuellement l'encodage que vous souhaitez utiliser:

using System.Text;
public static class StringExtensions
{
    /// <summary>
    /// Creates a byte array from the string, using the 
    /// System.Text.Encoding.Default encoding unless another is specified.
    /// </summary>
    public static byte[] ToByteArray(this string str, Encoding encoding = Encoding.Default)
    {
        return encoding.GetBytes(str);
    }
}

Et utilisez-le comme ci-dessous:

string foo = "bla bla";

// default encoding
byte[] default = foo.ToByteArray();

// custom encoding
byte[] unicode = foo.ToByteArray(Encoding.Unicode);
0
Dan Sinclair

Ce travail pour moi, après que je pourrais convertir mettre ma photo dans un champ bytea dans ma base de données.

using (MemoryStream s = new MemoryStream(DirEntry.Properties["thumbnailphoto"].Value as byte[]))
{
    return s.ToArray();
}
0
user10863293