七IO编程

Posted blogbo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了七IO编程相关的知识,希望对你有一定的参考价值。

  IO指input、output(输入、输出),由于程序在运行时数据是在内存驻留,由cpu这个超快的计算核心来执行,涉及到数据交换的地方,通常就是磁盘、网络等,需要IO接口

  浏览器访问新浪首页:浏览器程序通过网络IO获取新浪网页

            1)浏览器--(发送数据)--》新浪服务器(告诉想要的html,这个动作是往外发数据,output)

            2)新浪服务器把网页发过来,这个动作是从外面接受数据(input)

  所以,通常程序完成IO操作会有input和output两个数据流,当然也只有一个的情况,input:磁盘读取文件到内存,output:数据写到磁盘中

  cpu和内存的速度远远高于外设的速度

  同步IO:cup等待,即程序暂停执行后续代码,等待了之后再往下执行

  异步IO:cpu不等待,去做别的事情,但是异步IO的编程模型复杂,包括会回调模式(等别人来找)和轮询模式(自己不断检查)

 

  1.文件读写

  计算机系统分为:计算机硬件、操作系统、应用程序

  操作系统把复杂的硬件操作封装成简单的接口给用户/应用程序使用,用户或应用程序通过操作文件,将自己的数据永久保存下来

  操作文件流程:

  1)打开文件,得到文件句柄并赋值给一个变量

f = open(a.txt, r, encoding = utf-8)
f = open(C:/Users/michael/a.txt,r)
#结果:‘hello,world‘

  2)通过句柄对文件进行操作

data = f.read()

  3)关闭文件

f.close()

  关闭文件的注意事项

  关闭文件包含两部分资源:操作系统打开的文件+应用程序的变量,在操作完毕一个文件时,必须把该文件的这两个资源一个不落的回收,回收方法为:

1.f.close() #回收操作系统级打开的文件
2.del f #回收应用程序级的变量

  其中,del f一定要发生在f.close()之后,否则就会导致操作系统打开的文件还没有关闭,白白占用资源,而python自动的垃圾回收机制决定了无需考虑del f,但

