c# - How to take array segments out of a byte array after every X step?
问题描述
I got a big byte array (around 50kb) and i need to extract numeric values from it. Every three bytes are representing one value. What i tried is to work with LINQs skip & take but it's really slow regarding the large size of the array.
This is my very slow routine:
List<int> ints = new List<int>();
for (int i = 0; i <= fullFile.Count(); i+=3)
{
ints.Add(BitConverter.ToInt16(fullFile.Skip(i).Take(i + 3).ToArray(), 0));
}
I think i got a wrong approach to this.
解决方案
你的代码
首先,ToInt16
只使用两个字节。所以你的第三个字节将被丢弃。
您不能使用ToInt32
它,因为它会包含一个额外的字节。
让我们回顾一下:
fullFile.Skip(i).Take(i + 3).ToArray()
..仔细看看Take(i + 3)
。它说你想复制一个越来越大的缓冲区。例如,when i
is on index 32000 您将 32003 字节复制到新缓冲区中。
这就是代码很慢的原因。
代码也很慢,因为您分配了大量需要进行垃圾收集的字节缓冲区。65535 个大小不断增长的额外缓冲区,必须进行垃圾收集。
你也可以这样做:
List<int> ints = new List<int>();
var workBuffer = new byte[4];
for (int i = 0; i <= fullFile.Length; i += 3)
{
// Copy the three bytes into the beginning of the temp buffer
Buffer.BlockCopy(fullFile, i, workBuffer, 0, 3);
// Now we can use ToInt32 as the last byte always is zero
var value = BitConverter.ToInt32(workBuffer, 0);
ints.Add(value);
}
很容易理解,但不是最快的代码。
更好的解决方案
所以最有效的方法是自己进行转换(位移)。
就像是:
List<int> ints = new List<int>();
for (int i = 0; i <= fullFile.Length; i += 3)
{
// This code assume little endianess
var value = (fullFile[i + 2] << 16)
+ (fullFile[i + 1] << 8)
+ fullFile[i];
ints.Add(value);
}
这段代码不分配任何额外的东西(除了整数),而且应该很快。
您可以在 MSDN中阅读有关Shift 运算符的更多信息。关于字节序
推荐阅读
- java - 如何将图像裁剪为设定的字节数?
- bash - “docker run”在退出 bash shell 脚本后死机
- html - 在python代码中使用变量而不是html字体属性的值
- objective-c - (Mac) 模拟键盘快捷键 - 箭头键不起作用
- java - 如何解析此 JSONObject 以从 twitter 搜索 API 获取数组内的值以获取每条推文(名称、正文)?
- javascript - 如果数组之和为0,如何实现逻辑,从JavaScript中的数组中删除?
- three.js - three.js 旋转平面,因此它们始终垂直于相机轴而不改变 z 旋转
- excel - .选定的命令形式 Excel
- java - 我可以用哪种方式用Java中的List写下for循环?
- reactjs - ReactJS:停止自动提交输入