Python文件操作

1. 普通模式

1.1 文件操作说明

1)open()函数指定编码

open()函数访问文件时要先向操作系统发送请求,所以打开文件的编码以操作系统默认编码为准,windows默认编码为GBK。

若open()函数不指定编码,可能会造成乱码。

open()函数不会将整个文件瞬间全部加载到内存。

2)python3执行代码的过程

  1. 解释器找到代码文件,把代码字符串按文件头定义的编码加载到内存,转成unicode
  2. 把代码字符串按照语法规则进行解释
  3. 所有的变量字符都会以unicode编码声明

3)为何打开文件后要执行关闭操作

open函数返回的是一个地址,传递给 f 后,f 就是open函数打开文件的文件句柄。所谓的句柄就一块内存的索引,所以这里的 f 其实是文件位置的内存索引

如果打开文件后句柄一直不关闭,那么随着打开文件数量的增加,句柄量会一直增加,消耗的内存也一直增加,严重消耗系统资源。

如果文件句柄保存为一个临时的变量,那么,当这个变量被回收时,文件句柄就会被关闭;但是如果其被保存在类中充当一个实例变量,那么它便一直不会被关闭,这时便不能对该文件作删除操作。

其实在程序结束时,系统会自动关闭句柄,但是自觉的关闭文件句柄是一种良好的习惯。

1.2 open()函数

1)打开文件的方式

  • r, w, a
  • "+"  表示可以同时读写某个文件
  • r+, 读写【可读,可写】,但是写的时候如果原文件存在,则会从开头开始一个个覆盖
  • w+,写读【可读,可写】
  • a+, 写读【可读,可写】,追加写入
  • #####################################
  • rb, wb, ab
  • #####################################
  • x, 只写模式【不可读;不存在则创建,存在则报错】
  • x+ ,写读【可读,可写】
  • xb

2)读(r)方式打开文件

# 不存在则报错
f = open("file.txt", encoding="utf-8")  # open函数可以指定编码的格式
date = f.read()                         # 这里的read函数是以每一个字符的方式读取文本的
print(date)
f.close()                               # 文件访问结束时一定要进行关闭操作


f = open("file.txt", "r", encoding="utf-8")
print(f.readable())                     # readable()可以用来判断文件是否可读

print(f.readline(), end="")             # readline()可以读取一行文件内容,但是每一行内容后面都会被自动添加上一个换行符
print(f.readline(), end="")             # 可以将print()函数的end参数指定为空,以消除readline函数中自动添加上的换行符

print(f.readlines())                    # readlines()函数将每一行的内容后面添加一个换行符后保存到一个列表中
f.close()

3)写(w)方式打开文件

# 在文件处理的 "w" 模式下,若文件存在,则将原文件内容全部删除后,再进行写入,若文件不存在,则新建文件再进行写入
f = open("hello.txt", "w", encoding="utf-8")

print(f.writable())                                        # 判断文件是否可写

f.write("this is my place,\n welcome to you")              # 文件必须以字符串(str)的形式进行写入或读取
f.writelines(["name\n", "age\n", "gender\n", "addr\n"])    # writelines()函数接受一个列表,并进行迭代写入

f.close()

4)追加(a)方式打开文件

# 不存在则创建,存在则追加
f = open("hello.txt", "a", encoding="utf-8")
f.write("append到文件的后面")
f.close()

5)其他操作

f1 = open("file.txt", "r", encoding="utf-8")
date = f1.read()
f1.close()

f2 = open("welcome.txt", "r+", encoding="utf-8")     # r+ 模式表示读写模式,可读、可写,但文件必须事先存在
# r+模式中,若文件存在,则会从文件开头开始一个个覆盖
f2.write(date[1:])
f2.close()

6)路径

open('C:\Users\Meet')  #这样程序是不识别的
解决方法一: open('C:\\Users\\Meet') #这样就成功的将\进行转义 两个\\代表一个\ 解决方法二: open(r'C:\Users\Meet') #这样相比上边的还要省事,在字符串的前面加个小r也是转义的意思

1.3 with open()  as ...

# 使用with···as···的格式来进行文件操作可以不用在末尾关闭文件
# 若要将一行的代码截断到第二行显示,可以在第一行的末尾加上一个反斜杠
with open("file.txt", "r", encoding="utf-8") as f3, \
    open("welcome.txt", "r+", encoding="utf-8") as f4:
    date = f3.read()
    f4.write(date)

2. 读写模式&写读模式

2.1 读写模式(r+)

读写模式必须是写读后写,因为光标默认在开头位置,当读完了以后再进行写入。

在 r+ 模式下,如果读取了内容,不论读取内容多少,光标显示的是多少,再写入。

f1 = open('shit.txt',mode='r+',encoding='utf-8')
msg = f1.read()
f1.write('朕,一统天下')
f1.flush()
f1.close()
print(msg)

