从未格式化的二进制文件读取时检查逻辑值的有效性
Validity-Check for logical values when reading from unformatted binary file
我用 Fortran 读取了一个未格式化的二进制检查点文件,需要检查值的有效性。检查点的全部要点是发生了一些崩溃并且检查点文件本身可能已损坏(例如,如果在写入文件期间发生崩溃)。
所以我现在的问题是:是否有标准程序来检查从文件中读取的逻辑值是否正确存储为逻辑值。
一个简短的测试,写任何数字而不是逻辑数字并阅读它给了我一个.false。价值。我假设读取的每个数字都将按照类似 C 的规则进行转换:nr==0 ->.false。 nr!=0 -> .true.. 然而,这并不能帮助我辨别逻辑是否正确编写。
我能想到的是首先将值读取为整数(或某种二进制值?),然后检查它们是 0 还是 1,以指示逻辑的正确写入。
示例:
write_test.f90:
program write_test
logical,parameter :: bool=.true.
real*8,parameter :: r=5e20
open(unit=10,form='unformatted')
write(10)bool,r
close(10)
end program
read_test.f90:
program read_test
logical :: bool1
logical :: bool2
open(unit=10,form='unformatted')
read(10)bool1,bool2
write(*,*)bool1,bool2
end program
read_test.f90 的输出:
T F
bool2
看起来好像是一个很好的逻辑值.false.,但它被存储为一个真实的,我想避免以及可能获得的所有其他数据类型扔在那里。
显然它也没有使用 .true。对于 0 以外的值。我的猜测是存储在那里的实数的前导位是 0,它只读取这个位。
这可能是一个扩展评论而不是一个答案:
当您假设读取的每个数字都将按照类似 C 的规则进行转换时,您就错了:nr==0 ->.false。 nr!=0 -> .true. 或者至少,Fortran 标准的规则不能保证您的假设为真。这在用于表示 True 和 False 的位模式问题上保持沉默,特别是它不强制它们应该与用于表示 0 和 1(或 1 和 0 - 我永远无法得到那些认为那些是布尔值的有趣语言。
Fortran 标准所保证的几乎所有内容是默认大小的实数、整数和逻辑数在内存中占用相同数量的位数(除非您 fiddle 与它们有关)在未格式化写入文件时.这意味着,除其他外,任何 32 位(如果这是您的默认存储单元大小,则为 64 位)都可以解释为实数、整数或逻辑值。
某些位模式可能无法成功解释为任何或所有这些类型,但这又是一个低于 Fortran 标准运行级别的实现问题。
不可能仅从位知道一组 32 位代表什么类型的值,必须在某处描述如何解释二进制文件。这就是使它们相当不便携的原因。
如果这些问题对您很重要,您真的必须自己调查它们,特别是您的编译器(版本)使用什么位模式来表示逻辑值。您可以合理地期望(尽管这不能保证)整数以补码形式表示,实数以 IEEE 形式表示。
我用 Fortran 读取了一个未格式化的二进制检查点文件,需要检查值的有效性。检查点的全部要点是发生了一些崩溃并且检查点文件本身可能已损坏(例如,如果在写入文件期间发生崩溃)。
所以我现在的问题是:是否有标准程序来检查从文件中读取的逻辑值是否正确存储为逻辑值。
一个简短的测试,写任何数字而不是逻辑数字并阅读它给了我一个.false。价值。我假设读取的每个数字都将按照类似 C 的规则进行转换:nr==0 ->.false。 nr!=0 -> .true.. 然而,这并不能帮助我辨别逻辑是否正确编写。
我能想到的是首先将值读取为整数(或某种二进制值?),然后检查它们是 0 还是 1,以指示逻辑的正确写入。
示例:
write_test.f90:
program write_test
logical,parameter :: bool=.true.
real*8,parameter :: r=5e20
open(unit=10,form='unformatted')
write(10)bool,r
close(10)
end program
read_test.f90:
program read_test
logical :: bool1
logical :: bool2
open(unit=10,form='unformatted')
read(10)bool1,bool2
write(*,*)bool1,bool2
end program
read_test.f90 的输出:
T F
bool2
看起来好像是一个很好的逻辑值.false.,但它被存储为一个真实的,我想避免以及可能获得的所有其他数据类型扔在那里。
显然它也没有使用 .true。对于 0 以外的值。我的猜测是存储在那里的实数的前导位是 0,它只读取这个位。
这可能是一个扩展评论而不是一个答案:
当您假设读取的每个数字都将按照类似 C 的规则进行转换时,您就错了:nr==0 ->.false。 nr!=0 -> .true. 或者至少,Fortran 标准的规则不能保证您的假设为真。这在用于表示 True 和 False 的位模式问题上保持沉默,特别是它不强制它们应该与用于表示 0 和 1(或 1 和 0 - 我永远无法得到那些认为那些是布尔值的有趣语言。
Fortran 标准所保证的几乎所有内容是默认大小的实数、整数和逻辑数在内存中占用相同数量的位数(除非您 fiddle 与它们有关)在未格式化写入文件时.这意味着,除其他外,任何 32 位(如果这是您的默认存储单元大小,则为 64 位)都可以解释为实数、整数或逻辑值。
某些位模式可能无法成功解释为任何或所有这些类型,但这又是一个低于 Fortran 标准运行级别的实现问题。
不可能仅从位知道一组 32 位代表什么类型的值,必须在某处描述如何解释二进制文件。这就是使它们相当不便携的原因。
如果这些问题对您很重要,您真的必须自己调查它们,特别是您的编译器(版本)使用什么位模式来表示逻辑值。您可以合理地期望(尽管这不能保证)整数以补码形式表示,实数以 IEEE 形式表示。