Python_学习之文件操做
1、初识⽂文件操做
2、读写操做
3、文件的操做顺序
4、模式介绍
5、示例html
1、初识⽂文件操做
python来读写文件是用open()函数来打开一个⽂文件, 获取到⽂文件句句柄. 而后经过文件句柄就能够进行各类各样的操做了. 根据打开方式的不一样可以执行的操 做也会有相应的差别. python
打开文件的方式: r, w, a, r+, w+, a+, rb, wb, ab, r+b, w+b, a+b默认使⽤用的是r(只读)模式数据库
绝对路劲:从根目录到当前位置如:c:\install\file.txt
相对路劲:同一个文件夹的文件相对于当前程序所在的文件夹而言 ..\表示当前位置的上级目录 (经常使用)缓存
print(__file__) 获取当前文件的路径
2、读写操做
默认读模式只能读文件,不能作写操做,写模式只能写文件,不能读文件,除非使用(+)加模式app
3、文件的操做顺序
一、找到文件,打开做业,指定模式,根据文件保存时的编码来指定编码格式 :open(“path\file” , moth = “r/w/r+等”, encoding = “以什么编码格式显示文件内容”)ide
二、根据对应模式所拥有的方法操做文件: f.read()等其它操做函数
三、关闭文件 :f.close()学习
4、模式介绍
一、只读(r,rb)优化
r 表示以字符来读取编码
rb 表示以字节bytes来读取 ,如中文gbk 读取出来的格式为:b'\xd6\xd0',在读取图片,声音,视频文件时以此格式。
不管rb仍是wb,ab模式都不用指定encoding,由于文件存储最后都是字节的形式存起来的,若是指定将报错: # ValueError: binary mode doesn't take an encoding argument # 找到文件,指向一个变量即句柄 f = open("path\file.txt", mode = "r", encoding = "UTF-8") content = f.read() print(content) f.close() 注:文件都有一个指针,读模式是从开头即指针为0时,进行读取的,当读取完毕后,指针停在文件的末尾,若是后面没有内容,不关闭文件的状况下,继续读取将读取的时空白。 f.read() 一次性读取文件的所有内容,若是文件过大,将致使内存崩溃,系统宕机 f.read(n) 能够指定读取文件的范围,若是模式为r ,n表示几个字符,若是模式时rb,n表示几个字节(此处涉及到编码级,utf-8 中文表示3个字节,gbk 中文表示2个字节) f.readline() 一次读取一行数据,readline() 默认末尾都加了\n 换行,若是想文件好看,须要在后面加上strip() 去掉换行符 f.readlines() 把每一行一次读取出来放到一个列表中,而后须要对文件操做能够for循环,但一样文件过大时,会致使内存溢出,慎用。 f.readable() 判断当前模式是否可读 f.writeable() 判断当前模式是否可写 若是须要对文件操做,可直接循环句柄f,它是一行一行拿出来进行操做的。 for line in f: print(f"读取每一行字符串:{line}")
二、只写(w, wb)
写模式,若是文件存在,则清空文件内容,若是文件不存在,则建立新文件,都是从开头写,写完指针停留在最后,直到关闭文件。 f.write("内容") 内容只能是字符串,若是想将列表的元素写入只能经过for循环列表,直接填入列表,将报错。 f.flush() 写完内容记得要及时将内容从缓存写入磁盘,否则可能致使内容没有写入文件 f.close()
三、在读写的基础上附加功能
r + 读写,指针从零开始先读后写,若是先写的话,因打开文件指针在0处,写入的内容将从头覆盖相应长度的原文件内容(最经常使用) w+ 写读,先清空,后从头写入文件,因指针在文件尾部,读取文件为空白 a 追加模式,不能读,只能写,不会清空文件,会在尾部追加内容 a+ 追加读,不会清空文件,在尾部追加内容,因指针在尾部,读取文件时一样空白 总结:在不改变指针位置的状况下,a、w+、a+ 都没法读到内容,由于加完内容后指针都在文件尾部
四、获取文件的位置即指针,及改变文件的指针
f.tell() 获取当前文件的位置,也是以字节为单位 f.seek(n) 指定指针的位置,n是以字节为单位,若是是gbk,n 须要为2的倍数,utf-8 ,n 须要为3的倍数 移动到开头:f.seek(0) 移动到结尾:f.seek(0,2) 0表示偏移量,2表示结尾,1表示当前位置 在r+模式下. 若是读取了了内容. 不论读取内容多少. 光标显⽰示的是多少. 再写入 或者操做⽂文件的时候都是在结尾进⾏的操做.
五、截断
截断truncate(),只有在有写的模式下才能截断 想截断: 方法一、经过seek(n)移动指针到截断位置,truncate() 方法二、经过truncate(n)n没有指定是删除截断位置后的全部内容,n指定了就从头开始到n个字节
六、经过with……as 操做文件
由于经过f = open("path\file.txt", mode = "r", encoding = "UTF-8")很容易忘记关闭文件致使错位, 故通常用with方式[上下文],它无需咱们手动关闭,在咱们操做完毕后 with open("path\file_name", moth = "w" , encoding= "utf-8") as f: f.write("name") f.flush()
5、示例
1. 文件修改
import os with open("myPwd.txt", "r", encoding="utf-8") as f1, \ open("myPwd_new.txt", "w", encoding="utf-8") as f2: for line in f1: new_data = line.replace("sun", "xiu") # 逐行修改文件内容 f2.write(new_data) # 将修改后的文件写入到新文件中 os.remove("myPwd.txt.txt") os.rename("myPwd.txt_new.txt", "myPwd.txt.txt")
import hashlib
def check_md5(file_path): with open(file_path, 'rb') as f: md5_obj = hashlib.md5() while 1: b_data = f.read(4096) if b_data: md5_obj.update(b_data) else: return md5_obj.hexdigest()
import os import time import datetime import threading def writ_file(path, file_name): """ 写入文件 :param path: :param file_name: :return: """ st = "%s,00128980,00248980,00128980,%s" with open(os.path.join(path, f'{file_name}.txt'), 'a', encoding='utf-8') as fp: for i in range(1, 1651): line_text = st % ((str(i).ljust(11, '0')), datetime.datetime.today().replace(microsecond=0)) fp.write(f'{line_text}\n') print(f"线程{threading.get_ident()},写入数据:{line_text}完成") if __name__ == '__main__': """ # 批量生产2个1650行的文件 """ now = time.time() threads = [] x = 0 base_dir = os.path.dirname(os.path.abspath(__file__)) for i in range(0, 2): t = threading.Thread(target=writ_file, args=(base_dir, x)) t.start() threads.append(t) x += 1 for j in threads: j.join() print(time.time() - now)
# TODO:优化为一次夺取500行 import traceback from itertools import zip_longest def grouper(iterable, n, fill_value=None): """ 分组读取文件 :param iterable: :param n: 行数 :param fill_value: 当最后数据不够组数时的默认值 :return: """ args = [iter(iterable)] * n return zip_longest(*args, fillvalue=fill_value) def get_data(file_path): """ 读取文件,一次读取n行,返回生成器 :param file_path: 文件路径 :return: 返回的是一组数据 """ try: with open(file_path, 'r', encoding='utf-8') as f: for lines in grouper(f, 500, None): print(f"一次数据{len(lines)}条,数据为:{lines}") lines_data = [] for line in lines: # 当行数不够分组时,补充为None ('xxx',None,) if line: line = line.strip('\n') data = line.split(',') """此处省略从每行数据中获取须要的数据,仅仅是对字符串的处理了""" lines_data.append(tuple(data)) # 清除掉分组为None的元素 yield list(filter(None, lines_data)) except Exception as ex: print(f'解析文件[file_path]={file_path}发生异常,异常缘由为:{ex},位置为:{traceback.format_exc()}') yield 500 def save_data(generator_data): """批量保存数据:如保存数据库或文件""" count = 1 for line in generator_data: for db in line: string = "&".join(db) with open("test.txt", mode="a", encoding="utf-8") as f: f.write(f"{string}\n") print(f"第{count}笔数据{line}保存成功") count += 1 def _main(file_path: list): for path in file_path: file_data = get_data(path) save_data(file_data) if __name__ == '__main__': _main(["0.txt", ])
""" 考虑以下的案例: 同时打开三个文件,文件行数同样,要求实现每一个文件依次读取一行,而后输出,咱们先来看比较容易想到的写法: """ def open_more_file(filename1, filename2, filename3): with open(filename1, 'rb') as fp1: with open(filename2, 'rb') as fp2: with open(filename3, 'rb') as fp3: for i in fp1: j = fp2.readline() k = fp3.readline() print(i, j, k) def open_more_file_for_with(filename1, filename2, filename3): with open(filename1, 'rb') as fp1, open(filename2, 'rb') as fp2, open(filename3, 'rb') as fp3: for i in fp1: j = fp2.readline() k = fp3.readline() print(i, j, k) def open_more_file_for_zip(filename1, filename2, filename3): with open(filename1, 'rb') as fp1: with open(filename2, 'rb') as fp2: with open(filename3, 'rb') as fp3: for i, j, k in zip(fp1, fp2, fp3): print(i, j, k) def open_more_file_for_contextlib(filename1, filename2, filename3): """ 语法糖ExitStack的用法https://docs.python.org/3/library/contextlib.html :param filename1: :param filename2: :param filename3: :return: """ from contextlib import ExitStack with ExitStack() as stack: files = [stack.enter_context(open(fname)) for fname in (filename1, filename2, filename3)] for i, j, k in zip(files[0], files[1], files[2]): print(i, j, k)