我有一些需要挖掘数据的旧文件。这些文件是由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中进行了描述。