在c#中将int[]转换为byte[]

本文关键字:byte 转换 int 中将 | 更新日期: 2023-09-27 17:54:46

我知道如何做到这一点:通过创建必要大小的字节数组,并使用for循环从int数组中强制转换每个元素。

我想知道是否有更快的方法,因为如果int大于sbyte,上面的方法似乎会中断。

在c#中将int[]转换为byte[]

如果您想要按位复制,即从一个int中获得4个字节,则使用Buffer.BlockCopy:

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

不要使用Array.Copy,因为它会尝试转换而不仅仅是复制。有关更多信息,请参阅MSDN页面上的备注。

除了接受的答案(我现在正在使用),Linq爱好者可以选择的一行代码是:

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

我想,虽然,它会更慢…

有点老了,现在是2022年了…
我有一堆short s躺在周围(对不起,没有int s;-)),并认为将它们作为字节数组代替会很酷。在阅读了所有不同的方法之后,我感到非常困惑,并开始对我最喜欢的方法进行基准测试。
(代码应该易于应用于任何基类型。)
使用BenchmarkDotNet进行实际测试和统计分析。

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

我留下了最后一个,因为如果你只是在所有方法的末尾添加一个File.WriteAllBytes,并使它们实际产生一些输出,突然之间,BLOCKCOPY在我的机器上比SPANSTYLE快了一点。如果有人有这样的经历,或者有一个想法,这是如何发生的,请告诉我。

编辑:对不起,我忘了把实际结果包括在内(注意:在我的机器上),因为它在标准设置和所有预热下运行了很长一段时间。

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