python的文件操作


python的文件操作image

1、什么是文件
    文件是操作提供给用户/应用程序存取硬盘的一种机制

2、为何要用文件
    永久保存数据

3、代码如何操作文件
	关键字open()
    三步走:
    	1.利用关键字open打开文件
        2.利用其它方法操作文件
        3.关闭文件

文件路径image

相对路径与绝对路径
所谓相对路径,就是相对于自己的目标文件位置。

相对路径:
image
绝对路径:
image

路径中出现了字母与斜杠的组合产生了特殊含义如何取消?
在路径字符串前面加一个r
r'D:\pycharm\测试\a.txt'
image

其中如果打开一个文件,需要这三个参数:image

image
open(文件路径,读写模式,字符编码)
文件路径与读写模式是必须的
字符编码是可选的(有些模式需要编码)
res = open('a.txt', 'r', encoding='utf8')
文件运行的流程是这样的。
image
打开文件,由应用程序向操作系统发起系统调用open(...),操作系统打开该文件,对应一块硬盘空间,并返回一个文件对象赋值给一个变量 res
image

print(res.read()) 调用文件对象下的读/写方法,会被操作系统转换为读/写硬盘的操作

res.close() 向操作系统发起关闭文件的请求,回收系统资源

打开一个文件包含两部分资源:
应用程序的变量res和操作系统打开的文件。在操作完毕一个文件时,必须把与该文件的这两部分资源全部回收
,回收方法为:image

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

其中 del res一定要发生在res.close()之后,否则就会导致操作系统打开的文件无法关闭,白白占用资源。
而python自动的垃圾回收机制决定了我们无需考虑del res,这就要求我们,在操作完毕文件后,一定要记住res.close(),但是大多数人还是会不由自主的忘记res.close,考虑到这一点,python提供了关键字with

1、在执行完子代码块后,with 会自动执行f.close()image

with open('a.txt','w') as res:
pass
image
其中,pass只是为了补全语法结构,没有实际意义。

2、可用用with同时打开多个文件,用逗号分隔开即可image

with open('a.txt','r') as read_res,open('b.txt','w') as write_res:
data = read_res.read()
write_res.write(data)

指定操作文本文件的字符编码image

f = open(...)是由操作系统打开文件,如果打开的是文本文件,会涉及到字符编码问题,如果没有为open指定编码,那么打开文本文件的默认编码很明显是操作系统说了算了,操作系统会用自己的默认编码去打开文件,在windows下是gbk,在linux下是utf-8。

这就用到了上节课讲的字符编码的知识:若要保证不乱码,文件以什么方式存的,就要以什么方式打开。

f = open('a.txt','r',encoding='utf-8')

控制文件读写操作的模式

只需要记住3个①. 'r'(默认的):只读 ②.'w':只写 ③.'a':只追加写
r 只读模式(只能看不能改)

# 路径不存在:直接报错
 with open(r'b.txt', 'r', encoding='utf8') as f:
     pass
# 路径存在
 with open(r'a.txt', 'r', encoding='utf8') as f:
     print(f.read())  # 读取文件内所有的内容
     f.write('123')  # 写文件内容

image

w 只写模式(只能写不能看)image

# 路径不存在:自动创建
# with open(r'b.txt', 'w', encoding='utf8') as f:
#     pass

# 路径存在:1.会先清空文件内容  2.再执行写入操作
with open(r'a.txt', 'w', encoding='utf8') as f:
    # f.read()
    f.write('hello world!\n')
    f.write('hello world!\n')
    f.write('hello world!\n')

运行之前image
运行
image
运行之后直接被清空重新写入hello world!image

image

a 只追加模式(追加内容)image

#路径不存在:自动创建
# a模式  只追加模式
with open(r'a.txt','a',encoding='utf8') as f:
 pass
路径存在:不会清空文件 在文件末尾添加内容
with open(r'a.txt', 'a', encoding='utf8') as f:
 f.write('\n今天周四了 马上又要放假了 好开心!')

image
运行五次之后image
小总结
我们所使用的r w a读写模式都只能操作文本文件

文件操作方法image

# 文件操作方法
# 1.读系列
with open(r'a.txt', 'r', encoding='utf8') as f:
    # print(f.read())  # 一次性读取文件内所有的内容
    # print(f.readline())  # 每次只读文件一行内容
    # print(f.readlines())  # 读取文件所有的内容 组织成列表 每个元素是文件的每行内容
    # print(f.readable())  # 判断当前文件是否具备读的能力


# 2.写系列
with open(r'a.txt','w',encoding='utf8') as f:
    # f.write('克服一切困难 奥利给!')  # 往文件内写入文本内容
    # f.write(123)  # 写入的内容必须是字符串类型
    # f.writelines(['jason','kevin','tony'])  # 可以将列表中多个字符串元素全部写入
    # print(f.writable())  # True
    # print(f.readable())  # False
    f.flush()  # 直接将内存内文件数据刷到硬盘 相当于ctrl+s

