我有一些需要挖掘数据的旧文件。这些文件是由Lotus123 Release 4 for DOS创建的。我试图通过解析字节而不是使用Lotus打开文件来更快地读取文件。我有每个10字节的值记录。

这个Q中的@AndrewMorton指向http://www.mettalogic.co.uk/tim/l123/l123r4.html#rec17,它表示我们有一个10字节的GNU Long Double。

当他们读取WK3文件时,他还指出Gnumeric,但是我很难找到相关的代码。

Dim fileBytes() As Byte = My.Computer.FileSystem.ReadAllBytes(fiPath)
Dim arr(10) As Byte
For ...
    arr(x) = fileBytes(x)
    Debug.Print(Convert.ToInt16(fileBytes(x)))
Next ...

'values to the right
Dim data1 As Byte() = New Byte() {0, 0, 0, 0, 0, 45, 17, 188, 22, 64}    ' Value = 12325165
Dim data2 As Byte() = New Byte() {0, 0, 0, 0, 0, 248, 30, 196, 20, 64}   ' Value = 3213246
Dim data3 As Byte() = New Byte() {209, 92, 167, 145, 150, 202, 219, 205, 0, 64} ' Value = 3.21654
Dim data4 As Byte() = New Byte() {0, 0, 0, 0, 0, 120, 68, 196, 20, 64}   ' Value = 3215646
Dim data5 As Byte() = New Byte() {0, 0, 0, 0, 0, 104, 131, 211, 20, 192} ' Value = -3465434
Dim data6 As Byte() = New Byte() {0, 0, 0, 0, 0, 224, 131, 211, 20, 192} ' Value = -3465464
Dim data7 As Byte() = New Byte() {0, 0, 0, 0, 0, 60, 105, 163, 21, 192}  ' Value = -5354654
Dim data8 As Byte() = New Byte() {0, 0, 0, 0, 128, 82, 74, 135, 24, 192} ' Value = -35465546

Dim data1 As Byte() = New Byte() {0, 0, 0, 0, 0, 0, 0, 128, 255, 191}                  ' Value = -1
Dim data2 As Byte() = New Byte() {205, 204, 204, 204, 204, 204, 204, 204, 251, 191}    ' Value = -0.1
Dim data3 As Byte() = New Byte() {10, 215, 163, 112, 61, 10, 215, 163, 248, 191}       ' Value = -0.01
Dim data4 As Byte() = New Byte() {59, 223, 79, 141, 151, 110, 18, 131, 245, 191}       ' Value = -0.001
Dim data5 As Byte() = New Byte() {44, 101, 25, 226, 88, 23, 183, 209, 241, 191}        ' Value = -0.0001
Dim data6 As Byte() = New Byte() {35, 132, 71, 27, 71, 172, 197, 167, 238, 191}        ' Value = -0.00001
Dim data7 As Byte() = New Byte() {182, 105, 108, 175, 5, 189, 55, 134, 235, 191}       ' Value = -0.000001
Dim data8 As Byte() = New Byte() {0, 0, 0, 0, 0, 0, 0, 128, 255, 63}                   ' Value = 1
Dim data9 As Byte() = New Byte() {205, 204, 204, 204, 204, 204, 204, 204, 251, 63}     ' Value = 0.1
Dim data10 As Byte() = New Byte() {10, 215, 163, 112, 61, 10, 215, 163, 248, 63}       ' Value = 0.01
Dim data11 As Byte() = New Byte() {59, 223, 79, 141, 151, 110, 18, 131, 245, 63}       ' Value = 0.001
Dim data12 As Byte() = New Byte() {44, 101, 25, 226, 88, 23, 183, 209, 241, 63}        ' Value = 0.0001
Dim data13 As Byte() = New Byte() {35, 132, 71, 27, 71, 172, 197, 167, 238, 63}        ' Value = 0.00001
Dim data14 As Byte() = New Byte() {182, 105, 108, 175, 5, 189, 55, 134, 235, 63}       ' Value = 0.000001
Dim data15 As Byte() = New Byte() {188, 66, 122, 229, 213, 148, 191, 214, 231, 63}     ' Value = 0.0000001


我已经尝试实现this,但是它不起作用。只是给出垃圾值(我尝试了给出的两个答案)。

如何将10字节的GNU Long Double转换为Decimal。由于GNU使用C语言,因此我欢迎使用C代码,但更喜欢VB.net。

最佳答案

如果编译器的long double实现与此格式兼容,则用C代码从十个十进制值构建一个十字节的数组,然后将该数组解释为long double很简单。以下程序使用命令行中给出的十进制小数。显然,从其他地方(例如从stdin或文件中)获得数字很简单。

#include <stdlib.h>
#include <stdio.h>

void
show_longdouble(const unsigned char array[]) {
    long double *ldp = (long double *)array;
    int ix;

    for (ix = 0 ; ix < 10 ; ++ix) {
        printf("%u ", array[ix]);
    }
    printf("=> %Lf\n", *ldp);
}

int
main(int argc, char *argv[])
{
    if (11 == argc) {
        unsigned char vals[16]; /* only use 10, but dimension 16 for alignment */
        int ix;

        for (ix = 0 ; ix < 10 ; ++ix) {
            sscanf(argv[ix+1], "%hhu", &vals[ix]);
        }
        show_longdouble(vals);
    }
    return 0;
}


运行该程序可以得到:

$ ./gnu-long-double 0 0 0 0 0 45 17 188 22 64
0 0 0 0 0 45 17 188 22 64 => 12325165.000000

$ ./gnu-long-double 0 0 0 0 0 248 30 196 20 64
0 0 0 0 0 248 30 196 20 64 => 3213246.000000


如果要手动进行转换,而不是依赖于C编译器的内置printf,则该格式在Wikipedia中称为“ x86 Extended Precision格式”,并在https://en.wikipedia.org/wiki/Extended_precision#x86_extended_precision_format中进行了描述。

10-07 19:26
查看更多