分享

Fortran对无格式文件的大小端(big_endian & little_endian)转换

 zdhai326 2011-02-16
Fortran对无格式文件的大小端(big_endian & little_endian)转换
 
 
字节序,又称端序,尾序,英文:Endianness。在计算机科学领域中,字节序是指存放多字节数据的字节(byte)的顺序,典型的情况是整数在内存中的存放方式和网络传输的传输顺序。Endianness有时候也可以用指位序(bit)。

一般而言,字节序指示了一个UCS-2字符的哪个字节存储在低地址。如果LSByte在MSByte的前面,即LSB为低地址,则该字节序是小端序;反之则是大端序。在网络编程中,字节序是一个必须被考虑的因素,因为不同的处理器体系可能采用不同的字节序。在多平台的代码编程中,字节序可能会导致难以察觉的bug。
引自 http://zh./zh-cn/%E5%AD%97%E8%8A%82%E5%BA%8F

数值预报模式多用big_endian来存储数据,如果需要自己写程序来读写这些数据,端序的转换还是需要了解一些的。(所以我更喜欢用独立于机器的netCDF格式,没有这些麻烦事。)
那么如何用FORTRAN实现大小端转换?这里拿我常用的gfotran和PGI FORTRAN编译器为例。

用编译选项来控制:
gfortran编译器用 -fconvert=<conversion>,conversion其值可以是native,swap,little-endian和big-endian。详见《Using GNU Fortran》Chapter 2: GNU Fortran Command Options
PGI FORTRAN编译器用 -byteswapio。详见《PGI User Guide》Chapter 2. Using Command Line Options

例如,一个简单的f90源文件foo.f90:

PROGRAM convert

IMPLICIT NONE

INTEGER   :: i

i = 305419896 ! 0x12345678
OPEN(20, FILE = 'test.dat', form = 'unformatted', access='direct', recl=4)
WRITE(20, REC=1) i

END PROGRAM convert


先不加参数编译
$ pgf90 foo.f90
$ ./a.out
用十六进制编辑器查看test.dat的内容(little_endian),



加上参数编译
$ pgf90 -byteswapio foo.f90
$ ./a.out
再看看test.dat的内容,已经变成了这样(big_endian):



从生成文件的结果可以明显的发现little_endian和big_endian的差别。就像是写字,可以从左往右写,也可以从右往左写。


除了设置编译选项,gfortran和PGI FORTRAN都通过可以在fortran代码的“open“中加入“convert“来实现大小端转换。比如下面这个程序,读入了一个big_endian的无格式文件(big.dat),然后存储时就成了little_endian的文件(little.dat)。

PROGRAM convert

IMPLICIT NONE

INTEGER   :: i

OPEN(20, FILE = 'big.dat', form = 'unformatted', access='direct', recl=4, convert='big_endian')
READ(20, REC=1)i

OPEN(21, file= 'little.dat', form ='unformatted', access='direct',recl=4)
WRITE(21,rec=1)i

END PROGRAM convert



另外,由gfortran编译的程序还可以通过设置环境变量GFORTRAN_CONVERT_UNIT来改变大小端,其值可以是:NATIVE, SWAP,LITTLE_ENDIAN,BIG_ENDIAN。这一设置会覆盖fortran代码中open的convert设置,对于无法修改源代码的用户来说,这个功能比较实用。
详见《Using GNU Fortran》3.12 GFORTRAN_CONVERT_UNIT—Set endianness for unformatted I/O

$ gfortran foo.f90
$ export GFORTRAN_CONVERT_UNIT='big_endian'
$ ./a.out

还可以限制某些设备号用BIG_ENDIAN,其它设备号用NATIVE,如:GFORTRAN_CONVERT_UNIT='big_endian;native:10-20'

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多