fortran - 在 Fortran 中将原始二进制文件读入数组的 EOF 处理

我正在尝试编写 Fortran 代码,以 64 字节的 block 读取原始二进制文件 [例如 .png],对其执行一些操作,然后可能将其写入另一个文件。目前为止我写的代码如下,是借助this SO answer写的:

        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。

最佳答案

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

但是,由于您的意图是使用该输入大小来处理缓冲区中已填充的部分,所以这不是问题:您 cannot do that .也就是说,当触发文件结束条件时,您的整个缓冲区将变为未定义。

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

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

首先,如果您跟踪“成功”位置,则可以在失败时重新定位:

! 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

(处理在明显的地方进行。)这类似于 this other answer 中的想法。一个相关的问题。

对于第二个,使用文件位置及其大小我们可以查看是否有足够的“文件存储单元”来填充我们的缓冲区:

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 位文件存储单元。不过,这可能足以满足您的目的。并且您始终可以创建一个测试文件来查看您的缓冲区占用了多少个文件存储单元。

https://stackoverflow.com/questions/70839162/

相关文章:

r - 假阳性与假阴性权衡图

rust - 您可以在正在构建的结构中引用先前初始化的字段吗?

julia - JuMP 非线性优化约束被打破到 O(1e-9)

postgresql - GROUP BY 时前两个值的差异

python - 有没有办法用mypy覆盖python中继承的类属性类型?

c++ - 我可以用 g++ 编译,但得到一个有等效 cmake 的错误程序(GTK 错误)

pine-script - 如何在版本 5 中使用多个指标 ()

python-3.x - 跳过大型 XML 文件中的元素(python 3)

typescript - 如何在 Typescript 中使用 Chai expect() 验证特定

python - 如何使用 pybind11 从 C++ 调用 python 函数?