文件优化操作image

with open(r'a.txt', 'r', encoding='utf8') as f:
    # print(f.read())  # 一次性读取文件内所有的内容
    # print(f.read())  # 一次性读取文件内所有的内容
    # print(f.read())  # 一次性读取文件内所有的内容
    """
    1.一次性读完之后 光标停留在了文件末尾 无法再次读取内容
    2.该方法在读取大文件的时候 可能会造成内存溢出的情况
        解决上述问题的策略就是逐行读取文件内容
    """
    # for line in f:  # 文件变量名f支持for循环  相当于一行行读取文件内容
    #     line
    '''以后涉及到多行文件内容的情况一般都是采用for循环读取'''

简易版本的拷贝功能
1.获取待拷贝的目标文件路径
2.获取即将拷贝到哪个地方的新路径
3.利用文件操作实现数据拷贝

**1.待拷贝的文件路径**
wait_copy_file = input('file path>>>:').strip()
**2.新的文件路径**
new_file_path = input('new path>>>:').strip()
**3.以r模式打开步骤1的路径 以w模式打开步骤2的路径**
		with open(r'%s' % wait_copy_file, 'rb') as f1, \
			open(r'%s' % new_file_path, 'wb') as f2:
		for line in f1:
			f2.write(line)

二进制模式读写操作image

with open(r'a.txt','rb') as f:
# print(f.read())
print(f.read(6).decode('utf8')) #b模式下表示字节个数

with open(r'a.txt','r',encoding='utf8') as f:
print(f.read())
print(f.read(4)) 默认的t模式下表示字符个数

"""
read()  括号内可以放数字
	在t模式下表示字符个数
	在b模式下表示字节个数
英文字符统一使用一个bytes来表示
中文字符统一使用三个bytes来表示
"""


# with open(r'b.txt', 'rb') as f:
#     print(f.read(4).decode('utf8'))
#     print(f.tell()) 
# 查看光标移动了多少个字节
#     f.seek(3, 1)
#     print(f.read().decode('utf8'))
"""
控制文件内光标的移动  f.seek()
f.seek(offset,whence)
	offset表示位移量
		始终是以字节为最小单位
			正数从左往右移动
			负数从右往左移动
	whence表示模式
		0:以文件开头为参考系(支持tb两种模式)
		1:只支持b模式 以当前位置为参考系
		2:只支持b模式 以文件末尾为参考系
"""

# with open(r'b.txt', 'rb') as f:
#     print(f.read(4).decode('utf8'))
#     print(f.tell())  # 查看光标移动了多少个字节
#     f.seek(3, 1)
#     print(f.read().decode('utf8'))
"""
控制文件内光标的移动  f.seek()
f.seek(offset,whence)
	offset表示位移量
		始终是以字节为最小单位
			正数从左往右移动
			负数从右往左移动
	whence表示模式
		0:以文件开头为参考系(支持tb两种模式)
		1:只支持b模式 以当前位置为参考系
		2:只支持b模式 以文件末尾为参考系
"""

小练习:实现动态查看最新一条日志的效果
image

import time
with open('a.txt', 'rb') as f:
	f.seek(0, 2)
	while True:
		line = f.readline()
		if len(line) == 0:
			# 没有内容
			time.sleep(0.5)
		else:
			print(line.decode('utf-8'), end='')
import time
with open('a.txt', 'rb') as f:
	f.seek(0, 2)
	while True:
		line = f.readline()
		if len(line) == 0:
			# 没有内容
			time.sleep(0.5)
		else:
			print(line.decode('utf-8'), end='')

文件的内容修改image

# 第一种方法(废内存)
with open('a.txt', 'r', encoding='utf8') as f:  # 打开一个文本文件a.txt选择只读模式
	res = f.read()  # 将读出来的文件赋值给res,读取到内存空间。
	data = res.replace('lin', 'xxx')  # 然后再把res里面的内容修改后交给变量名data
with open('a.txt', 'w', encoding='utf8') as f1:  # 再将a.txt文件内容清空,重新写入data里的内容~
	f1.write(data)
# 这种方法如果要修改的文本文件大的话,对内存占用大。


# 第二种方法  导入标准库os,遍历写入(节省内存,损耗硬盘)
import os  # 导入标准库os

# 然后打开要修改的a.txt选择只读赋值给f,打开并创建一个a.txt.swap的文件(可以理解为虚拟文件),赋值给f1
with open('a.txt', 'r', encoding='utf8') as f, \
		open('.a.txt.swap', 'w', encoding='utf8') as f1:
	for line in f:  # 遍历获取a.txt每一行内容
		f1.write(line.replace('lin', 'xxx'))  # 将其中关于lin的内容修改为xxx
os.remove('a.txt')  # 随后先删除掉旧得a.txt   并将创建的.a.txt.swap文件名改为 a.txt
os.rename('.a.txt.swap', 'a.txt')

两种方法视情况使用,如果文件过大使用第二种方法,反之,使用第一种更方便~image

image


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM