web-dev-qa-db-fra.com

Convertir une représentation sous forme de chaîne binaire en un tableau d'octets

Comment convertir une chaîne telle que "0111010001100101011111111111110100" en un tableau d'octets utilisé par la suite File.WriteAllBytes de sorte que la chaîne binaire exacte soit le binaire du fichier Dans ce cas, il s'agirait du texte "test".

27
ParoX

Si vous n'avez pas ce fétiche LINQ, si courant ces derniers temps, vous pouvez essayer de la manière habituelle.

string input ....
int numOfBytes = input.Length / 8;
byte[] bytes = new byte[numOfBytes];
for(int i = 0; i < numOfBytes; ++i)
{
    bytes[i] = Convert.ToByte(input.Substring(8 * i, 8), 2);
}
File.WriteAllBytes(fileName, bytes);

LINQ est génial mais il doit y avoir des limites.

34
Maciej Hehl

Vous pouvez commencer par diviser la chaîne en une séquence de chaînes de 8 caractères, puis convertir ces chaînes en octets et éventuellement écrire les octets dans un fichier.

string input = "01110100011001010111001101110100";
var bytesAsStrings =
    input.Select((c, i) => new { Char = c, Index = i })
         .GroupBy(x => x.Index / 8)
         .Select(g => new string(g.Select(x => x.Char).ToArray()));
byte[] bytes = bytesAsStrings.Select(s => Convert.ToByte(s, 2)).ToArray();
File.WriteAllBytes(fileName, bytes);

EDIT: voici une autre façon de scinder la chaîne en morceaux de 8 caractères, peut-être un peu plus simples:

int nBytes = (int)Math.Ceiling(input.Length / 8m);
var bytesAsStrings =
    Enumerable.Range(0, nBytes)
              .Select(i => input.Substring(8 * i, Math.Min(8, input.Length - 8 * i)));

Si vous savez que la longueur de la chaîne est un multiple de 8, vous pouvez la rendre encore plus simple:

int nBytes = input.Length / 8;
var bytesAsStrings =
    Enumerable.Range(0, nBytes)
              .Select(i => input.Substring(8 * i, 8));
10
Thomas Levesque

Un peu tard, mais voici mes 2 centimes:

var binaryStr = "01110100011001010111001101110100";

var byteArray = Enumerable.Range(0, int.MaxValue/8)
                          .Select(i => i*8)
                          .TakeWhile(i => i < binaryStr.Length)
                          .Select(i => binaryStr.Substring(i, 8))
                          .Select(s => Convert.ToByte(s, 2))
                          .ToArray();
File.WriteAllBytes("C:\temp\test.txt", byteArray);
4
theburningmonk

En réalité, la réponse de @Maciej n’est pas correcte. Comme @ Phate01 a remarqué que numOfBytes n'est correct que pour la longueur d'entrée qui est une puissance de 8. La deuxième chose est que le tableau d'octets doit être rempli de n à 0 index et non l'inverse. Voici l'exemple de code:

var bits = "000011110000001000";
var numOfBytes = (int)Math.Ceiling(bits.Length / 8m);
var bytes = new byte[numOfBytes];
var chunkSize = 8;

for (int i = 1; i <= numOfBytes; i++)
{
    var startIndex = bits.Length - 8 * i;
    if (startIndex < 0)
    {
        chunkSize = 8 + startIndex;
        startIndex = 0;
    }
    bytes[numOfBytes - i] = Convert.ToByte(bits.Substring(startIndex, chunkSize), 2);
}

Cela peut être amélioré pour se débarrasser de l'état if, mais sous cette forme, il est plus compréhensible.

2
kriskot

Les autres réponses sont couvertes, mais juste pour le plaisir, j’ai écrit le contraire. Passant de la chaîne à la représentation binaire ascii:

    private static string StringToAsciiBin(string s)
    {
        string output = "";
        foreach (char c in s.ToCharArray())
        {
            for (int i = 128; i >= 1; i /=2)
            {
                if (((int)c & i) > 0)
                {
                    output += "1";
                }
                else
                {
                    output += "0";
                }
            }
        }
        return output;
    }
1
jwsample