是必须要f.close()

  文件编码:f = open(...)是由操作系统打开文件,操作系统会用自己默认的编码去打开文件,在windows下是gdk,linux下是utf-8,所以要制定编码

  文件的打开模式:文件句柄 = open(‘文件路径’, ‘模式‘)

  ‘r‘        open for reading ,读

  ‘w‘         open for writing,truncating the file first,写

  ‘a‘        open for writing,appending to the end of the file if it exists,在后面添加

  ‘b‘        binary mode,二进制模式

  ‘t‘         text mode(default),文本模式

  ‘u‘        universal newline mode(for backwards compatibility;should not be used in new code)

  打开文件的模式有(默认为文本模式):

  r:只读模式(默认模式,文件必须存在,不存在则抛出异常)

  w:只写模式(不可读:不存在则创建,存在则清空内容

  a:之追加写模式(不可读:不存在则创建,存在则只追加内容)

  对于非文本文件,我们只能使用‘b‘模式,’b‘表示以字节的方式操作(而所有文件也都是以字节的形式存储的,使用这种模式无需考虑文本文件的字符编码,图

片文件的jpg文件,视频文件的avi格式)

  rb    

  wb

  ab

  注:以b方式打开时,读取到的内容是字节类型,写入时也需要提供字节类型,不能指定编码

  ‘+’表示可以同时读写某文件

  r+  读写(可读,可写)

  w+  写读(可读,可写)

  a+  写读(可读,可写)

  x  只写模式(不可读,不存在则创建,存在则报错)

  x+  写读(可读,可写)

  由于历史的原因,换行符在不同的系统中有不同的模式,比如在linux中是一个 ,而在windows中是‘ ’,用u模式打开文件,就是支持所有的换行模式,也就说‘ ’ ‘ ’ ‘ ’都可表示换行

  t是windows平台特有的所谓text mode(文本模式),区别在于会自动识别windows平台的换行符

  

  文件内的光标移动

  read(3):文件打开方式为文本模式时,代表读取3个字符

      文件打开方式为b模式时,代表读取3个字节

  其余的文件内光标移动都是以字节为单位如seek,tell,truncate

  注意:seek有三种移动方式0,1,2,其中1和2必须在b模式下进行,但无论哪种模式,都是以bytes为单位移动的

     truncate是截断文件,所以文件的打开方式必须可写,但是不能用w或w+等方式打开,因为那样直接清空文件了,所以truncate要在r+或a或a+等模式下测试效果

 

  二进制文件

  调用read()时一次性读取文件的全部内容,可以反复调用read(size)每次最多读取size个字节的内容,另外,调用readline()可以每次读取一行内容,调用

readlines()一次读取所有内容并返回list,因此,要根据需要决定怎么调用

  如果文件很小,read()一次性读取最方便,如果不能确定文件大小,反复调用read(size)最保险,如果是配置文件,调用readlines()最方便

f = open(‘C:/Users/Administrator/Desktop/a.txt‘,‘r‘,encoding = ‘gbk‘)
for
line in f.readlines(): print(line.strip()) #把末尾的‘ ‘删掉 #把每行的结果读出来

  前面讲的默认都是读取文本文件,并且是UTF-8编码的文本文件,要读取二进制文件,比如图片视频等,用‘rb‘模式打开文件即可

f = open(C:/Users/Administrator/Desktop/test.jpg,rb) #二进制模式
f.read()
#结果:b‘xffxd8xffxe1x00x18Exifx00x00...‘ # 十六进制表示的字节
f.close()

 

  字符编码

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

f = open(C:/Users/Administrator/Desktop/a.txt,r,encoding = gbk)
f.read()

  遇到有些编码不规范的文件,错误为UnicodeDecodeError,因为在文本文件中可能夹杂了一些非法编码的字符,遇到这种情况,open()函数还接受一个errors参

数,表示如果遇到编码错误后如何处理,最简单的方式是直接忽略

f = open(C:/Users/Administrator/Desktop/a.txt,r,encoding = gbk,errors=ignore)

 

  写文件

  读写文件是一样的,唯一区别是open()函数时,传入标识符‘w‘或者‘wb‘表示写文件文本或二进制文本

f = open(C:/Users/Administrator/Desktop/a.txt,w)
f.write(dududud)
f.close()

  可以反复调用write()来写入文件,但是务必要调用f.close()来关闭文件,当我们写文件时,操作系统往往不会立刻把数据写入磁盘,而是放在内存缓存起来,空

闲的时候在慢慢写入,只有调用close()方法时,操作系统才保证把没有写入的数据全部写入磁盘,忘记调用close()的后果是数据可能只写了一部分到磁盘,剩下的

丢失了,所以最好用with

with open(C:/Users/Administrator/Desktop/a.txt,w) as f:
f.write(aaaaaaa)

  要写入特定编码的文本文件,给open()函数传入encoding参数,将字符串自动转换成指定编码

  有一个问题,当以‘w‘模式写入文件时,如果文件已存在,会直接覆盖(相当于删掉后新写入一个文件),如果希望追加在文件末尾,需要传入‘a‘

with open(C:/Users/Administrator/Desktop/a.txt,a) as f:
f.write(
bbbbbbb) #换行添加

  

  with上下文管理

  会有忘记f.close()的情况,因为文件读写时都有可能产生IOError,一旦出错,后面的f.close()就不会调用,所以,为了保证无论是否出错都能正确的关闭文件,推荐傻瓜式操作方式,使用with关键字来管理上下文

with open(a.txt,w) as f:
    pass
with open(a.txt,r) as read_f,open(b.txt,w) as write_f:
    data = read_f.read()
    write_f.write(data)

  

  文件的修改

  文件的数据是存放在硬盘上的,因而只存在覆盖、不存在修改这么一说,我们平时看到的修改文件,都是模拟出来的效果,具体的说有两种实现方式:

  方式一:将硬盘存放的该文件内容全部加载到内存,在内存中是可以修改的,修改完毕中,在由内存覆盖到硬盘(word,vim,nodpad++等编辑器)

import os 
with open(C:/Users/Administrator/Desktop/a.txt,encoding = gbk) as read_f,open(C:/Users/Administrator/Desktop/b.txt,w) as write_f: 
  data = read_f.read() #全部读入内存,如果文件很大,会很卡,读入到了data文件中 
  data = data.replace(alex,SB) #在内存中完成修改,将data文件中的alex换成了SB 
  write_f.write(data) #一次性写入新文件,把a文件数据写入到了文件b中

os.remove(C:/Users/Administrator/Desktop/a.txt) #移除a.txt   
os.rename(C:/Users/Administrator/Desktop/a.txt,C:/Users/Administrator/Desktop/b.txt) #把b.txt重新命名为了a.txt

#目录撇,转义捺

  方法二:将硬盘存放的该文件的内容一行一行读入内存,修改完毕就写入新文件,最后用新文件覆盖原文件(适用于小文件)

import os
with open(a.txt) as read_f,open(.a.txt.swap,w) as write_f:
    for line in read_f:
        line = line.replace(alex,SB)
        write_f.write(line)
os.remove(a.txt)
os.rename(.a.txt.swap,a.txt)

 

  2.StringIo和BytesIO 

  StingIO

  很多时候,数据读写不一定是文件,也可以在内存中读写

  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())
#hello world!

  getvalue()用于获得写入后的str

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

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

  

  ByteslO

  StringIO操作的只能是str,如果是操作二进制数据,就需要使用BytesIO

  BytesIO实现了在内存中读写bytes,我们创建一个BysteIO,然后写入一些bytes:

