减少FORTRAN中输出文件的大小

时间:2018-05-27 23:29:53

标签: file binary fortran size

我想在不丢失任何数据的情况下最小化FORTRAN中输出文件的大小。为了找到最好的方法,我编写了程序:

      program test                                                              

      character(len=255) format

1     format(9i3)                                                               

c FORMATTED          
      open(99,file='form1.txt',form='formatted')                                
      do i=1,1                                                            
        write(99,1) 1, 2, 3, 4, 5, 6, 7, 8, 9                                   
      enddo                                                                     
      close(99)                                                                 

c UNFORMATTED          
      open(98,file='form2.txt',form='unformatted')                              
      do i=1,1                                                            
        write(98) 1, 2, 3, 4, 5, 6, 7, 8, 9                                     
      enddo                                                                     
      close(98)                                                                 

c DIRECT ACCESS          
      nrec=sizeof(i)*9                                                          
      open(97,file='form3.txt',form='unformatted',                              
     &     access='direct',recl=nrec)                                           
      do i=1,1                                                            
        write(97,rec=i) 1, 2, 3, 4, 5, 6, 7, 8, 9                               
      enddo                                                                     
      close(97)                                                                 

      call system('ls -lh form?.txt')                                           
      end

这将创建三个文件,每个文件一个记录。该计划的输出是:

-rw-r--r--. 1 user users  28 May 27 17:10 form1.txt
-rw-r--r--. 1 user users  44 May 27 17:10 form2.txt
-rw-r--r--. 1 user users  36 May 27 17:10 form3.txt

来自Oracle's website

  

如果FORM ='UNFORMATTED',则每个记录都以INTEGER * 4计数开头并终止,使每个记录比正常情况长8个字符。此约定不与其他语言共享,因此仅对FORTRAN程序之间的通信有用。

我的问题是:

  1. 为什么form1.txtform2.txt之间存在16个字节(不是前面引用中提到的8个字节)的差异?请注意,file1.txt的大小取决于格式(例如,如果我将行format(9i3)更改为format(9i4)file1.txt的文件大小会增加9个字节。)
  2. 我的主要问题是:

    1. 我有大数据文件(大于100G),有五列和数百万行。 FORTRAN中减少输出文件大小的最佳方法是什么(也许以二进制形式写入)?
    2. 我的一个类似问题是:Best way to write a large array to file in fortran? Text vs Other

2 个答案:

答案 0 :(得分:3)

虽然没有直接解决您的问题,但我想指出,如果您使用二进制数据,文件大小有一个下限。即使最密集的存储表示没有任何校验和或关于例如的元信息。如果使用记录长度,则必须存储sizeof(数据类型)* num_entries字节。

您可以使用像blosc这样的快速压缩算法,甚至能够胜过C& RAM-to-RAM memcpy()。效率和性能显然在很大程度上取决于数据的分布,但在实际应用中可以达到几十GB /秒。

100GB可能需要很多数据才能适应您机器的RAM。可以手动对文件进行分块,也可以使用HDF5之类的库。 HDF5为基本任意数量的高性能数据提供压缩分块存储。但是,即使存在HDF5 Fortran API,也可以合并大型库。

答案 1 :(得分:3)

基本上你的格式9i3意味着每个数字在文件中只占用3个字节。这是27个字节再加上一个用于回车的28个字节。

但是你只能以这种格式存储最多999的数字,即使这样,超过99的数字也会混合在一起。

Direct Access存储整数的二进制表示,因此每个数字为32位或4个字节。这总共是36个字节。这超过了你的格式化版本的28,但它可以适用于所有整数,最高可达2,147,483,647,最低可达-2,147,483,648,但仍然是相同的大小。 (如果您希望格式化版本具有相同的灵活性,则需要格式9I11,总共100个字节。)

未格式化的版本有点中间,它仍然存储一些元数据,这就是它比直接访问更大的原因,但是像直接访问一样,你可以在占用相同数量的同时存储所有整数太空了。

关于你的第二个问题,你应该使用什么取决于很多事情。正如您所注意到的,如果您的整数始终在0到99之间,那么它们的字符串表示形式小于它们的二进制表示形式。但是一旦你需要4位数(包括符号),二进制表示就会变小。我还应该指出,如果你的数字很小,你也可以将它们声明为8位或16位整数,这意味着它们只分别占用一个或两个字节。

二进制表示也更快,因为数字不需要在二进制和字符串之间转换。

但是对于您正在谈论的大小,调查其他文件格式可能很有价值,例如NetCDF有一些压缩数据的方法。