从 C 到 Python:写二进制
From C to Python: writing binary
我正在编写一个从 C 到 python 的脚本,以生成二进制格式的站数据,以便在 GrADS. Here the documentation about the structure: http://cola.gmu.edu/grads/gadoc/aboutstationdata.html#station
中使用
Python 脚本生成二进制文件,但 GrADS 只能读取第一个站,并且从 C 生成的二进制文件与 python 输出文件有很大不同。
我在想问题是在文件中写入 de struct (ReportHeader) 时。
C 脚本:
#include <stdio.h>
/* Structure that describes a report header in a stn file */
struct rpthdr {
char id[8]; /* Character station id */
float lat; /* Latitude of report */
float lon; /* Longitude of report */
float t; /* Time in relative grid units */
int nlev; /* Number of levels following */
int flag; /* Level independent var set flag */
} hdr;
main () {
FILE *ifile, *ofile;
char rec[80];
int flag,year,month,yrsav,mnsav,i;
float val1,val2,val3,val4,val5;
/* Open files */
ifile = fopen ("listabin1112.txt","r");
ofile = fopen ("arquivo1112.dat","wb");
if (ifile==NULL || ofile==NULL) {
printf ("Error opening files\n");
return 0 ;
}
/* Read,write loop */
flag = 1;
while (fgets(rec,79,ifile)!=NULL) {
/* Format conversion */
sscanf (rec," %f %f %f %f %f %f %f",&hdr.lat,&hdr.lon,&val1,&val2,&val3,&val4,&val5);
for (i=0; i<8; i++) {
hdr.id[i] = rec[i+25];
}
printf("%f\n", hdr.lat);
/*Time group terminator if need */
if (flag) {
yrsav = year;
mnsav = month;
flag = 0;
}
if (yrsav!=year || mnsav!=month) {
hdr.nlev = 0;
fwrite (&hdr,sizeof(struct rpthdr), 1, ofile);
}
yrsav = year;
mnsav = month;
/* Write this report */
hdr.nlev = 1;
hdr.flag = 1;
hdr.t = 0.0;
fwrite (&hdr,sizeof(struct rpthdr), 1, ofile);
fwrite (&val1,sizeof(float), 1, ofile);
fwrite (&val2,sizeof(float), 1, ofile);
fwrite (&val3,sizeof(float), 1, ofile);
fwrite (&val4,sizeof(float), 1, ofile);
fwrite (&val5,sizeof(float), 1, ofile);
}
hdr.nlev = 0;
fwrite (&hdr,sizeof(struct rpthdr), 1, ofile);
}
还有我的 python 脚本:
from ctypes import *
import struct
class ReportHeader(Structure):
_fields_ = [('id', c_char * 8),
('lat', c_float),
('lon', c_float),
('t', c_float),
('nlev', c_int),
('flag', c_int)]
if __name__ == '__main__':
ifile = "listabin1112.txt"
ofile = "teste.dat"
of = open(ofile, "wb")
hdr = ReportHeader()
""" Read, write loop """
ids = 10000000
with open(ifile) as f:
for line in f:
lat, lon, val1, val2, val3, val4, val5, cidade = line.rstrip().split()
hdr.lat = float(lat) - 0.000001
hdr.lon = float(lon) - 0.000001
hdr.id = str(ids)
hdr.flag = 1
hdr.nlev = 1
hdr.t = 0.
ids += 1
print hdr.lat
""" Escreve """
of.write(hdr)
of.write(struct.pack('f', float(val1)))
of.write(struct.pack('f', float(val2)))
of.write(struct.pack('f', float(val3)))
of.write(struct.pack('f', float(val4)))
of.write(struct.pack('f', float(val5)))
hdr.nlev = 0
of.write(hdr)
of.close()
C 代码使用 float
,您的 python 代码使用 d
,这是 double
的格式;你必须使用 f
来匹配 C 格式。
由于没有任何示例输入,我将代码缩减为只创建带有示例数据的二进制文件:
C
#include <stdio.h>
#include <string.h>
struct rpthdr
{
char id[8]; /* Character station id */
float lat; /* Latitude of report */
float lon; /* Longitude of report */
float t; /* Time in relative grid units */
int nlev; /* Number of levels following */
int flag; /* Level independent var set flag */
} hdr;
int main(void)
{
FILE* ofile;
float val1, val2, val3, val4, val5;
/* Open files */
ofile = fopen("arquivo1112.dat", "wb");
/* Write this report */
strcpy(hdr.id,"1234567");
hdr.lat = 45.123f;
hdr.lon = 110.456f;
hdr.nlev = 1;
hdr.flag = 2;
hdr.t = 1.0f;
val1 = 2.0f;
val2 = 3.0f;
val3 = 4.0f;
val4 = 5.0f;
val5 = 6.0f;
fwrite(&hdr, sizeof(struct rpthdr), 1, ofile);
fwrite(&val1, sizeof(float), 1, ofile);
fwrite(&val2, sizeof(float), 1, ofile);
fwrite(&val3, sizeof(float), 1, ofile);
fwrite(&val4, sizeof(float), 1, ofile);
fwrite(&val5, sizeof(float), 1, ofile);
}
Python
from ctypes import *
import struct
class ReportHeader(Structure):
_fields_ = [('id', c_char * 8),
('lat', c_float),
('lon', c_float),
('t', c_float),
('nlev', c_int),
('flag', c_int)]
ofile = "teste.dat"
with open(ofile, "wb") as of:
hdr = ReportHeader()
hdr.id = b'1234567'
hdr.lat = 45.123
hdr.lon = 110.456
hdr.nlev = 1
hdr.flag = 2
hdr.t = 1.0
val1 = 2.0
val2 = 3.0
val3 = 4.0
val4 = 5.0
val5 = 6.0
of.write(hdr)
of.write(struct.pack('5f',val1,val2,val3,val4,val5))
结果(两个文件都是48字节)
C:\test1.exe
C:\test2.py
C:\>fc arquivo1112.dat teste.dat
Comparing files arquivo1112.dat and TESTE.DAT
FC: no differences encountered
所以要么你在为浮点数编辑代码时修复了代码,要么问题出在输入数据的处理上。
我正在编写一个从 C 到 python 的脚本,以生成二进制格式的站数据,以便在 GrADS. Here the documentation about the structure: http://cola.gmu.edu/grads/gadoc/aboutstationdata.html#station
中使用Python 脚本生成二进制文件,但 GrADS 只能读取第一个站,并且从 C 生成的二进制文件与 python 输出文件有很大不同。 我在想问题是在文件中写入 de struct (ReportHeader) 时。
C 脚本:
#include <stdio.h>
/* Structure that describes a report header in a stn file */
struct rpthdr {
char id[8]; /* Character station id */
float lat; /* Latitude of report */
float lon; /* Longitude of report */
float t; /* Time in relative grid units */
int nlev; /* Number of levels following */
int flag; /* Level independent var set flag */
} hdr;
main () {
FILE *ifile, *ofile;
char rec[80];
int flag,year,month,yrsav,mnsav,i;
float val1,val2,val3,val4,val5;
/* Open files */
ifile = fopen ("listabin1112.txt","r");
ofile = fopen ("arquivo1112.dat","wb");
if (ifile==NULL || ofile==NULL) {
printf ("Error opening files\n");
return 0 ;
}
/* Read,write loop */
flag = 1;
while (fgets(rec,79,ifile)!=NULL) {
/* Format conversion */
sscanf (rec," %f %f %f %f %f %f %f",&hdr.lat,&hdr.lon,&val1,&val2,&val3,&val4,&val5);
for (i=0; i<8; i++) {
hdr.id[i] = rec[i+25];
}
printf("%f\n", hdr.lat);
/*Time group terminator if need */
if (flag) {
yrsav = year;
mnsav = month;
flag = 0;
}
if (yrsav!=year || mnsav!=month) {
hdr.nlev = 0;
fwrite (&hdr,sizeof(struct rpthdr), 1, ofile);
}
yrsav = year;
mnsav = month;
/* Write this report */
hdr.nlev = 1;
hdr.flag = 1;
hdr.t = 0.0;
fwrite (&hdr,sizeof(struct rpthdr), 1, ofile);
fwrite (&val1,sizeof(float), 1, ofile);
fwrite (&val2,sizeof(float), 1, ofile);
fwrite (&val3,sizeof(float), 1, ofile);
fwrite (&val4,sizeof(float), 1, ofile);
fwrite (&val5,sizeof(float), 1, ofile);
}
hdr.nlev = 0;
fwrite (&hdr,sizeof(struct rpthdr), 1, ofile);
}
还有我的 python 脚本:
from ctypes import *
import struct
class ReportHeader(Structure):
_fields_ = [('id', c_char * 8),
('lat', c_float),
('lon', c_float),
('t', c_float),
('nlev', c_int),
('flag', c_int)]
if __name__ == '__main__':
ifile = "listabin1112.txt"
ofile = "teste.dat"
of = open(ofile, "wb")
hdr = ReportHeader()
""" Read, write loop """
ids = 10000000
with open(ifile) as f:
for line in f:
lat, lon, val1, val2, val3, val4, val5, cidade = line.rstrip().split()
hdr.lat = float(lat) - 0.000001
hdr.lon = float(lon) - 0.000001
hdr.id = str(ids)
hdr.flag = 1
hdr.nlev = 1
hdr.t = 0.
ids += 1
print hdr.lat
""" Escreve """
of.write(hdr)
of.write(struct.pack('f', float(val1)))
of.write(struct.pack('f', float(val2)))
of.write(struct.pack('f', float(val3)))
of.write(struct.pack('f', float(val4)))
of.write(struct.pack('f', float(val5)))
hdr.nlev = 0
of.write(hdr)
of.close()
C 代码使用 float
,您的 python 代码使用 d
,这是 double
的格式;你必须使用 f
来匹配 C 格式。
由于没有任何示例输入,我将代码缩减为只创建带有示例数据的二进制文件:
C
#include <stdio.h>
#include <string.h>
struct rpthdr
{
char id[8]; /* Character station id */
float lat; /* Latitude of report */
float lon; /* Longitude of report */
float t; /* Time in relative grid units */
int nlev; /* Number of levels following */
int flag; /* Level independent var set flag */
} hdr;
int main(void)
{
FILE* ofile;
float val1, val2, val3, val4, val5;
/* Open files */
ofile = fopen("arquivo1112.dat", "wb");
/* Write this report */
strcpy(hdr.id,"1234567");
hdr.lat = 45.123f;
hdr.lon = 110.456f;
hdr.nlev = 1;
hdr.flag = 2;
hdr.t = 1.0f;
val1 = 2.0f;
val2 = 3.0f;
val3 = 4.0f;
val4 = 5.0f;
val5 = 6.0f;
fwrite(&hdr, sizeof(struct rpthdr), 1, ofile);
fwrite(&val1, sizeof(float), 1, ofile);
fwrite(&val2, sizeof(float), 1, ofile);
fwrite(&val3, sizeof(float), 1, ofile);
fwrite(&val4, sizeof(float), 1, ofile);
fwrite(&val5, sizeof(float), 1, ofile);
}
Python
from ctypes import *
import struct
class ReportHeader(Structure):
_fields_ = [('id', c_char * 8),
('lat', c_float),
('lon', c_float),
('t', c_float),
('nlev', c_int),
('flag', c_int)]
ofile = "teste.dat"
with open(ofile, "wb") as of:
hdr = ReportHeader()
hdr.id = b'1234567'
hdr.lat = 45.123
hdr.lon = 110.456
hdr.nlev = 1
hdr.flag = 2
hdr.t = 1.0
val1 = 2.0
val2 = 3.0
val3 = 4.0
val4 = 5.0
val5 = 6.0
of.write(hdr)
of.write(struct.pack('5f',val1,val2,val3,val4,val5))
结果(两个文件都是48字节)
C:\test1.exe
C:\test2.py
C:\>fc arquivo1112.dat teste.dat
Comparing files arquivo1112.dat and TESTE.DAT
FC: no differences encountered
所以要么你在为浮点数编辑代码时修复了代码,要么问题出在输入数据的处理上。