51 votes

Convertir un int[] en byte[] en C#

Je sais comment le faire de la manière la plus longue : en créant un tableau d'octets de la taille nécessaire et en utilisant un for-loop pour transférer chaque élément du tableau d'int.

Je me demandais s'il n'y avait pas un moyen plus rapide, car il semble que la méthode ci-dessus s'interrompe si le fichier de données de l'utilisateur est endommagé. int était plus grand qu'un sbyte .

111voto

Daniel Hilgarth Points 90722

Si vous voulez une copie bit à bit, c'est-à-dire obtenir 4 octets d'un int, alors utilisez Buffer.BlockCopy :

byte[] result = new byte[intArray.Length * sizeof(int)];
Buffer.BlockCopy(intArray, 0, result, 0, result.Length);

N'utilisez pas Array.Copy car il essaiera de convertir et pas seulement de copier. Voir les remarques sur la page MSDN pour plus d'informations.

8voto

heltonbiker Points 4725

En plus de la réponse acceptée (que j'utilise maintenant), une alternative pour les amoureux de Linq serait :

byte[] bytes = ints.SelectMany(BitConverter.GetBytes).ToArray(); 

Je suppose, cependant, que ce serait plus lent...

5voto

Un fil un peu ancien, c'est 2022 maintenant
J'avais un tas de short qui traînent (désolé, pas de int s ;-) ) et j'ai pensé que ce serait cool de les avoir sous forme de tableau d'octets à la place. Après avoir lu toutes les différentes façons d'aborder la question, j'étais très confus et j'ai commencé à faire des tests comparatifs avec mes logiciels préférés.
(Le code devrait être facile à appliquer à tout type de base).
Il utilise BenchmarkDotNet pour effectuer les tests et les analyses statistiques.

using System;
using System.Linq;
using System.Runtime.InteropServices;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;

namespace ArrayCastingBenchmark;

public class Benchy {
    private const int number_of_shorts = 100000;
    private readonly short[] shorts;

    public Benchy() {
        Random r = new(43);
        shorts = new short[number_of_shorts];
        for (int i = 0; i < number_of_shorts; i++)
            shorts[i] = (short) r.Next(short.MaxValue);
    }

    [Benchmark]
    public ReadOnlySpan<byte> SPANSTYLE() {
        ReadOnlySpan<short> shortSpan = new ReadOnlySpan<short>(shorts);
        return MemoryMarshal.Cast<short, byte>(shortSpan);
    }

    [Benchmark]
    public byte[] BLOCKCOPY() {
        byte[] bytes = new byte[shorts.Length * sizeof(short)];
        Buffer.BlockCopy(shorts, 0, bytes, 0, bytes.Length);
        return bytes;
    }

    [Benchmark]
    public byte[] LINQY() {
        return shorts.Select(i => (byte) i).ToArray();
    }

    [Benchmark]
    public byte[] BITCONVERTER() {
        byte[] bytes = shorts.SelectMany(BitConverter.GetBytes).ToArray();
        return bytes;
    }

    //[Benchmark]
    //public void BINARYWRITER() {
    //    var fhandle = File.OpenHandle("_shorts_binarywriter.bin", FileMode.Create, FileAccess.Write);
    //    var binaryWriter = new BinaryWriter(new FileStream(fhandle, FileAccess.Write));
    //    foreach (var shorty in shorts)
    //        binaryWriter.Write(shorty);
    //    binaryWriter.Flush();
    //    binaryWriter.Close();
    //    fhandle.Close();
    //}
}

internal class Program {
    static void Main(string[] args) {
        var summary = BenchmarkRunner.Run<Benchy>();
    }
}

J'ai laissé le dernier, parce que si tu ajoutes juste un File.WriteAllBytes à la fin de toutes les méthodes et les faire produire des résultats, soudainement BLOCKCOPY est un peu plus rapide que SPANSTYLE sur ma machine. Si quelqu'un d'autre est confronté à ce problème ou a une idée de la façon dont cela peut se produire, veuillez me le dire.

EDIT : Désolé, j'ai oublié d'inclure les résultats réels (attention : sur ma machine) car il fonctionne pendant un certain temps avec les paramètres standard et tout le réchauffement.

 |       Method |              Mean |           Error |          StdDev |
 |------------- |------------------:|----------------:|----------------:|
 |    SPANSTYLE |         0.4592 ns |       0.0333 ns |       0.0666 ns |
 |    BLOCKCOPY |    15,384.8031 ns |     304.6014 ns |     775.3079 ns |
 |        LINQY |   175,187.7816 ns |   1,119.2713 ns |   1,046.9671 ns |
 | BITCONVERTER | 9,053,750.0355 ns | 330,414.7870 ns | 910,058.2814 ns |

-2voto

Charlie Somerville Points 5856
int[] ints = { 1, 2, 3, 4, 5, 6 };
byte[] bytes = ints.Select(x => (byte)x).ToArray();

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X