在little-endian系统中读取big-endian文件

时间:2016-09-21 16:53:18

标签: c endianness

我有一个我需要在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.因为我的机器本机是little-endian,我需要手动执行字节交换。这就是我所做的:

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代码中输出垃圾作为输出。我想我已经开始了很长时间,不能再看到自己的错误了。任何人都可以发现任何明显的错误吗?

4 个答案:

答案 0 :(得分:2)

将endian swap作为无符号数学运算,然后分配给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;
    }
}

答案 1 :(得分:0)

我更喜欢这个面具和换档组合:

poise_service

答案 2 :(得分:0)

正如几个人所建议的那样,做无条件的转变就可以了。我正在回答这个问题只是为了完整起见,因为我从接受的答案中略微调整了一下:

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

答案 3 :(得分:-1)

使用无符号类型交换位将使事情变得更加容易:

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

相关问题