gEOF处理,用于在Fortran中将原始二进制文件读取到数组中



我正在尝试编写Fortran代码,该代码以64字节的块读取原始二进制文件(例如.png(,对其执行一些操作,然后可能将其写入另一个文件。到目前为止,我写的代码如下,是在这个so答案的帮助下写的:

integer(kind = int8), dimension(0:63) :: file_read_buffer
integer :: input_file_handle
integer :: io_error
open(newunit=input_file_handle, file=input_file_name, status="old", access="stream", action="read", iostat=io_error)
if(io_error /= 0) then
! file didn't open properly
end if
do
read(unit = input_file_handle, iostat = io_error) file_read_buffer
select case(io_error)
case(0)
! consume buffer normally
case(iostat_end)   
! do EOF processing
case default
! error!
end select    
end do

如果在数组完全填充之前达到EOF,那么有没有办法知道在达到EOF之前填充了多少?此外,如果EOF被引发一次,那么对read((的进一步调用是否也会返回EOF?

如果有帮助的话,我现在正在使用gfortran。

如果文件结尾条件是由输入语句引起的,则无法确定该输入语句读取了多少。

然而,由于您的意图是使用该输入大小来处理缓冲区中已填充的部分,因此这不是问题:您无法做到这一点。也就是说,当文件结束条件被触发时,整个缓冲区将变得未定义。

相反,您应该丢弃整个缓冲区并重新处理输入。你有两个选择:

  • 如果到达文件末尾,请在它之前重新定位并读取更少的数据
  • 确定剩余的数据量,如果可用数据量较少,则减少读取(避免文件结尾条件(

第一次,如果你跟踪你的";"成功";位置,故障时可以重新定位:

! Read full-sized chunks
do
read(unit, iostat=iostat) buffer
if (iostat==iostat_end) exit
inquire (unit, pos=file_pos)
end do
! reposition
read (unit, pos=pos)
! Read smaller chunks
do
read (unit, iostat=iostat) buffer(1)
if (iostat==isotat_end) exit
end

(处理在明显的地方进行。(这与另一个相关问题答案中的想法相似。

第二,使用文件位置及其大小,我们可以看到是否有足够的";文件存储单元";填充我们的缓冲区:

inquire (unit, size=file_size)
do
inquire (unit, pos=file_pos)
remaining = (file_size-file_pos+1)*FILE_STORAGE_SIZE/STORAGE_SIZE(buffer)
if (remaining<SIZE(buffer)) exit
read (unit) buffer
end do
read (unit) buffer(:remaining)

FILE_STORAGE_SIZE告诉我们有多少位组成一个文件存储单元,STORAGE_SIZE告诉我们有多少个位要存储(在内存中(阵列的一个元素。

第二种选择可能很好,但总体上并不安全:我们不能确定存储大小为16位的元素是否对应于文件存储单元的16位。不过,这可能对你的目的来说已经足够好了。您还可以创建一个测试文件来查看缓冲区占用了多少文件存储单元。