文件操作
文件操作
open方法操作文件的三要素
open('filedown', mode='r', encoding='utf-8')
1.文件路径
2.编码方式
3.操作方式:只读,只写,追加,读写,写读。。。
mode='r' / ‘w’ / 'a' 只读/只写/追加 字符形式
'r+' / ‘w+’ / 'a+' 读写/写读/可追加可读 字符形式
rb' / ‘wb’ / 'ab' 只读/只写/追加 字节形式
'r+b' / ‘w+b’ / 'a+b' 读写/写读/可追加可读 字节形式
文件内容的读取
按字符形式读取文件内容.只读模式mode='r'(默认操作方式)
f = open('filedown', mode='r', encoding='utf-8')
contents = f.read() #一次读取所有内容
print(type(contents))#<class 'str'> 读取的类型是字符串
print(contents)
f.close() #文件对象操作完毕后需要关闭
#open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
#打开一个文件,并返回文件对象
'''
file:(当前相对路径下)文件名(文件名.后缀)或绝对路径的文件地址(例如d:\a.txt),这是必须的
文件不存在会保报错
mode:操作方式,默认是只读 , r ,可以不写
encoding: 编码方式,默认utf-8
buffering: 设置缓冲
errors: 报错级别
newline: 区分换行符
closefd: 传入的file参数类型
在硬盘存储的文件的编码方式与open方法的encoding编码不同时,会报错(在绝对路径下会出现的问题)
在相对路径下,文件编码有编辑器统一,encoding='utf-8'或encoding='ansi'都能读取同一个文件
'''
按字节形式读取文件内容,mode='rb',
f = open('filedown', mode='rb')
contents = f.read()
print(type(contents))#<class 'bytes'> 读取的类型是字节
print(contents)
f.close()
'''
rb模式下,不接受encoding参数等部分参数
读取的文件都是bytes类型数据
b'\xe5\x88\x98\xe4\xb8\x80'
适合文件的上传,下载,传输
'''
文件内容的写入
按字符写入,只写模式,mode='w',可设置编码
#只写
f = open('files', mode='w',encoding = 'utf-8')
leng = f.write('''hello
world
''')#返回写入数据的字符个数,可以不接收
print(leng)
f.close()
#找到files文件,没有这个文件就创建这个文件,编辑工具可能无法显示创建的这个文件
#可以切换视图类型或去本地实际的储存路径下查看
#如果当前文件已有内容,清空文件内容再写入(这个方法能清空文件所有内容)
按字节写入,mode='wb',适合上传,下载,数据传输
f = open('files', mode='wb')#以bytes类型写入文件
f.write('hellworld'.encode('utf-8'))
f.close()
'''mode='wb'需要的是bytes类型
'hellworld'.encode('utf-8') 传入的是str类型数据需要转为bytes类型
str——>bytes : str.encode('utf-8')
bytes ——> str: bytes.decode('utf-8')
以这种方式写入一样会清空文件内容再写入
'''
字符与字节间的转换
str——>bytes : str.encode('utf-8') 将字符编码为字节
bytes ——> str: bytes.decode('utf-8') 将字节解码为字符
文件内容的追加
按字符追加,追加模式 mode = ' a '
#追加
f = open('files',mode='a',encoding='utf-8')
f.write('三思而行')
f.close()
'''
在文本末尾追加
'''
按字节追加 mode = ' ab '
#以bytes类型追加
f = open('files',mode='ab')
f.write('三思而行'.encode('utf-8'))
f.close()
文件内容的读写
按字符读写,读写模式 mode = ' r+ ' (常用)
#读写r+
f = open('files',mode='r+',encoding='utf-8')
print(f.read())
f.write('sadhjhf')
print(f.read())
f.close()
'''
先进行读,再进行写,后续写入的内容无法读取
因为当前文件原有的内容读取后,文件光标停在文件内容的末尾,所以写入的内容在光标处写入
即在文件末尾添加新写入的内容,不会清空原内容,光标停在新写入内容的末尾
再次读取时,光标向下读取,此时光标在文件末尾没有内容可以读取,所以没有内容
如果先写后读,写入文件时光标在文件首位,写入的字符会自动覆盖原先的内容,所以先读取将光标移至内容末尾再将新写入的内容传入
'''
按字节读写模式 mode = ' r+b'
#读写r+b
f = open('files',mode='r+b')
f.read()
f.write('时间及时真理'.encode('utf-8'))
f.close()
文件内容的写读
按字符写读,写读模式 mode = 'w+'
按字节写读,写读模式 mode = 'wb+'
#写读 w+
f = open('files',mode='w+',encoding='utf-8')
f.write('wanwuguiyi ')
print(f.read())#无输出
f.close()
'''
先清空文件内容再写入
此时光标在文件末尾,所以read()读取的内容为空
调整文件光标的位置 来获取输出
f.seek(0)将光标调至文件首位
print(f.read())
f.close()
'''
文件内容的追加读
按字符写入,可追加可读 mode = 'a+'
按字节写入,可追加可读 mode = 'ab+'
f = open('files',mode='a+',encoding='utf-8')
f.write('挖掘和客户机 ')
f.seek(0)#设置文件的光标
print(f.read())
f.close()
JSON格式对象的读写
json是一种数据的定义格式
广泛的应用于跨平台跨语言的数据交换
import json
def main():
mydict = {
'name': '张三',
'age': 23,
'qq': 123456,
'friend': [
{'name': '李四', 'age': 24},
{'name': '王五', 'age': 25},
{'name': '赵六', 'age': 26}
]
}
try:
with open('data.json', 'w', encoding='utf-8') as fs:
json.dump(mydict, fs)#将Python对象按照JSON格式序列化到文件中
#load() - 将文件中的JSON数据反序列化成对象
except IOError as e:
print(e)
print('保存数据完成!')
def readjson():
try:
with open('data.json', 'r', encoding='utf-8') as f:
files = json.load(f)#将读取文件中发json形式的对象后输出
print(files)
except IOError as e:
print(e)
print('读取数据完成!')
if __name__ == '__main__':
# main()
readjson()
读取未知编码文件
'''
https://pypi.org/project/chardet/ 下载chardet模块chardet-3.0.4.tar.gz
解压文件夹chardet-3.0.4中有一个chardet文件夹
复制粘贴至Python\Python37\Lib\site-packages下即可引用
chardet模块 识别数据的编码方式
'''
import chardet
#name = '小猫'.encode() #将字符编译为字节
#print(chardet.detect(name)) #需要一个字节参数,判断字节数据的编码
#{'encoding': 'utf-8', 'confidence': 0.7525, 'language': ''}
#返回一个字典数据,判断编码为utf-8,几率大致是0.7525
#读取未知编码文件
with open(r'test.txt','rb') as f:#以字节形式读取文件
date = f.read()
ret= chardet.detect(date)#读取文件编码
print(ret)
date = date.decode(ret['encoding'])#将字节以文件编码格式解码为字符串
#对于记事本的ansi格式编码无法解读
#date = date.decode('ansi')
print(date)
字符串与字节类型在内存占用的大小
import sys
st = '你好'
print(type(st))#<class 'str'>
print(sys.getsizeof(st))#78
s = bytes(st,encoding='utf-8')
print(type(s))#<class 'bytes'>
print(sys.getsizeof(s))#39
判断文件是否可读
f = open('files')
if f.readable():#判断文件时可读 True/False
print(f.read())
f.close()
设置文件光标位置
f = open('files')
print(f.read())
f.seek(0)#设置文件光标位置到首位
f.tell()#获取文件当前光标位置,返回int值,可用于断点续传
f.seek(f.tell())
读取文件相关操作
f = open('test.txt', 'r', encoding='utf-8')
ret = f.readline() #读取文本中一行数据,一次一行
f.seek(0) #重置文件的光标到首位
re = f.readlines()#读取文本所有数据,每一行作为一个列表元素,元素末尾会有\n
#['落叶随风将要去何方\n', '只留给天空美丽一场\n', '曾飞舞的声音\n', '像天使的翅膀\n']
f.seek(0) #重置文件的光标到首位
'''取出元素末尾\n
re = f.readlines()#读取文本所有数据,每一行作为一个列表元素
li = []
for i in re :
s = i.split('\n')[0]
li.append(s)
print(li)
'''
count = len(f.readlines()) #获取文件的行数
f.seek(0) #重置文件的光标到首位
f.truncate(n) #截取文件中当前节点后n个字符,会清空文件内容再写入n个字符
一次读取所有文件内容
with open('song.txt', 'r', encoding='utf-8') as f:
ret = f.read()
print(ret)
一次读取一行文件的内容
with open('song.txt', 'r', encoding='utf-8') as f:
ret = f.readline()
print(ret)
逐行输入文件的内容
1.通过for循环遍历文件对象
2.通过文件对象的readlines()方法将每一行作为列表元素存入列表中
with open('song.txt', 'r', encoding='utf-8') as f:
for ret in f:
print(ret)
# 这种方式输出的每一行数据都有两个换行符,一个来自文件的每一行末尾的换行符,一个来自print函数的换行符
# 可以使用字符串的rstrip方法来清除多余的空白行
with open('song.txt', 'r', encoding='utf-8') as f:
for ret in f:
print(ret.rstrip())
# 通过文件对象的readlines()方法将每一行作为列表元素存入列表中后输出
with open('song.txt', 'r', encoding='utf-8') as f:
ret = f.readlines()
for i in ret:
print(i.rstrip())
with和as
with open(...) as 别名:
1.这种方法可以打开多个文件
2.可以给文件对象起别名
3.不用写f.close(),自动关闭
这是文件操作的常用方式
with open('files1') as f,open('files2') as f2:
pass
# 一次性读取整个文件内容
with open('test.txt', 'r', encoding='utf-8') as f:#常用方式
print(f.read())
# 通过for-in循环逐行读取
with open('test.txt', mode='r') as f:
for line in f:
print(line, end='')
print()
lines =[]
# 读取文件按行读取到列表中
with open('test.txt') as f:
lines = f.readlines()
print(lines)
文件操作总结:
视频,图片等文件用bytes类型读写,即mode='rb',按字节读
read() ,readlines()一次性读取所有内容
readline()一行一行读,缺点是不确定光标位置
读文件最好是使用for循环
str类型数据一般是unicode编码,不便传输,所以需要转为bytes类型
str与bytes用法一致,仅在于编码不同
bytes更利于传输