“向前”阅读并回溯算法

时间:2013-06-26 07:01:46

标签: javascript algorithm data-structures

所以,我试图'模仿'可以包含以下数据的文件格式:

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位浮点数(或者就此而言是double)。这里有一个例子:

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出现两次,则以下两个块将为double阻止并且需要“提前预读”。

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

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

任何人都有任何想法?您可以随意使用伪代码或任何编程语言进行回答。我只需要解决这个问题的基本原则。

以下代码是我提出的(在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

2 个答案:

答案 0 :(得分:0)

我使用两个指针 - 当前数据块,潜在的浮点数或数据块,并在需要时增加后者。

在8字节块读取开始时:

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

在readNextFloat体的末尾:

Next(Float)Index++

答案 1 :(得分:0)

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

  • 以8字节块的形式读取文件。读取块后,将其保存为8字节数组。

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

  • 每当253发生时,从文件中读取8个字节作为double并输出。即使在同一个区块中有多个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);
}