我知道如何用冗长的方式来处理这个问题:创建一个必要大小的字节数组,然后使用for循环将每个元素从int数组强制转换。
我想知道是否有更快的方法,因为上述方法似乎会在int大于sbyte时出错。
我知道如何用冗长的方式来处理这个问题:创建一个必要大小的字节数组,然后使用for循环将每个元素从int数组强制转换。
我想知道是否有更快的方法,因为上述方法似乎会在int大于sbyte时出错。
如果你想进行位拷贝,即从一个 int 类型中获取 4 个字节,则使用 Buffer.BlockCopy
:
byte[] result = new byte[intArray.Length * sizeof(int)];
Buffer.BlockCopy(intArray, 0, result, 0, result.Length);
不要使用 Array.Copy
,因为它会尝试转换而不仅仅是复制。请查看MSDN页面上的备注以获取更多信息。
int
或byte
的存在。result
的内存表示将与intArray
完全相同。 - Daniel Hilgarthint[] result = new int[byteArray.Length / sizeof(int)]; Buffer.BlockCopy(byteArray, 0, result, 0, result.Length);
这段代码创建了一个整型数组result
,它的长度是字节数组byteArray
长度除以一个整型所占用的字节数。然后使用Buffer.BlockCopy
方法将byteArray
中的数据复制到result
中,从位置0开始,复制长度为result.Length
。 - Daniel Hilgarthbyte[] result = new byte[Buffer.ByteLength((Array)valueTypeArray)];
翻译后文意不变,并更加通俗易懂。 - Zenimabyte[] bytes = ints.SelectMany(BitConverter.GetBytes).ToArray();
v=>
... yptes(v)
。 - Meirion Hughes这是一个有点老的线程,现在是2022年...
我有一堆short
(抱歉,没有int
;-)),想让它们成为一个字节数组。在阅读了所有不同方法后,我非常困惑,于是开始对我的一些最喜欢的方法进行基准测试。
(该代码应该易于用于任何基本类型。)
它使用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 |
MemoryMarshal.AsBytes
,也许比强制转换快一点。 - undefined
short
”不匹配。 - H H