Python_IO编程

本篇文章将介绍python里面的I/O编程。更多内容请参考:python学习指南

I/O编程

读写文件时最常见的IO操作。Python内置了读写文件的函数,用法和C是兼容的。
读写文件前,我们必须了解一下,在磁盘上读写文件的功能都是由操作系统提供的,现代操作系统不允许普通的程序直接操作磁盘,所以,读写文件就是请求操作系统打开一个文件对象(通常称为文件描述符),然后,通过操作系统提供的接口从这个文件对象中读取数据(读文件),或者把数据写入这个文件对象(写文件)。

在I/O编程中,Stream(流)是一种重要的概念,分为输入流(Input Stream)和输入流(Output Stream)。我们可以把流理解为一个水管,一个负责输入,一个负责输出,这样读写就可以实现同步。

文件读写

打开文件
读写文件是最常见的IO操作。Python内置了读写文件的函数,方便了文件的IO操作。
文件读写之前需要打开文件,确定文件的读写模式。open函数用来打开文件,语法如下:

open(name[, mode[, buffering]])

open函数使用一个文件作为唯一的强制参数,然后返回一个文件对象。模式(mode)和缓冲区(buffering)参数都是可选的,默认模式是读模式,默认缓冲区是无。
如果文件不存在,open()函数就会抛出一个IOError错误,并且给出错误码和详细的信息告诉你文件不存在:

>>>f = open("user/michael/notfound.txt", "r")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
FileNotFoundError: [Errno 2] No such file or directory: 'user/michael/notfound.txt'

文件模式
open函数打开中的mode参数,通过改变mode参数可以实现对文件的不同操作

功能描述
'r' 读模式
'w' 写模式
'a' 追加模式
'b' 二进制模式(可添加到其它模式中使用)
'+' 读/写模式(可添加到其它模式中使用)

一般处理文本文件时,是用不到'b'参数的,但如果处理其它类型的文件(二进制文件),比如mp3或者图形,就应该在模式中加上'b',这在爬虫中处理媒体文件很常用。

文件缓冲区
open函数中第三个可选参数buffering控制着文件的缓冲。如果参数是0,I/O操作就是无缓冲的,直接将数据写到硬盘上;如果参数是1,I/O操作就是有缓冲的,数据先写入到内存里,只有使用flush函数或者close函数才会将数据更新到硬盘;如果参数大于1的数据则代表着缓冲区的大小(单位是字节),-1(或者任何负数)代表使用默认缓冲区的大小。

文件读取
文件读取主要分为按字节读取和按行读取,经常用到的方法有read()readline()readlines()close()

>>>f = open(r"c:\\text\\xiaoqi.txt", "r")
>>>f.read()   #调用read()方法可以一次性地将文件内容全部读到内存中
'xiaoqi'
f.close()  #文件读取完成后必须关闭

由于文件操作可能会出现IO异常,一旦出现IO异常,后面的close()
方法就不会调用。所以为了保证程序的健壮性,我们需要使用try...finally来实现。

try
    f = open(r'c:\\text\\xiaoqi.txt')
    print(f.read())
finally:
    if f:
        f.close()

Python提供了一种更加简单有趣的写法,使用with语句来替代try...finally代码块和close()方法

with open(r'c:\text\xiaoqi.txt') as fileReader:
    print(fileReader.read())

利用read()一次将文件内容读到内存,但是如果文件过大,将会出现内存不足的问题。一般对于大文件,可以重复调用read(size)方法,一次最多读取size个字节。如果文件是文本文件,Python提供了更加合理的做法,调用了readline()可以每次读取一行内容,调用readlines()一次读取所有内容并按行返回列表。大家可以根据自己的具体需求采取不同的读取方式:

  1. 小文件可以直接采取read()方法读到内存;
  2. 大文件更加安全的方法是连续调用read(size);
  3. 面对于配置文件等文本文件,使用readlines()方法更加合理
with open(r'c:\\text\\ss.txt') as fileReader:
    for line in fileReader.readlines():
        print(line.strip())

文件写入
写文件和读文件是一样的,唯一的区别实在调用open方法时,传入标识符w或者wb表示写入文本文件或者写入二进制文件,示例如下:

f = open(r'c:\text\qie.txt', 'w')
f.write('xiaoqi')
f.close()

