我尝试打开6个不同的文件(至少),然后读取每个文件中的行数,每个文件大约应该有20,000行。我已经在这个论坛上阅读了一些关于如何做到这一点的帖子,因为我是一个新手,并且我已经尝试为我的目的实施它。
我可以单独执行此操作而没有任何问题,但是当我尝试读入所有文件时,我收到一条错误消息。我得到了" Killed:9"错误消息或malloc错误:
malloc: *** mach_vm_map(size=63032829050880) failed (error code=3)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
此错误对内存分配有何意义?我究竟做错了什么?我该如何纠正这个问题?
PROGRAM X
IMPLICIT NONE
INTEGER :: J,IO,NFILES,NLINES
CHARACTER (LEN=128) :: FILENAME
NFILES = 6
NLINES = 0
DO J = 0,NFILES-1
WRITE(FILENAME,'(A,I7.7,A)') 'data_',J*200,'.txt'
OPEN(1,FILE='FILENAME',FORM='FORMATTED')
DO
READ(1,*,IOSTAT=IO)
IF (IO/=0) EXIT
NLINES = NLINES + 1
END DO
WRITE(*,*) NLINES
CLOSE(1)
END DO
END PROGRAM X
我正在使用gfortran进行编译。
更新
我创建了6个测试文件data_0000000.txt,data_0000200.txt,...,data_0001000.txt,每个文件少于10行,每行少于100个字符。不幸的是,我得到了同样的错误。
答案 0 :(得分:1)
强制性免责声明:如果您只想知道文件中的行数,请使用wc -l <filename>
。如果你不需要,不要重新发明轮子。
我写这不一定是因为我认为你不知道,但因为其他人可能会出现,并认为他们需要编写自己的程序来获取文件行数。
至于你的问题:我不知道为什么你会收到malloc
错误。也许告诉我们你正在使用哪个编译器和系统(包括版本)?也就是说,在阅读代码时我注意到了三件事:
您创建了一个变量FILENAME
,但之后就不再使用它了。你引用它:FILE='FILENAME'
这意味着open命令会查找一个字面上称为FILENAME
的文件,而不是名称存储在变量FILENAME
中的文件。删除引号:
OPEN(1, FILENAME=FILENAME, FORM='FORMATTED')
您使用单位编号1
- 这很危险。不同版本的Fortran使用特定的单位编号进行特定用途。使用更大(至少10或更多)的句柄,或者甚至更好地使用open语句中的newunit
描述符:
INTEGER :: u
OPEN(NEWUNIT=u, FILE=FILENAME, ACTION='READ', FORM='FORMATTED')
READ(u, *, IOSTAT=IO)
CLOSE(u)
您没有在文件之间将NLINES
变量重置为0。程序将打印累积总和,而不是直接打印每个文件的行数。
答案 1 :(得分:0)
添加到@ chw21的响应,如果你的唯一目的是计算文件中的记录(行)数,这里有一个模块化的解决方案和一个测试程序(计数在子程序{{1}内完成) }):
getNumRecordInFile()
现在,如果您将此代码放在名为“main.f95”的文件中并在Fortran 2008标准下进行编译,那么它应该输出“main.f95”文件中的行数,这应该类似于以下内容:
module NumRecord_mod
implicit none
type :: Err_type
logical :: occurred = .false.
integer :: stat = -huge(0)
character(:), allocatable :: msg
end type Err_type
contains
! returns the number of lines in a file.
subroutine getNumRecordInFile(filePath,numRecord,Err)
implicit none
character(len=*), intent(in) :: filePath
integer, intent(out) :: numRecord
type(Err_type), intent(out) :: Err
character(len=8) :: record
integer :: fileUnit
logical :: fileExists, isOpen
integer :: iostat
character(*), parameter :: PROCEDURE_NAME = "@getNumRecordInFile()"
Err%occurred = .false.
Err%msg = ""
! Check if file exists
inquire( file=filePath, exist=fileExists, opened=isOpen, number=fileUnit, iostat=Err%stat )
if (Err%stat/=0) then
Err%occurred = .true.
Err%msg = PROCEDURE_NAME // ": Error occurred while inquiring the status of file='" // filePath // "'."
return
end if
if (.not.fileExists) then
Err%occurred = .true.
Err%msg = PROCEDURE_NAME // ": The input file='" // filePath // "' does not exist."
return
end if
if (isOpen) close(unit=fileUnit,iostat=Err%stat)
if (Err%stat>0) then
Err%occurred = .true.
Err%msg = PROCEDURE_NAME // ": Error occurred while attempting to close the open input file='" // filePath // "'."
return
end if
open(newunit=fileUnit,file=filePath,status="old",iostat=Err%stat)
if (Err%stat>0) then
Err%occurred = .true.
Err%msg = PROCEDURE_NAME // ": Error occurred while opening input file='" // filePath // "'."
return
end if
numRecord = 0
do
read(fileUnit,'(A)',iostat=iostat) record
if(iostat==0) then
numRecord = numRecord + 1
cycle
elseif(is_iostat_end(iostat)) then
exit
else
Err%occurred = .true.
Err%stat = iostat
Err%msg = PROCEDURE_NAME // ": Error occurred while reading input file='" // filePath // "'."
return
end if
end do
close(fileUnit,iostat=Err%stat)
if (Err%stat>0) then
Err%occurred = .true.
Err%msg = PROCEDURE_NAME // ": Error occurred while attempting to close the open input file='" // &
filePath // "' after counting the number of records in file."
return
end if
end subroutine getNumRecordInFile
end module NumRecord_mod
program test_numRecord
use NumRecord_mod
implicit none
type(Err_type) :: Err
integer :: numRecord
character(:), allocatable :: filePath
filePath = "main.f95"
call getNumRecordInFile(filePath=filePath,numRecord=numRecord,Err=Err)
if (Err%occurred) then
write(*,*) Err%msg
write(*,*) Err%stat
error stop
else
write(*,*) "Total number of records in file='" // filePath // "': ", numRecord
end if
end program test_numRecord
对于测试,您只需复制粘贴在线Fortran编译器中的整个代码:https://www.tutorialspoint.com/compile_fortran_online.php
但请记住,在执行代码之前,请转到$gfortran -std=f2008 *.f95 -o main
$main
Total number of records in file='main.f95': 98
,将编译选项-std=f95
更改为-std=f2008
。
答案 2 :(得分:-1)
尝试这个更改(声明和读取行),没有指定行内容的变量,这里插入虚拟...
character(len=1000) :: dummy
...
READ(u, '(a)' , IOSTAT=IO) dummy
....