0

因此,我正在尝试“模仿”一种可以包含以下数据的文件格式:

0x64-0xFB(100-251):A single byte consisting of a value (byteval-100)
0xFC(252): A 'null' byte, I don't need anything with that
0xFD(253): An indicator that I need to 'read ahead', more information follows
0xFE(254): Another 'null' byte in this case

这些值都分组为 8 个字节的块,直到EOF发生。

当一个0xFD值出现时,我需要移动到下一个 8 字节块,并在那里读取一个值。读完这篇文章后,我需要移动到下一个字节(并跳过下一个块,因为我已经读过了)。对于这种情况,这将是一个 64 位浮点数(或双精度,就此而言)。这里有一个例子:

0x71 0x75 0xFD 0x6E 0x78 0x82 0x8C 0x72

0x00 0x00 0x00 0x00 0x00 0xC0 0x82 0x40

将是以下值(按顺序)

13 (0x71 - 100)
17 (0x75 - 100)
600.0 (the value of 0x0000000000C08240 in double, because of the 0xFD)
10 (0x6E - 100)
20 (0x78 - 100)
30 (0x82 - 100)
40 (0x8C - 100)
14 (0x72 - 100)

可能在一个块中0xFD出现多次,表示后面的块都是double块(所以,如果0xFD出现两次,后面的两个块将是双块,需要“预读”)。

我已经尝试过对此进行编程,但我想不出一个可行的解决方案(这也有点效率)。我尝试制作一个“长值块”列表,当我进入一个长数据块时,我会跳过它。读取长数据块后,我还需要返回下一个“正常”数据。但是,这会带来各种技术难题。

我确信有一些简单的解决方案,但我无法理解它。

有人有什么想法吗?随意用伪代码或任何编程语言回答这个问题。我只需要如何处理这个问题的基本原则。

以下代码是我想出的(在 Javascript 中):

    readNumber: function() {
        opcode = this.getNextOpcode();      
        switch(opcode) {
            case -1:
            case 252:
            return null;
            case 253:
            return this.readNextFloat(this.position);
            case 255:
                return null; //SYSMIS
                default:
                return opcode - this.header.bias;
            }
        },
    getNextOpcode: function() {
        if(_.contains(this.longdatablocks,this.getCurrentBlock())) {
            gotoBlock(_.max(this.longdatablocks) + 1);
            return this.rU8();
        }
        return this.rU8();
    },
    readNextFloat: function(position) {
        this.gotoBlock(this.getnextBlock())
        console.debug(this.position);
        this.longdatablocks.push(this.getCurrentBlock());
        retval = this.rF64();
        this.position = position;
        return retval;
    },

但是,这并不能很好地处理它。不幸的是,多个0xFD's 没有被覆盖。

4

2 回答 2

0

I'd use two pointers - to current data block, and to potential float or data block, and increment latter when needed.

at the start of 8-byte block reading:

CurrentIndex = NextIndex
Next(Float)Index = CurrentIndex + 1

at the end of readNextFloat body:

Next(Float)Index++
于 2013-06-26T07:30:08.560 回答
0

这是C中的一个解决方案。这个想法:

  • 以 8 字节块读取文件。读取块后,将其保存在 8 字节数组中。

  • 遍历当前块的 8 个字节(这次从内存中读取)并 1 个 1 处理它们

  • 每当出现 253 时,从文件中读取 8 个字节作为双精度并输出。无需向前跳或向后跳,即使在同一块中有多个 253。只需按顺序读取 8 个字节块即可得到正确的输出。

代码:

void parse(char *fname)
{
    FILE *f = fopen(fname, "rb");
    unsigned char *block = (unsigned char *)malloc(8); // allocate an 8 byte block of memory
    while (fread(block, 1, 8, f) == 8) // keep reading 8 bytes from the file to the memory block until EOF
    {
        for (int i = 0; i < 8; i++) // go through the block in memory, byte by byte
        {
            if (block[i] <= 251) printf("%d\n", block[i] - 100); // if the byte is <= 251, output value - 100
            else if (block[i] == 253) // otherwise, read 8 bytes from the file as a double and output it
            {
                double d;
                fread(&d, 1, 8, f);
                printf("%lf\n", d);
            }
        }
    }
    fclose(f);
    free(block);
}
于 2013-06-26T08:31:24.183 回答