c# - C#中的自定义4位数据类型
问题描述
我想创建一个 4 位(半字节)的自定义数据类型。
一种选择是 -
byte source = 0xAD;
var hiNybble = (source & 0xF0) >> 4; //Left hand nybble = A
var loNyblle = (source & 0x0F); //Right hand nybble = D
但是,我想将每 4 位存储在一个数组中。
例如,一个 2 字节的数组,
00001111 01010000
将作为 4 个半字节存储在自定义数据类型数组中 -
0000
1111
0101
0000
本质上我想对 4 位类型进行操作。
有什么办法可以将字节数组转换为半字节数组?
欣赏一个例子。
谢谢。
解决方案
您可以通过读取然后转换来封装返回 4 位样本的流(从没有编译器的手机编写来测试。预期拼写错误和一个错误):
public static int ReadNibbles(this Stream s, byte[] data, int offset, int count)
{
if (s == null)
{
throw new ArgumentNullException(nameof(s));
}
if (data == null)
{
throw new ArgumentNullException(nameof(data));
}
if (data.Length < offset + length)
{
throw new ArgumentOutOfRangeException(nameof(length));
}
var readBytes = s.Read(data, offset, length / 2);
for (int n = readBytes * 2 - 1, k = readBytes - 1; k >= 0; k--)
{
data[offset + n--] = data[offset + k] & 0xf;
data[offset + n--] = data[offset + k] >> 4;
}
return readBytes * 2;
}
对 12 位整数执行相同操作(假设 MSB 半字节排序):
public static int Read(this Stream stream, ushort[] data, int offset, int length)
{
if (stream == null)
{
throw new ArgumentNullException(nameof(stream));
}
if (data == null)
{
throw new ArgumentNullException(nameof(data));
}
if (data.Length < offset + length)
{
throw new ArgumentOutOfRangeException(nameof(length));
}
if (length < 2)
{
throw new ArgumentOutOfRangeException(nameof(length), "Cannot read fewer than two samples at a time");
}
// we always need a multiple of two
length -= length % 2;
// 3 bytes length samples
// --------- * -------------- = N bytes
// 2 samples 1
int rawCount = (length / 2) * 3;
// This will place GC load. Something like a buffer pool or keeping
// the allocation as a field on the reader would be a good idea.
var rawData = new byte[rawCount];
int readBytes = 0;
// if the underlying stream returns an even number of bytes, we will need to try again
while (readBytes < data.Length)
{
int c = stream.Read(rawData, readBytes, rawCount - readBytes);
if (c <= 0)
{
// End of stream
break;
}
readBytes += c;
}
// unpack
int k = 0;
for (int i = 0; i < readBytes; i += 3)
{
// EOF in second byte is undefined
if (i + 1 >= readBytes)
{
throw new InvalidOperationException("Unexpected EOF");
}
data[(k++) + offset] = (ushort)((rawData[i + 0] << 4) | (rawData[i + 1] >> 4));
// EOF in third byte == only one sample
if (i + 2 < readBytes)
{
data[(k++) + offset] = (ushort)(((rawData[i + 1] & 0xf) << 8) | rawData[i + 2]);
}
}
return k;
}
推荐阅读
- reactjs - 在 React 中从 Child 更新 Parent 状态而不触发 Child 的重新渲染
- html-webpack-plugin - 使用 pug、json、htmlwebpackplugin 访问嵌套对象
- kotlin - 在 kotlin android 开发中,布局(以编程方式)如何与没有 xml 的数据绑定一起工作?
- python - 错误:jupyter notebook 中不支持的类文件主要版本 56
- python - 使用数组中的名称创建 python 函数
- javascript - For 循环遍历 Array 不起作用。如何解决?
- java - Java 正则表达式在回顾中只能使用 1 个量词(需要 2 个)
- c# - 使用位图提高 xamarin.forms 中的对比度导致类型加载异常
- c# - Blazor 中的“无法从绑定属性‘绑定值’推断属性名称”错误
- php - ZF2 基于路由约束路由多个控制器