在Fortran 90中,什么是写一个数组到一个文本文件中,逐行的好办法? [英] In Fortran 90, what is a good way to write an array to a text file, row-wise?

查看:461
本文介绍了在Fortran 90中,什么是写一个数组到一个文本文件中,逐行的好办法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是新来的Fortran,我希望能够在二维数组写入一个文本文件,在逐行方式(在其自己的行每行的列之间的空间,和)。我曾尝试以下,似乎在下面简单的例子来工作:

I am new to Fortran, and I would like to be able to write a two-dimensional array to a text file, in a row-wise manner (spaces between columns, and each row on its own line). I have tried the following, and it seems to work in the following simple example:

PROGRAM test3
  IMPLICIT NONE

  INTEGER :: i, j, k, numrows, numcols
  INTEGER, DIMENSION(:,:), ALLOCATABLE :: a

  numrows=5001
  numcols=762
  ALLOCATE(a(numrows,numcols))
  k=1
  DO i=1,SIZE(a,1)
    DO j=1,SIZE(a,2)
      a(i,j)=k
      k=k+1
    END DO
  END DO

  OPEN(UNIT=12, FILE="aoutput.txt", ACTION="write", STATUS="replace")
  DO i=1,numrows
    WRITE(12,*) (a(i,j), j=1,numcols)
  END DO
END PROGRAM test3

正如我所说的,这似乎在这个简单的例子很好地工作:生成的文本文件, aoutput.txt ,包含1号线的数字1-762 2号线号763-1524 ,等

As I said, this seems to work fine in this simple example: the resulting text file, aoutput.txt, contains the numbers 1-762 on line 1, numbers 763-1524 on line 2, and so on.

但是,当我用上面的思路(即最后的第五到最后,第四到最后,第三到最后,第二个到最后$ C $上述C线)在更复杂的程序中,我遇到了麻烦;每一行分隔(由一个新行)只能断断续续,似乎。 (我还没有发布,而且很可能将不会发布,在这里我的整个复杂的程序/脚本 - 因为它是比较长)缺乏在我复杂的程序/脚本一致行分隔符的可能表明另一个bug在我的code ,不与四线写入到文件例行以上,由于上​​述简单的例子出现的工作正常。不过,我想知道,你能不能帮我想如果有一个更好的逐行写入到文本文件的例程,我应该使用?

But, when I use the above ideas (i.e., the last fifth-to-last, fourth-to-last, third-to-last, and second-to-last lines of code above) in a more complicated program, I run into trouble; each row is delimited (by a new line) only intermittently, it seems. (I have not posted, and probably will not post, here my entire complicated program/script--because it is rather long.) The lack of consistent row delimiters in my complicated program/script probably suggests another bug in my code, not with the four-line write-to-file routine above, since the above simple example appears to work okay. Still, I am wondering, can you please help me think if there is a better row-wise write-to-text file routine that I should be using?

非常感谢您的宝贵时间。我真的AP preciate它。

Thank you very much for your time. I really appreciate it.

推荐答案

有在这里的几个问题。

There's a few issues here.

最根本的是,你不应该使用文字作为数据的相当大的块数据格式。这是很大的,它是缓慢的。文本输出有利于你要读自己的东西;你不会坐下来的381万整数的打印输出,并通过他们翻转。由于下面的code证明,正确的文本输出为10倍左右慢,和更大的50%,比二进制输出。如果你移动到浮点值,也有使用ASCII字符串作为数据交换格式precision损失的问题。等等。

The fundamental one is that you shouldn't use text as a data format for sizable chunks of data. It's big and it's slow. Text output is good for something you're going to read yourself; you aren't going to sit down with a printout of 3.81 million integers and flip through them. As the code below demonstrates, the correct text output is about 10x slower, and 50% bigger, than the binary output. If you move to floating point values, there are precision loss issues with using ascii strings as a data interchange format. etc.