我们可以反复调用write()方法写入文件,最后必须使用close()方法来关闭文件。使用write()方法的时候,操作系统不是立即将数据写入文件中的,而是先写入内存中缓存起来,等到空闲时候再写入文件中,最后使用close()方法就将数据完整地写入文件中了。当然也可以使用f.flush()方法,不断地将数据立即写入文件中,最后使用close()方法来关闭文件。和读文件同样道理,文件操作中可能会出现IO异常,所以还是推荐使用with语句:

with open(r'c:\text\csd.txt', 'w') as fileWriter:
    fileWriter.write('sdfs')

file-like Object

open()函数返回的这种有个read()方法的对象,在Python中统称为file-like Object,除了file外,还可以是内存的字节流,网路流,自定义流等。file-like Object不要求从特定类继承,只要写个read()方法就行。
StringIO就是内存中创建的file-like Object,常用作临时缓冲。

二进制文件
一般我们用open()读取的是文本文件,并且是UTF-8编码的文本文件。要读取二进制文件,比如图片、视频,就需要用rb模式打开文件:

f = open("/Users/michael/test.jpg", 'rb')
f.read()
b'\xff\xd8\xff\xe1\x00\x18Exif\x00\x00...' # 十六进制表示的字节

字符编码
要读取非UTF-8编码的文本文件,需要给open()函数传入encoding参数,例如,读取GBK编码的文件:

f = open("/Users/michael/gbk.text", "r", encoding="gbk")
f.read()
'测试'

遇到有些编码不规范的文件,你可能会遇到UnicodeDecodeError,因为在文本文件中可能夹杂了一些非法编码的字符。遇到这种情况,open()函数还接收一个errors参数,表示如果遇到编码错误后如何处理。最简单的方式是直接忽略:

f = open('/Users/michael/gbk.txt', 'r', encoding='gbk', errors='ignore')

StringIO
很多时候,数据读写并不一定是文件也可以在内幕才能中读写。
StringIO顾名思义就是在内存中读写str。
要把str写入StringIO,我们需要先创建一个StringIO,然后,像文件一样写入即可:

>>>from io import StringIO
>>>f = StringIO()
>>>f.write('hello')
5
>>>f.write(" ")
1
>>>f.write("world!")
6
>>>print(f.getvalue())   #getvalue()方法用于获得写入后的str
'hello world!'

要读取StringIO,可以用一个str初始哈StringIO,然后,像读文件一样读取:

>>>from io import StringIO
>>>f = StringIO("Hello!\nGoodbye!")
>>>while True:
    s = f.readline()
    if s == " ":
        break
    print(s.strip())
Hello!
Hi!
Goodbye

BytesIO
StringIO操作的只能是str,如果要操作二进制数据,就需要使用ByetsIO.
BytesIO实现了在内存中读写bytes,我们创建了一个BytesIO,然后写入一些bytes

>>>from io import BytesIO
>>>f = BytesIO()
>>>f.write('中文'.encode("utf-8"))
6
>>>print(f.getvalues)
b'\xe4\xb8\xad\xe6\x96\x87'

注意:写入的不是str,而是经过UTF-8编码的bytes。
和StringIO类似,可以用一个bytes初始化BytesIO,然后,像读文件一样读取:

>>>from io import BytesIO
>>>f = BytesIO(b'\xe4\xb8\xad\xa6\x96\x87')
>>>f.read()
b'\xe4\xb8\xad\xe6\x96\x87'

参考

  1. 廖雪峰-IO编程
  2. Python学习记录之:IO编程
  3. Python中的str与unicode处理方法
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容

  • 文件读写 读写文件是最常见的IO操作。Python内置了读写文件的函数,用法和C是兼容的。由于文件读写时都有可能产...
    时间之友阅读 429评论 0 0
  • pyton review 学习指南 https://www.zhihu.com/question/29138020...
    孙小二wuk阅读 1,015评论 0 2
  • IO编程概念 IO在计算机中指Input/Output,也就是输入和输出。由于程序和运行时数据是在内存中驻留,由C...
    时间之友阅读 706评论 0 0
  • 文件读写 读文件由于文件读写时都有可能产生IOError,一旦出错,后面的f.close()就不会调用。所以,为了...
    carolwhite阅读 159评论 0 0
  • 我们看书,总是从一本书的最高境界来欣赏和品评。我们使用绳子,总是从最薄弱的一段来断定绳子的质量。坐冷板凳的书呆子,...
    风中的半只烟阅读 82评论 0 0