from io import BytesIO
f = BytesIO()
f.write(中文.encode(utf-8))
print(f.getvalue())
b‘xe4xb8xadxe6x96x87‘

  请注意,写入的不是str,而是经过UTF-8编码的bytes

  和StringIO类似,可以用一个bytes初始化BytesIO,然后,像读文件一样读取

from io import BytesIO
f = BytesIO(bxe4xb8xadxe6x96x87)
f.read()
b‘xe4xb8xadxe6x96x87‘

  StingIO和BytesIO是在内存中操作str和bytes的方法,使得和读写文件具有一致的接口

 

  3.操作文件和目录

  如果我们要操作文件、目录,可以在命令行下面输入操作系统提供的各种命令来完成,如dir、cp等命令

  python内置的os模块可以直接调用操作系统提供的接口函数

import os
os.name #操作系统

  如果是posix,说明系统是linux,unix或Mac OS X,如果是nt,就是Windows系统

  

  环境变量

  在操作系统中定义的环境变量,全部保存在os.environ这个变量中,可以直接查看,直接调用os.environ

  要获取某个环境变量的值,可以调用os.environ.get(‘key‘)

 

  操作文件和目录

  操作文件和目录的函数一部分放在os模块中,一部分放在os.path模块中,查看、创建、删除目录可以这么调用:

# 查看当前目录的绝对路径:
os.path.abspath(.)
/Users/michael
# 在某个目录下创建一个新目录,首先把新目录的完整路径表示出来:
os.path.join(/Users/michael,testdir)
/Users/michael/testdir
# 然后创建一个目录:
os.mkdir(/Users/michael/testdir)
# 删掉一个目录:
os.rmdir(/Users/michael/testdir)

#对文件重命名
os.rename(test.txt,test.py)

#删除文件
os.remove(test.py)

  

  4.序列化

  序列化:变量从内存中—》可存储或传输的过程,在python中叫pickling,在其他语言中被称之为serialization,marshalling,flattening等等,都是一个意思

  序列化之后,可以把序列化后的内容—》写入磁盘,或者通过网络传输到别的机器上

  反序列化,把变量内容从序列化的对象重新读到内存中,unpickling

  对象序列化并写入文件,pickle.dumps()方法把任意对象序列化成一个bytes,然后,就可以把这个bytes写入文件

import pickle
d = dict(name = Bob, age = 20, score =88)
pickle.dumps(d)

  pickle.dumps()方法把任意对象序列化成一个bytes,然后,就可以把这个bytes写入文件,或者用另一个方法pickle.dump()直接把对象序列化后写入一个file-like Object

f = open(dump.txt,wb)
pickle.dump(d,f)
f.close()

  把对象从磁盘读到内存时,可以先把内容读到一个bytes,然后用pickle.loads()方法反序列化出对象,也可以直接用pickle.load方法从一个file-like object中直接反序列化出对象

f = open(dump.txt,rb)
d.pickle.load(f)
f.close()
d

  尝试把一个对象序列化并写入文件

import pickle
d = {name:Bob,a:20,s:88}
pickle.dumps(d)
#b‘x80x03}qx00(Xx06x00x00x00dididiqx01Xx03x00x00x00Bobqx02c__main__
f2
qx03)x81qx04Xx02x00x00x0020qx05Xx00x00x00x00qx06Xx02x00x00x0088qx07u.‘

  pickle.dumps()方法把任意对象序列化成一个bytes,然后,就可以把这个bytes写入文件,或者用另一个方法pickle.dump()直接把对象序列化后写入一个file-like Object

f = open(dump.txt,wb)
pickle.dump(d,f)
f.close()

  把对象从磁盘读到内存时,可以先把内容读到一个bytes,然后用pickle.loads()方法反序列化出对象,也可以直接用pickle.load方法从一个file-like object中直接反序列化出对象

f = open(dump.txt,rb)
d.pickle.load(f)
f.close()
d

  JSON序列化

import json
d = dict(name=Bob, age=20, score=88)
json.dumps(d)
#‘{"age": 20, "score": 88, "name": "Bob"}‘

  JSON反序列化

json_str = {"age": 20, "score": 88, "name": "Bob"}
json.loads(json_str)
#{‘age‘: 20, ‘score‘: 88, ‘name‘: ‘Bob‘}

 

 

  

 

 

 

  

  

以上是关于七IO编程的主要内容,如果未能解决你的问题,请参考以下文章

golang代码片段(摘抄)

java内存流:java.io.ByteArrayInputStreamjava.io.ByteArrayOutputStreamjava.io.CharArrayReaderjava.io(代码片段

并发编程之IO模型

java缓冲字符字节输入输出流:java.io.BufferedReaderjava.io.BufferedWriterjava.io.BufferedInputStreamjava.io.(代码片段

python并发编程之IO模型

VSCode自定义代码片段——JS中的面向对象编程