所以,我试图'模仿'可以包含以下数据的文件格式:
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
。
答案 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);
}