Python自学之路九:文件

一个运行中的程序会存取放在随机存取存储器(RAM)上的数据。RAM读取速度快,但断电后保存在上面的数据会自动消失;磁盘速度比RAM慢,但可以一直保持数据。因此,计算机系统在数据存储设计中得权衡磁盘和RAM。程序员需要在非易失性介质(例如磁盘)上做持久化存储和检索数据。

在这篇文章中,你将学习到以下内容

1.文本文件读写

①文件的打开

普通文件是数据持久化最简单的类型,它仅仅是在一个文件名下的字节流,把数据从一个文件读入内存,然后从内存写入文件。读写一个文件之前需要使用open()函数打开它:f = open(filename[,mode[,buffering]])

  • f:open()返回的文件对象;
  • filename:文件的字符串名;
  • mode:可选参数,打开模式和文件类型;
  • buffering:可选参数,文件的缓冲区,默认为-1。

mode第一个字母表明对其的操作:

  • ‘r’表示读模式;
  • ‘w’表示写模式。如果文件不存在则新创建,如果存在则重写新内容;
  • ‘x’表示在文件不存在的情况下新创建并写文件;
  • ‘a’表示在文件末尾追加写内容;
  • ‘+’表示读写模式。

mode第二个字母是文件类型:

  • ‘t’(或者省略)表示文本类型;
  • ‘b’表示二进制文件。

②使用write()写文本文件

生成的文件“example”可以在Python目录下找到,用记事本打开,就能看到刚刚输入的这五行代码。

如果源字符串很大,可以将数据分块,直到所有字符被写入。

例如下面,第一次写入50个字符,然后写入剩下的32个字符:

③使用read()、readline()或者readlines()读文本文件

可以使用不带参数的read()函数一次读入文件的所有内容:

和写入一样,读入也可以设置最大的字符数限制。

例如下面,一次读入50个字符,然后把每一块拼接成原来的字符串article:

我们还可以使用readline()每次读入文件的一行。

例如下面,通过追加每一行拼接成原来的字符串article:

读取文本文件最简单的方式是使用迭代器,它也是每次返回一行,但是代码比之前的例子短:

也可以使用函数readlines()调用每次读取一行,并返回单行字符串的列表:

④使用with自动关闭文件

每一次打开文件之后,都得使用close()关闭文件。

如果不close(),那就要等到垃圾回收时,自动释放资源,垃圾回收的时机是不确定的,也无法控制的。如果程序是一个命令,很快就执行完了,那么可能影响不大(并不是说就保证没问题)。但如果程序是一个服务,或是需要很长时间才能执行完,或者很大并发执行,就可能导致资源被耗尽,也有可能导致死锁。

Python中有一个上下文管理器,可以很好的防止我们忘了使用close()关闭文件,上下文管理器会清理一些资源例如打开的文件。它的书写形式为with expression as variable:

完成上下文管理器的代码后,文件会被自动关闭。

2.二进制文件

①使用write()写二进制文件

如果文件模式字符串中包含'b',那么文件会以二进制模式打开。这种情况下,读写的是字节而不是字符串。

和文本一样,二进制数据也可以分块写入:

②使用read()读二进制文件

③使用seek()改变位置

无论是读或者写文件,Python都会跟踪文件中的位置。函数 tell() 返回距离文件开始处的字节偏移量。函数seek()允许跳转到文件其他字节偏移量的位置:f.seek(offset[, whence])。offset:开始的偏移量,也就是代表需要移动偏移的字节数;whence:给offset参数一个定义,表示要从哪个位置开始偏移:

0代表从文件开头开始算起,1代表从当前位置开始算起,2代表从文件末尾算起。

同时,值得注意的是,如果whence为1或者2时,需要用rb打开文件,否则程序会报错。

whence值为空没设置时会默认为0。

3.结构化文本文件

对于简单的文本文件,唯一的结构层次是间隔的行,但有时候需要更加结构化的文本,用于后续使用的程序保存数据或者向另外一个程序传送数据。

①CSV

带分隔符的文件一般用作数据交换格式或者数据库,是纯文本文件,以逗号为分隔符。csv文件可以是任何支持迭代器协议的对象,并在每次调用其方法时返回一个字符串- 文件对象和列表对象都是合适的。

  • 值没有类型,所有值都是字符串;
  • 不能指定字体颜色等样式;
  • 不能指定单元格的宽高,不能合并单元格;
  • 没有多个工作表;
  • 不能嵌入图像图表。
  1. 除了逗号,还有其他可代替的分隔符'|'和'\t'很常见;
  2. 有些数据会有转义字符序列,如果分隔符出现在一块区域内,则整块都要加上引号或者在它之前加上转义字符;
  3. 文件可能有不同的换行符,在第一行可以加上列名。

文件读取

reader:re = csv.reader()。接受一个可迭代对象(比如csv文件),能返回一个生成器,可以从其中解析出内容。

DictReader:re = csv.DictReader()。与reader类似,但返回的每一个单元格都放在一个元组的值内。

文件写操作

w = csv.writer()/w.witerow(rows)(row:写一行进去)。当文件不存在时,自动生成,支持单行写入和多行写入。

字典数据写入:w = csv.DictWriter()w.writeheader()w.writerow(rows)。writeheader就是写表头,writerow把字典当中key对应的表头的标题栏,然后value写进CSV文件里。

②Excel

