读书笔记--python数据可视化--003_读取定宽数据文件

来源:互联网 发布:adobeacrobat9pro mac 编辑:程序博客网 时间:2024/05/22 18:28

如果文件中的格式是以定宽的格式存储的,那么可以通过格式来匹配并提取数据。一种方法是逐行读取数据,然后利用字符串的操作来提取数据。这种方法比较直接,如果在性能不做要求的话是首选操作。另外一种是利用python的struct模块来提升性能,并能读取较大的数据(比如几百兆的数据),因为这个模块使用c语言而不是python实现的。

struct模块是python标准库的一部分,因此不需安装就能够使用。

#-*- coding: UTF-8 -*-''' #################################################   # Author : 余欢 # Date : Dec 26, 2015    5:25:22 PM #company : 南京师范大学--大数据实验室 # description : 读取定宽数据文件 ################################################# '''import stringimport struct'''1  指定要读取的数据文件2  定义数据读取的方式3  逐行读取文件并根据格式把每行数据解析成单独的字段4  打印每行的每个字段'''filename = "/root/Desktop/data-visualization/data_visualization_Code/3367OS_02_Code/ch02-fixed-width-1M.data"#定义数据文件按中的每一行数据的格式理解mask="9s14s5s"with open(filename, 'r') as f:    for line in f:        #fields = struct.Struct(mask).unpack_from(line)  #面向对象的方法        fields = struct.unpack_from(mask, line)  #非面向对象的方法        print "fields:", [field.strip() for field in fields]

2、Python的struct模块
我们知道python只定义了6种数据类型,字符串,整数,浮点数,列表,元组,字典。但是C语言中有些字节型的变量,在python中该如何实现呢?这点颇为重要,特别是要在网络上进行数据传输的话。python提供了一个struct模块来提供转换。下面就介绍这个模块中的几个方法。

2.1、struct.pack()
struct.pack用于将Python的值根据格式符,转换为字符串(因为Python中没有字节(Byte)类型,可以把这里的字符串理解为字节流,或字节数组)。其函数原型为:struct.pack(fmt, v1, v2, …),参数fmt是格式字符串,关于格式字符串的相关信息在下面有所介绍。v1, v2, …表示要转换的python值。下面的例子将两个整数转换为字符串(字节流):

import struct  a = 20  b = 400  str = struct.pack("ii", a, b)  #转换后的str虽然是字符串类型,但相当于其他语言中的字节流(字节数组),可以在网络上传输  print 'length:', len(str)  print str  print repr(str)  #---- result  #length: 8  #    ----这里是乱码  #'/x14/x00/x00/x00/x90/x01/x00/x00' 

格式符”i”表示转换为int,’ii’表示有两个int变量。进行转换后的结果长度为8个字节(int类型占用4个字节,两个int为8个字节),可以看到输出的结果是乱码,因为结果是二进制数据,所以显示为乱码。可以使用python的内置函数repr来获取可识别的字符串,其中十六进制的0x00000014, 0x00000190分别表示20和400。

2.2、struct.unpack
struct.unpack做的工作刚好与struct.pack相反,用于将字节流转换成python数据类型。它的函数原型为:struct.unpack(fmt, string),该函数返回一个元组。 浮点值在解包后与原来值不一样,这是因为浮点数的精度问题导致的。下面是一个简单的例子:

str = struct.pack("ii", 20, 400)  a1, a2 = struct.unpack("ii", str)  print 'a1:', a1  print 'a2:', a2  #---- result:  #a1: 20  #a2: 400  

2.3、struct.calcsize
struct.calcsize用于计算格式字符串所对应的结果的长度,如:struct.calcsize(‘ii’),返回8。因为两个int类型所占用的长度是8个字节。

2.4、struct.pack_into, struct.unpack_from

import struct  from ctypes import create_string_buffer  buf = create_string_buffer(12)  print repr(buf.raw)  struct.pack_into("iii", buf, 0, 1, 2, -1)  print repr(buf.raw)  print struct.unpack_from('iii', buf, 0)  #---- result  #'/x00/x00/x00/x00/x00/x00/x00/x00/x00/x00/x00/x00'  #'/x01/x00/x00/x00/x02/x00/x00/x00/xff/xff/xff/xff'  #(1, 2, -1)  

2.4、关于格式字符串
这里写图片描述

2.5、字节序
为了在与不同硬件结构之间交换数据,需要考虑字节序,如下:
这里写图片描述

注:缺省的情况下,使用本机字节序(同@),可以通过上面的字符修改字节序。

计算格式字符串的大小函数:struct.calcsize(fmt)

>>>struct.calcsize("ihi")    #缺省为4字节对齐时,长度为1212
>>>struct.calcsize("iih")   #当h在最后的时(此时不4字节对齐),长度为1010
>>>struct.calcsize("@ihi")12
>>>struct.calcsize("=ihi")10
>>>struct.calcsize(">ihi")10
>>>struct.calcsize("<ihi")10
>>>struct.calcsize("!ihi")10

注:二进制文件打开/读取的时候需要使用“rb”/“wb”模式以二进制方式打开/读取文件。
注:关于LE(little-endian)和BE(big-endian)区别:
- LE—最符合人的思维的字节序,地址低位存储值的低位,地址高位存储值的高位。
- BE—最直观的字节序,地址低位存储值的高位,地址高位存储值的低位。
例如:双字0X01020304在内存中存储方式,LE=0403 02 01,BE=01 02 03 04。

0 0
原创粉丝点击