# 正常的读取之后, 写在结尾

2.2 写读模式(w+)

w+ 模式下,是把文件清空了再写,很少用。

f1 = open('shit.txt',mode='w+',encoding='utf-8')
f1.write('hehe')
msg = f1.read()
f1.flush()
f1.close()
print(msg)

3. 二进制b模式

  • windodws平台中的回车为 \r\n , 而Linux和Unix平台中的回车为 \n
  • 文件默认的打开方式为 rt 的方式, t 表示文本方式
  • 字符串和字节之间的转换
    • 字符串-----> encode -----> bytes
    • bytes -----> decode -----> 字符串
f = open("b_test.txt", "rb")    # 这种以二进制方式打开文件的的方式不能指定编码
date = f.read()
print(date)
print(date.decode("utf-8"))   # 将二进制的数据流解码成utf8格式的文本内容
f.close()

f = open("b_write.txt", "wb")
# f.write(bytes("你好!\n", encoding="utf-8"))   # 这里的write中写入的内容必须为二进制形式,可以用bytes函数或者直接encode的形式编码成二进制
f.write("你的名字是什么?".encode("utf-8"))
f.close()

f = open("b_test.txt", "ab")
f.write(bytes("\nthis is append\n", encoding="utf-8"))
# bytes函数:将对应的字符串按照一定的编码抓换成二进制
#            第一个参数接受一个str类型,第二个参数指定编码格式
f.write("the last append".encode("utf-8"))
f.close()

# 在python中,会统一将回车转换为 \n  , 若想要显示windows平台中对于回车的 \r\n , 可将open函数中的 newline 选项定义为 空 ""
f = open("b_test.txt", "r", encoding="utf-8", newline="")
date = f.readlines()
print("My_test:", date)
f.close()

4. 其他方法

4.1 flush()

f = open("b_test.txt", "r+", encoding="utf-8")

print(f.closed)    # f.closed 判断文件是否关闭
print(f.encoding)  # f.encoding 显示文件打开的编码
print(f.name)      # f.name 显示文件名

f.flush()     
# f.flush() 函数将数据写入到磁盘中,因为数据一般不会立即写入磁盘,
#           而是先保存到(缓冲)buffer中,到达一定的数量或时间时,
#           会统一写入到磁盘中,这样会增加减少io的数量,增加效率

4.2 tell()

f = open("b_test.txt", "r+", encoding="utf-8")
print(f.tell()) # 读取光标此时的位置,现在光标处于文件开头,光标位置为0 # tell() 方法读取的光标的位置是以字节数来确定的,回车在windows平台中 \r\n 为两个字节,utf-8汉字占3个字节 f.readline() print(f.tell()) # 读取一行文件内容后,现在光标位于一行的末尾

4.3 seek()

f = open("b_test.txt", "r+", encoding="utf-8")
# 除read()外,其余文件操作中处理光标移动的方法都是以字节为单位如tell() 、 seek() 、 truncate()等
# 偏移量可以为负数,表示向前偏移
f.seek(6, 0)   
# seek()函数的第一个参数表示偏移量,第二个参数有3个选项: 
  0 表示绝对位置
  1 表示相对于当前位置
  2 表示文件末尾
# 当seek的第二个参数为2时(从末尾开始seek), 前面的偏移量必须为负数,倒着去seek # 注意:对于非二进制的文本文件,不允许使用seek的偏移定位,只能使用全局定位 date = f.readline() print(date) f.close() f.truncate(20) # 截取从光标位置开始计数的20个字节的字符

4.4 循环文件的方式

# 循环文件的方式:
for i in f.readlines():    # 这样会一次性把文件全部加载到内存中,保存为一个列表的形式进行遍历
    print(i)

for i in f:     # 推荐方式,这样不会一次性全部加载到内存中,只在有需要的时候慢慢加载,维持文件内容占据一片小的内存(进行读取和丢弃的循环)
    print(i)   

5. 读取一个大文件的最后一行

f = open("huge_file.txt", "rb")

for i in f:                           # 对文件内容进行小内存循环迭代
    line_length = -20                 # 指定一个初始的seek长度
    while True:
        f.seek(line_length, 2)          # 将光定位到结尾的倒数第line_length个字节的位置
        date = f.readlines()          # 将readlines读取到的内容保存到一个列表中
        if len(date) > 1:             # 若列表中的元素个数大于1,表示此次readlines读取到了完整的最后一行和不完整的倒数第二行
            print("最后一行的内容为:", date[-1])      # 文件最后一行的内容保存在列表的倒数第一个元素
            break
        line_length *= 2              # 偏移量过小,加大偏移量

 

 

 

 

 

posted @ 2020-06-12 21:56  Praywu  阅读(262)  评论(0编辑  收藏  举报