关于文件的一些常见误区:
- 长期使用Windows操作系统的朋友很容易被扩展名所误导,认为扩展名决定文件类型,其实这种观念是错误的!
- 误区一:文件扩展名是一个文件的必要构成部分(一个文件可以有或没有扩展名,对于打开文件操作,没有扩展名的文件需要选择程序去打开它,有扩展名的文件会自动用设置好的程序(如有)去尝试打开)
- 误区二:文件扩展名表明了该文件是何种类型(文件扩展名可以人为设定,扩展名为TXT的文件有可能是一张图片,同样,扩展名为M-P3的文件,依然可能是一个视频。)
Python处理文件的三个必要参数
文件路径:D:\jacky_file.txt (你想操作这个文件,必须要知道这个文件的位置)
编码方式:utf-8,gbk,gb2312… (文件其实就是数据的存储,数据存储你需要编码知道这个数据是以什么编码存储的)
操作模式:只读,只写,追加,写读,读写…
一、打开文件
在Python中,使用open()函数打开文件并返回文件对象:
open(file, mode=‘r’, buffering=None, encoding=None, errors=None, newline=None, closefd=True)
第一个参数是传入的文件路径和文件名,不带路径时,Python会在当前文件夹取找到这个文件并打开。
第二个参数指定文件打开模式,如下表:
打开模式 | 执行操作 |
---|---|
‘r’ | 以只读方式打开文件(默认) |
’w’ | 以写入的方式打开文件,会覆盖已存在的文件,无该文件则创建 |
‘x’ | 如果文件已经存在,使用此模式打开将引发异常 |
‘a’ | 以写入模式打开,如果文件存在,则在末尾追加写入,文件不存在则创建 |
’b’ | 以二进制模式打开文件 |
‘t’ | 以文本模式打开(默认) |
’+' | 可读写模式(可添加到其他模式中使用) |
‘U’ | 通用换行符支持 |
encoding: 不是具体的编码或者解码,他是指:此次打开文件使用什么编码本。一般来说:你的文件用什么编码保存的,就用什么方法打开,一般都是用utf-8(有些使用的是gbk)。
- 路径问题错误 \ 转义导致 解决:路径前加 r 变成原始字符串
f = open('F:\Python\tata\jacky_file.txt', mode='r+', encoding='utf-8')
for each_line in f:
print(each_line, end="")
f.close()
Traceback (most recent call last):
File "C:/python文件都在这里/python 全栈/day1-8/file_.py", line 2, in <module>
f = open('F:\Python\tata\jacky_file.txt', mode='r+', encoding='utf-8')
OSError: [Errno 22] Invalid argument: 'F:\\Python\tata\\jacky_file.txt'
#使用原始字符串方法:
f = open(r'F:\Python\tata\jacky_file.txt', mode='r+', encoding='utf-8')
for each_line in f:
print(each_line, end="")
f.close()
I am studying python! #文件内容被打印出来了
- 编码问题导致文件解码错误
打开文件用的编码与文件储存时用的编码不一样导致的,比如这个文件当时用word软件保存时,word软件默认的编码为utf-8,但是你利用python代码打开时,用的gbk,那么这个就会报错了。
用utf-8编码方式打开用gbk编码的文件会报错
f = open(r'log', mode='r+', encoding='utf-8')
for each_line in f:
print(each_line, end="")
f.close()
Traceback (most recent call last):
File "C:/python文件都在这里/python 全栈/day1-8/file_.py", line 3, in <module>
for each_line in f:
UnicodeDecodeError: 'gbk' codec can't decode byte 0x80 in position 33: illegal multibyte sequence
- rb 和 wb模式 :一般用于非文本文件如:图片,音频,视频等。
rb模式:以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。带b的都是以二进制的格式操作文件,他们主要是操作非文字文件:图片,音频,视频等,并且如果你要是带有b的模式操作文件,那么不用声明编码方式。
wb模式:以二进制格式打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。
二、文件对象的方法
打开文件并取得文件对象之后,就可以利用文件对象的一些方法对文件进行读取或修改等操作。(文件默认不能修改,只能间接修改:创建一个同名文件覆盖)
文件对象方法
文件对象方法 | 执行操作 |
---|---|
f.close() | 关闭文件 |
f.read([size=-1]) | 从文件读取size个字符,当未给定size或给定负值的时候,读取剩余的所有字符,然后作为字符串返回 |
f.readline([size=-1]) | 从文件中读取并返回一行(包括行结束符),如果有size有定义则返回size个字符(注:readline()读取出来的数据在后面都有一个\n,可用strip()去掉) |
f.readlines([size=-1]) | readlines() 返回一个列表,列表里面每个元素是原文件的每一行,如果文件很大,占内存,容易崩盘。 |
f.write(str) | 将字符串str写入文件 |
f.writelines(seq) | 向文件写入字符串序列seq,seq应该是一个返回字符串的可迭代对象 |
f.seek(offset, from) | 在文件中移动文件指针,从from(0代表文件起始位置,1代表当前位置,2代表文件末尾)偏移offset个字节 |
f.tell() | 返回当前在文件中的位置 |
f.truncate([size=file.tell()]) | 截取文件到size个字节,默认是截取到文件指针当前位置 |
flush() | 方法是用来刷新缓冲区的,即将缓冲区中的数据立刻写入文件,同时清空缓冲区,不需要是被动的等待输出缓冲区写入。(一般情况下,文件关闭后会自动刷新缓冲区,但有时你需要在关闭前刷新它,这时就可以使用 flush() 方法。) |
当对文件执行了写入操作时,那么应该在完成写入之后关闭文件。使用with语句代替f.close()可以大大地减少代码量,而且也不用担心文件打开了忘记关闭的问题(with会自动帮你关闭文件),而且使用with语句支持一次性打开多个文件,举个栗子:
f = open('jacky_file.txt', mode='r+', encoding='utf-8')
for each_line in f:
print(each_line, end="")
f.close()
# 用with更方便,不用担心文件的关闭的问题
with open('jacky_file.txt', mode='r+', encoding='utf-8') as f1, \
open('log', mode='r+', encoding='utf-8') as f2:
for each_line in f1:
print(each_line, end='')
三、文件的读取和定位
- read(n) 文件打开方式为文本模式时,代表读取n个字符; 文件打开方式为b模式时,代表读取n个字节
- tell()方法可以告诉你文件指针的位置
- seek(offset, from)有两个参数,表示从from(0表示文件起始位置,1表示当前位置,2表示文件末尾)偏移offset字节。因此使用seek(0, 0)可以将文件指针置于文件起始位置。
>>> f = open(r'C:\python文件都在这里\jacky_file.txt', mode='r+', encoding='utf-8')
>>> f.read() #读取文件全部内容
'小苦瓜python!'
>>> f.tell() #返回文件指针的位置 3*3 + 7 == 16 (utf-8编码中一个中文占三个字节)
16
>>> f.seek(0, 0) # == seek(0) 把文件指针拉到文件的开头位置
0
>>> f.read(5) # 读取5个字符
'小苦瓜py'
>>> f.tell() # 3*3 +2 == 11
11
- readable() 返回布尔值,是否可读
- writeable() 返回布尔值,是否可写
f = open(r'C:\python文件都在这里\jacky_file.txt',mode='r', encoding='utf-8')
print(f.readable()) # True
print(f.writable()) # False
content = f.read()
f.close()
作业
1.编写一个程序,当用户输入文件名和行数(N)后,将该文件的前N行内容打印到屏幕上
def print_file_n_row(file_name, line_num):
with open(file_name, mode='r', encoding='utf-8') as f:
for i in range(line_num):
print(f.readline(), end='')
file_name = input("请输入要打开的文件:")
line_num = int(input("请输入需要显示文件前几行:"))
print_file_n_row(file_name, line_num)
2.将文件中(jacky_file)所有的jacky都替换成大写的SB。
with open('jacky_file.txt', mode='r', encoding='utf-8') as read_file, \
open('jacky_file.bak', mode='w', encoding='utf-8') as write_file:
for each_line in read_file:
each_line = each_line.replace('jacky', 'SB')
write_file.write(each_line)
import os
os.remove('jacky_file.txt') #删除源文件
os.rename('jacky_file.bak', 'jacky_file.txt') #重命名新建的文件为源文件的名称