Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
File 读取大型文本文件的最快方法_File_Text_Fortran_Fortran90 - Fatal编程技术网

File 读取大型文本文件的最快方法

File 读取大型文本文件的最快方法,file,text,fortran,fortran90,File,Text,Fortran,Fortran90,我希望从大型(~870000000行/~4GB)文本文件中提取某些行组。举个小例子,在一个50行的文件中,我可能需要第3-6行、第18-27行和第39-45行。使用SO开始,并编写一些程序以使用我的数据进行基准测试,fortran90似乎给了我最好的结果(与python、shell命令(bash)等相比) 我目前的方案只是打开文件,使用一系列循环将读取指针移动到需要的位置,并将结果写入输出文件 在上面的小示例中,这看起来像: open(unit=1,fileName) open(

我希望从大型(~870000000行/~4GB)文本文件中提取某些行组。举个小例子,在一个50行的文件中,我可能需要第3-6行、第18-27行和第39-45行。使用SO开始,并编写一些程序以使用我的数据进行基准测试,fortran90似乎给了我最好的结果(与python、shell命令(bash)等相比)

我目前的方案只是打开文件,使用一系列循环将读取指针移动到需要的位置,并将结果写入输出文件

在上面的小示例中,这看起来像:

    open(unit=1,fileName)
    open(unit=2,outFile)

    do i=1,2
      read(1,*)
    end do
    do i=3,6
      read(1,*) line
      write(2,*) line
    end do
    do i=7,17
      read(1,*)
    end do
    do i=18,27
      read(1,*) line
      write(2,*) line
    end do
    do i=28,38
      read(1,*)
    end do
    do i=39,45
      read(1,*) line
      write(2,*) line
    end do
*应该注意的是,我在编译时假设使用缓冲I/o,尽管这似乎只会最低限度地提高速度

我很好奇这是否是完成任务最有效的方法。如果上述事实上是fortran90实现这一点的最佳方法,那么还有其他语言更适合此任务吗


*更新:确保我正在使用缓冲I/o,手动查找最有效的块大小/块计数。这使速度提高了约7%。我应该注意,我正在处理的文件没有固定的记录长度。

您也可以尝试使用
sed
实用程序

sed '3,6!d' yourfile.txt
sed '18,27!d' yourfile.txt

Unix实用程序往往非常优化,能够非常快速地解决像这样的简单任务

任何语言都应该能做到这一点,所以如果你能纠正打字错误,那么坚持主题应该是最有效的。 (如果我在iPad上有一个fortran编译器,它会更有用。)


谢谢你的回复!我确实尝试了一个sed解决方案(即sed-n“3,6p;18,27p;39,45p;45q”文件名),而且无论我的fortran90解决方案的结构如何(awk是类似的),它似乎都要花费大约两倍的时间。如果文件不是那么大的话就没那么重要了,但我正在寻找最快的解决方案,即使它有点复杂。是的,我知道你想做什么,我也有一些类似的任务。无论如何,这些实用程序总是值得一试。另外,您可以尝试在C中实现这一点。准确读取fs的块大小,手动扫描换行,仔细(!)计算它们,并将缓冲区缝合在一起。而且要注意,在没有换行符的情况下处理10G文件不会使您的机器崩溃。以防万一您没有想到这一点-如果您可以访问生成这些大文件的代码,您可以在那里挖掘,也许可以在那里准备您需要的。此外,如果您的行碰巧长度相同,那么你就非常幸运了,你可以手动寻找你需要的线路,这肯定比其他任何方式都要快。但我猜它们的长度不同……总之,仔细看看你的解决方案,我认为如果你自己阅读更大的块和处理行,你当前的解决方案肯定会有所改进。阅读大型文本文件的最快简便方法是什么?把它放在一个非常快的磁盘系统上,不要写慢代码来读取它,这会伤到你自己的脚。还有更复杂的解决方案,但它们非常依赖于操作系统,而实际的IO模式非常依赖于硬件,因为最快的方式通常完全绕过页面缓存。值得一提的是,
mmap()
通常是一个非常糟糕的选择,因为您只想从头到尾地流式处理文件,而不需要重新读取其中的任何部分
mmap()
在您必须从整个文件的随机位置执行多次重新读取时效果最佳。使用
流访问可能比按顺序跳过特定行更快。谢谢,我将使用流I/o了解这可能如何工作。对于流访问,您需要解析文件以查找行尾标记,我看不出这有什么帮助。。(除非所有线路的长度完全相同。)是的,我得出了相同的结论,即流访问没有帮助。不幸的是,这些条目的长度不相等,因此会产生一些简单的解决方案。最终坚持了一个类似于我上面最初的计划。C++中有一个解决方案:看起来有点有希望,但是我宁愿给我的代码额外时间,而不是学习C++的这一个任务。这绝对不是OP提出的更快,这就是他所问的。首先,在循环中嵌入一个条件,并且还读取和解析每一行,而OP的代码只读取和解析他感兴趣的行。我投反对票。@Ross我想你说得有道理。在4GB文件前面的几行示例中,顺序读取不应产生任何影响。在我的带有RAID的工作机器上,一个4GB的文件在大约15秒内得到缓冲。但这是使用对line()数组的读取,然后在循环中执行一些无关紧要的条件。实际上,我们需要将读取性能与条件读取性能分开考虑。因此,我认为您可能正在“获取”(或暗示)非顺序和非流式输入是“最快的”?但这篇文章似乎也在问基本的IO。
PROGRAM AA
IMPLICIT NONE
INTEGER :: In_Unit, Out_Unit, I
LOGICAL, DIMENSION(1000) :: doIt
CHARACTER(LEN=20) :: FileName = 'in.txt'
CHARACTER(LEN=20) :: Outfile = 'out.txt'
CHARACTER(LEN=80) :: line

open(NEWunit=In_Unit,  fileName)  ! Status or action = read only??
open(NEWunit=Out_Unit, outFile)   ! Status or action = new or readwrite??

DoIt        = .FALSE.
DoIt(3:6)   = .TRUE.
DoIt(18:27) = .TRUE.
DoIt(39:45) = .TRUE.

do i=1,1000
  read(I_Unit,*) line
  IF(doIt(I)) write(Out_Unit,*) line
end do

CLOSE(In_Unit)
CLOSE(Out_Unit)

END PROGRAM AA