openpyxl模块(需要cmd里用pip安装)

  • 用来读写扩展名为xlsx/xlsm/xltx/xltm的文件;
  • Workbook类是对工作簿的抽象;
  • Worksheet类是对表格的抽象;
  • Cell类是对单元格的抽象文件写操作。

创建Excel文件

一个Workbook对象代表一个Excel文档,使用该方法创建一个Worksheet对象后才能打开一个表from openpyxl import Workbookwb = Workbook()ws = wb.active

读取Excel文件

注意是load_worbook!from openpyxl import load_workbookwb = load_workbook(filename)ws = wb.file.active:把当前的工作表提交出来。

获取单元格信息

  • 获取Cell对象:c = wb[‘sheet’][‘A1’]:通过索引的形式取到工作表,再用单元格的坐标的对象来引用它,c = wb[‘sheet’].cell(row=1,column=1):直接用点cell的坐标;
  • c.coordinate:返回单元格坐标;
  • c.value:返回单元格的值;
  • c.row:返回单元格所在的行坐标;
  • c.column:返回单元格所在列坐标。

③PDF

PyPDF2:轻松处理pdf文件的库

  • 包含了PdfFileReader、PdfFileMerger、PageObject和PdfFileWriter四个主要类;
  • 能进行读写、分割、合并、文件转换等多种操作;
  • 只能从PDF文档中提取文本并返回为字符串,而无法提取图像、图表或其他媒体。

PDF读操作:pdfFileReader类

首先用内置迭代open函数打开它,获得一个文件对象,然后再用FileReader处理这个文件,对象就返回了一个FileReader:readFile = open('test.pdf','rb')pdfFileReader = PdfFileReader(readFile)

  • .getNumPages():计算PDF文件总页数;
  • .getPage(index):检索指定编号index的页面。

PDF写操作:pdfFileWriter类

首先由writefile可以进行写,我们有一个写对象,可以得到这个写的对象:writeFile = 'output.pdf'pdfFileWriter = PdfFileWriter()

  • .addPage(pageObj):根据每页返回的PageObject,写入到文件;
  • .addBlankPage():在文件的最后一页后面写入一个空白页,保存到新文件。

合并多个pdf文档

我们可以用append往FileMerger当中把整个pdf文档放里面去,也可以再merge一个,从索引开始,把另一个pdf文件放进去,最后可以把整个merger里的pdf合并在一起,输出一个新的pdf。

单个页面操作:PageObject类

当我们从用pdfreader取到一个page的时候,我们就得到一个pageobject,有了这个对象,我们就能做以下操作:

  • .extractText():按照顺序提取文本;
  • .getContents():访问页面内容;
  • .rotateClockwise(angle):顺时针旋转;
  • .scale(sx,sy):改变页面大小。

④XML(参考Bill Lubanovic)

带分隔符的文件仅有两维的数据:行和列。如果你想在程序之间交换数据结构,需要一种方法把层次结构、序列、集合和其他的结构编码成文本。XML是最突出的处理这种转换的标记(markup)格式,它使用标签(tag)分隔数据,如下面的示例文件menu.xml所示:

以下是XML的一些重要特性:

  • 标签以一个<字符开头,例如示例中的标签 menu、breakfast、lunch、dinner 和 item;
  • 忽略空格;
  • 通常一个开始标签(例如<menu>))跟一段其他的内容,然后是最后相匹配的结束标签,例如</menu>;
  • 标签之间是可以存在多级嵌套的,例子中,标签item是标签breakfast、lunch和dinner的子标签;
  • 可选属性(attribute)可以出现在开始标签里,例如price是item的一个属性;
  • 标签中可以包含值(value),例子中每个item都会有一个值,例如第二个breakfast item的pancakes;
  • 如果一个命名为thing的标签没有内容或者子标签,它可以用一个在右尖括号的前面添加斜杠的简单标签所表示,例如<thing/>代替开始和结束都存在的标签<thing>和</thing>;
  • 存放数据的位置可以是任意的——属性、值或者子标签。例如也可以把最后一个item标签写作 。

在Python中解析XML最简单的方法是使用ElementTree

,下面来解析menu.xml文件以及输出一些标签和属性:

对于嵌套列表中的每一个元素,tag是标签字符串,attrib是它属性的一个字典。ElementTree有许多查找XML导出数据、修改数据乃至写入XML文件的方法,它的Python官方文档中有详细的介绍。

⑤JSON

JavaScript Object Notation(JSON)是源于JavaScript的当今很流行的数据交换格式,它是JavaScript语言的一个子集,也是Python合法可支持的语法,对于Python的兼容性使得它成为程序间数据交换的较好选择。不同于众多的XML模块,Python 只有一个主要的JSON模块json,其中两个主要的函数是json.dumps()json.loads()

如果要处理的是文件而不是字符串

,我们可以使用json.dump()json.load()来编码和解码JSON数据。

JSON编码支持的基本数据类型为None,bool,int,float和str,以及包含这些类型数据的lists,tuples和dictionaries。对于dictionaries,keys需要是字符串类型(字典中任何非字符串类型的key在编码时会先转换为字符串)。 为了遵循JSON规范,我们应该只编码Python的lists和dictionaries。而且,在web应用程序中,顶层对象被编码为一个字典是一个标准做法。JSON编码的格式对于Python语法来说几乎是完全一样的,除了一些小的差异之外。 比如,True会被映射为true,False被映射为false,而None会被映射为null。

如果想参阅更多复杂的例子或者了解json更详细的内容,请查看Python的JSON官方文档

点赞

发表评论

电子邮件地址不会被公开。必填项已用 * 标注