学习笔记

0210-文件操作

Posted on 2022-02-10,8 min read
封面图

IO编程

本章主要讲同步IO,异步IO太复杂,后续涉及到服务端再讲.

文件读写

读文件
open() 函数, f.close() 关闭文件;
调用read()会一次性读取文件的全部内容, read(size)读取size个字符/字节的内容.
readline()可以每次读取一行内容,调用readlines()一次读取所有内容并按行返回list

>>> with open('ABC.txt', 'r') as fname :
>>> 		str = fname.read()
>>> f = open('/Users/michael/test.jpg', 'rb') #以二进制打开, 打开文本可以用decode解码为字符串
>>> f.read()
b'\xff\xd8\xff\xe1\x00\x18Exif\x00\x00...' # 十六进制表示的字节
for line in f.readlines():
    print(line.strip()) # strip参数为空,把末尾的'\n'或空格删掉

写文件
调用open()函数时,传入标识符'w'或者'wb'表示写文本文件或写二进制文件:新建或删除存在的内容.
追加内容用标识符:a.
StringIO和BytesIO

  • tell 方法获取当前文件读取指针的位置
  • seek 方法,用于移动文件读写指针到指定位置,有两个参数,第一个offset: 偏移量,需要向前或向后的字节数,正为向后,负为向前;第二个whence: 可选值,默认为0,表示文件开头1表示相对于当前的位置,2表示文件末尾
  • seek方法时,需注意,如果你打开的文件没有用'b'的方式打开,则offset无法使用负值
# stringIO 比如说,这时候,你需要对获取到的数据进行操作,但是你并不想把数据写到本地硬盘上,这时候你就可以用stringIO
from io import StringIO
from io import BytesIO
def outputstring():
    return 'string \nfrom \noutputstring \nfunction'

s = outputstring()

# 将函数返回的数据在内存中读
sio = StringIO(s)
# 可以用StringIO本身的方法
print(sio.getvalue())
# 也可以用file-like object的方法
s = sio.readlines()
for i in s:
    print(i.strip())


# 将函数返回的数据在内存中写
sio = StringIO()
sio.write(s)
# 可以用StringIO本身的方法查看
s=sio.getvalue()
print(s)

# 如果你用file-like object的方法查看的时候,你会发现数据为空
sio = StringIO()
sio.write(s)
for i in sio.readlines():
    print(i.strip())

# 这时候我们需要修改下文件的指针位置
# 我们发现可以打印出内容了
sio = StringIO()
sio.write(s)
sio.seek(0,0)
print(sio.tell())
for i in sio.readlines():
    print(i.strip())

# 上面涉及到了两个方法seek 和 tell

# stringIO 只能操作str,如果要操作二进制数据,就需要用到BytesIO
# 上面的sio无法用seek从当前位置向前移动,这时候,我们用'b'的方式写入数据,就可以向前移动了
bio = BytesIO()
bio.write(s.encode('utf-8'))
print(bio.getvalue())
bio.seek(-36,1)
print(bio.tell())
for i in bio.readlines():
    print(i.strip())

操作文件与目录

os.chdir(file_path)
进入file_path路径;
os.path.abspath('.')
当前位置的绝对路径
os.path.join(pwd,x)
合并路径
os.listdir(pwd)
列出当前路径所有文件及目录(不包括子目录)
os.path.isfile(os.path.join(pwd,x))
判断括号内的路径是否为文件
os.path.isdir(os.path.join(pwd,x))
判断括号内的路径是否为目录
shutil模块提供了copyfile()的函数

>>> os.path.split('/Users/michael/testdir/file.txt')
('/Users/michael/testdir', 'file.txt')
>>> os.path.splitext('/path/to/file.txt') #获得文件拓展名
('/path/to/file', '.txt')

查找当前目录及子目录的指定文件名:

import os

def findfile(s, file_path):
    #进入当前目录
    os.chdir(file_path)
    #查找当前目录包含输入字符串的文件
    L = [x for x in os.listdir('.') if os.path.isfile(x)]
    for x in L:
        #查找是否包含s,包含返回开始s的下标,不包含返回-1
        if x.find(s)!=-1:
            print(os.path.join(file_path,x))
        else:
            pass
    #查找各目录中是否包含输入字符串的文件
    Y = [x for x in os.listdir('.') if os.path.isdir(x)]
    for x in Y:
        file_path2=os.path.join(file_path,x)
        findfile(s,file_path2)

def main():
    #path = input('请输入绝对路径:')
    path = os.path.abspath('.')
    s = input('请输入要查找的字符串:')
    result = findfile(s, path)
    if result == None :
        print ('没找到或查找结束!')

if __name__ == '__main__':
    main()

序列化

pickle
pickle.dumps()方法把任意对象序列化成一个bytes;
pickle.loads()方法反序列化出对象;
pickle.dump()直接把对象序列化后写入一个file-like Object即写入文件;
pickle.load()方法从一个file-like Object中直接反序列化出对象.

>>> import pickle
>>> d = dict(name='Bob', age=20, score=88)
>>> pickle.dumps(d)
b'\x80\x03}q\x00(X\x03\x00\x00\x00ageq\x01K\x14X\x05\x00\x00\x00scoreq\x02KXX\x04\x00\x00\x00nameq\x03X\x03\x00\x00\x00Bobq\x04u.'
>>> f = open('dump.txt', 'wb')
>>> pickle.dump(d, f)
>>> f.close()
>>> f = open('dump.txt', 'rb')
>>> d = pickle.load(f)
>>> f.close()
>>> d
{'age': 20, 'score': 88, 'name': 'Bob'}

JSON

JSON类型 Python类型
{} dict
[] list
"string" str
1234.56 int或float
true/false True/False
null None

json模块,dumps()方法返回一个str,内容就是标准的JSON;类似的,dump()方法可以直接把JSON写入一个file-like Object

>>> import json
>>> d = dict(name='Bob', age=20, score=88)
>>> json.dumps(d)
'{"age": 20, "score": 88, "name": "Bob"}'
>>> json_str = '{"age": 20, "score": 88, "name": "Bob"}'
>>> json.loads(json_str)
{'age': 20, 'score': 88, 'name': 'Bob'}

class 转为json对象:
dumps()方法的default参数可以定义将class转为dict的函数;

import json

class Student(object):
    def __init__(self, name, age, score):
        self.name = name
        self.age = age
        self.score = score
s = Student('Bob', 20, 88)

def student2dict(std):
    return {
        'name': std.name,
        'age': std.age,
        'score': std.score
    }
>>> print(json.dumps(s, default=student2dict))
{"age": 20, "name": "Bob", "score": 88}

通常class的实例都有一个__dict__属性,它就是一个dict,用来存储实例变量; 少数例外,比如定义了__slots__class

print(json.dumps(s, default=lambda obj: obj.__dict__))

object_hook函数负责把dict转换为Student实例:

def dict2student(d):
    return Student(d['name'], d['age'], d['score'])

>>> json_str = '{"age": 20, "score": 88, "name": "Bob"}'
>>> print(json.loads(json_str, object_hook=dict2student))
<__main__.Student object at 0x10cd3c190>

下一篇: 0209-对象高级编程-错误测试→

loading...