在小端系统中读取大端文件
reading big-endian files in little-endian system
我有一个需要用 C 语言读取的数据文件。它由以二进制形式存储的交替 16 位整数组成,我只需要第一列(即,每隔一个条目从 0 开始)
我有一个简单的 python 脚本可以准确读取文件:
import numpy as np
fname = '[filename]'
columntypes = np.dtype([('curr_pA', '>i2'),('volts', '>i2')])
test = np.memmap(fname, dtype=columntypes,mode='r')['curr_pA']
我想将它移植到 C。因为我的机器本身是小端的,所以我需要手动执行字节交换。这是我所做的:
void swapByteOrder_int16(double *current, int16_t *rawsignal, int64_t length)
{
int64_t i;
for (i=0; i<length; i++)
{
current[i] = ((rawsignal[2*i] << 8) | ((rawsignal[2*i] >> 8) & 0xFF));
}
}
int64_t read_current_int16(FILE *input, double *current, int16_t *rawsignal, int64_t position, int64_t length)
{
int64_t test;
int64_t read = 0;
if (fseeko64(input,(off64_t) position*2*sizeof(int16_t),SEEK_SET))
{
return 0;
}
test = fread(rawsignal, sizeof(int16_t), 2*length, input);
read = test/2;
if (test != 2*length)
{
perror("End of file reached");
}
swapByteOrder_int16(current, rawsignal, length);
return read;
}
在 read_current_int16
函数中,我使用 fread
将一大块数据(两列)读入 rawsignal
数组。然后我调用 swapByteOrder_int16
来挑选所有其他值,并交换其字节。然后我将结果转换为 double
并将其存储在 current
.
中
没用。我在 C 代码中得到垃圾作为输出。我想我已经开始太久了,再也看不到自己的错误了。任何人都可以发现任何明显的错误吗?
作为无符号数学执行字节序交换,然后分配给 double
。
void swapByteOrder_int16(double *current, const int16_t *rawsignal, size_t length) {
for (size_t i = 0; i < length; i++) {
int16_t x = rawsignal[2*i];
x = (x*1u << 8) | (x*1u >> 8);
current[i] = x;
}
}
用无符号类型交换位将使事情变得容易得多:
void swapByteOrder_int16(double *current, void const *rawsignal_, size_t length)
{
uint16_t const *rawsignal = rawsignal_;
size_t i;
for (i=0; i<length; i++)
{
uint16_t tmp = rawsignal[2*i];
tmp = ((tmp >> 8) & 0xffu) | ((tmp << 8) & 0xff00u);
current[i] = (int16_t)(tmp);
}
}
注意:当 rawsignal
未对齐时,您必须 memcpy()
它。
我更喜欢这种蒙版和移位组合:
current[i] = ((rawsignal[2*i] & 0x00ff) << 8) | (rawsignal[2*i] >> 8)
正如几个人所建议的那样,以未签名的方式进行轮班就可以了。为了完整起见,我用我的实现来回答这个问题,因为我从接受的答案中稍微调整了一下:
void swapByteOrder_int16(double *current, uint16_t *rawsignal, int64_t length)
{
union int16bits bitval;
int64_t i;
for (i=0; i<length; i++)
{
bitval.bits = rawsignal[2*i];
bitval.bits = (bitval.bits << 8) | (bitval.bits >> 8);
current[i] = (double) bitval.currentval;
}
}
union int16bits
{
uint16_t bits;
int16_t currentval;
};
我有一个需要用 C 语言读取的数据文件。它由以二进制形式存储的交替 16 位整数组成,我只需要第一列(即,每隔一个条目从 0 开始)
我有一个简单的 python 脚本可以准确读取文件:
import numpy as np
fname = '[filename]'
columntypes = np.dtype([('curr_pA', '>i2'),('volts', '>i2')])
test = np.memmap(fname, dtype=columntypes,mode='r')['curr_pA']
我想将它移植到 C。因为我的机器本身是小端的,所以我需要手动执行字节交换。这是我所做的:
void swapByteOrder_int16(double *current, int16_t *rawsignal, int64_t length)
{
int64_t i;
for (i=0; i<length; i++)
{
current[i] = ((rawsignal[2*i] << 8) | ((rawsignal[2*i] >> 8) & 0xFF));
}
}
int64_t read_current_int16(FILE *input, double *current, int16_t *rawsignal, int64_t position, int64_t length)
{
int64_t test;
int64_t read = 0;
if (fseeko64(input,(off64_t) position*2*sizeof(int16_t),SEEK_SET))
{
return 0;
}
test = fread(rawsignal, sizeof(int16_t), 2*length, input);
read = test/2;
if (test != 2*length)
{
perror("End of file reached");
}
swapByteOrder_int16(current, rawsignal, length);
return read;
}
在 read_current_int16
函数中,我使用 fread
将一大块数据(两列)读入 rawsignal
数组。然后我调用 swapByteOrder_int16
来挑选所有其他值,并交换其字节。然后我将结果转换为 double
并将其存储在 current
.
没用。我在 C 代码中得到垃圾作为输出。我想我已经开始太久了,再也看不到自己的错误了。任何人都可以发现任何明显的错误吗?
作为无符号数学执行字节序交换,然后分配给 double
。
void swapByteOrder_int16(double *current, const int16_t *rawsignal, size_t length) {
for (size_t i = 0; i < length; i++) {
int16_t x = rawsignal[2*i];
x = (x*1u << 8) | (x*1u >> 8);
current[i] = x;
}
}
用无符号类型交换位将使事情变得容易得多:
void swapByteOrder_int16(double *current, void const *rawsignal_, size_t length)
{
uint16_t const *rawsignal = rawsignal_;
size_t i;
for (i=0; i<length; i++)
{
uint16_t tmp = rawsignal[2*i];
tmp = ((tmp >> 8) & 0xffu) | ((tmp << 8) & 0xff00u);
current[i] = (int16_t)(tmp);
}
}
注意:当 rawsignal
未对齐时,您必须 memcpy()
它。
我更喜欢这种蒙版和移位组合:
current[i] = ((rawsignal[2*i] & 0x00ff) << 8) | (rawsignal[2*i] >> 8)
正如几个人所建议的那样,以未签名的方式进行轮班就可以了。为了完整起见,我用我的实现来回答这个问题,因为我从接受的答案中稍微调整了一下:
void swapByteOrder_int16(double *current, uint16_t *rawsignal, int64_t length)
{
union int16bits bitval;
int64_t i;
for (i=0; i<length; i++)
{
bitval.bits = rawsignal[2*i];
bitval.bits = (bitval.bits << 8) | (bitval.bits >> 8);
current[i] = (double) bitval.currentval;
}
}
union int16bits
{
uint16_t bits;
int16_t currentval;
};