如果你的目标是用MATLAB来交换数据,这是相当容易地将数据写入格式MATLAB可以读取;您可以使用matOpen / matPutVariable API从MATLAB,或者只是写出来作为一个HDF5数组MATLAB可以阅读。或者你也可以写出来的原Fortran语言的二进制数组如下,并有<一个href=\"http://www.mathworks.com/support/solutions/en/data/1-15RS7/index.html?product=ML&solution=1-15RS7\">matlab阅读。

If your aim is to interchange data with matlab, it's fairly easy to write the data into a format matlab can read; you can use the matOpen/matPutVariable API from matlab, or just write it out as an HDF5 array that matlab can read. Or you can just write out the array in raw Fortran binary as below and have matlab read it.

如果您必须使用ASCII写出来巨大的阵列(其中,如前所述,是一个糟糕的和缓慢的想法),那么你正在运行与在列表的drected IO的默认记录长度的问题。最好是在运行时生成的格式字符串,它正确地描述你的输出,和最安全的对这种大的这顶(〜5000字符宽!)线是明确设置记录长度的东西大于你会打印出从而使FORTRAN IO库不帮忙,打破了线为您服务。

If you must use ascii to write out huge arrays (which, as mentioned, is a bad and slow idea) then you're running into problems with default record lengths in list-drected IO. Best is to generate at runtime a format string which correctly describes your output, and safest on top of this for such large (~5000 character wide!) lines is to set the record length explicitly to something larger than what you'll be printing out so that the fortran IO library doesn't helpfully break up the lines for you.

在下面的code,

  WRITE(rowfmt,'(A,I4,A)') '(',numcols,'(1X,I6))'

产生rowfmt在这种情况下将字符串(762(1X,I6))这是您将用于打印输出的格式,而 RECL 选项打开设置记录长度是东西比大7 *数numCols + 1。

generates the string rowfmt which in this case would be (762(1X,I6)) which is the format you'll use for printing out, and the RECL option to OPEN sets the record length to be something bigger than 7*numcols + 1.

PROGRAM test3
  IMPLICIT NONE

  INTEGER :: i, j, k, numrows, numcols
  INTEGER, DIMENSION(:,:), ALLOCATABLE :: a
  CHARACTER(LEN=30) :: rowfmt
  INTEGER :: txtclock, binclock
  REAL    :: txttime, bintime

  numrows=5001
  numcols=762
  ALLOCATE(a(numrows,numcols))
  k=1
  DO i=1,SIZE(a,1)
    DO j=1,SIZE(a,2)
      a(i,j)=k
      k=k+1
    END DO
  END DO

  CALL tick(txtclock)
  WRITE(rowfmt,'(A,I4,A)') '(',numcols,'(1X,I6))'
  OPEN(UNIT=12, FILE="aoutput.txt", ACTION="write", STATUS="replace", &
       RECL=(7*numcols+10))
  DO i=1,numrows
    WRITE(12,FMT=rowfmt) (a(i,j), j=1,numcols)
  END DO
  CLOSE(UNIT=12)
  txttime = tock(txtclock)

  CALL tick(binclock)
  OPEN(UNIT=13, FILE="boutput.dat", ACTION="write", STATUS="replace", &
       FORM="unformatted")
  WRITE(13) a
  CLOSE(UNIT=13)
  bintime = tock(binclock)

  PRINT *, 'ASCII  time = ', txttime
  PRINT *, 'Binary time = ', bintime

CONTAINS

    SUBROUTINE tick(t)
        INTEGER, INTENT(OUT) :: t

        CALL system_clock(t)
    END SUBROUTINE tick

    ! returns time in seconds from now to time described by t
    REAL FUNCTION tock(t)
        INTEGER, INTENT(IN) :: t
        INTEGER :: now, clock_rate

        call system_clock(now,clock_rate)

        tock = real(now - t)/real(clock_rate)
    END FUNCTION tock
END PROGRAM test3

这篇关于在Fortran 90中,什么是写一个数组到一个文本文件中,逐行的好办法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