首页 > 技术文章 > Python之文件操作

tootooman 2018-05-03 18:51 原文

1、文件处理流程

a.打开文件,得到文件句柄并赋值给一个变量

b.通过句柄对文件进行操作

c.关闭文件


2、文件操作模式

有一个文件:小重山

昨夜寒蛩不住鸣。

惊回千里梦,已三更。

起来独自绕阶行。

人悄悄,帘外月胧明。

白首为功名,旧山松竹老,阻归程。

欲将心事付瑶琴。

知音少,弦断有谁听。

读模式:r

文件不存在会报错
file=open('小重山','r',encoding='utf8')  # 把小重山这个文件作为一个对象,'r':表示可读,encoding='utf8':编码转换
data=file.read()  # 按字符串个数,取字符串内容,默认为所有,可以为数字,表示取多少个字符,加数字没意义
data=file.readline() # 跟随光标按行取内容,每行的末尾都会有一个换行符 \n,也算一个字符,取一行内容
data=file.readlines() # 跟随光标位置开始打印所有行,但是是以列表的形式展现出来,想打印所有,就用 for 循环 data
data=file.readable()  # 判断文件是否可读
file.close()   # 只要有打开文件的方法存在,就加上文件关闭的方法
file.tell()  # 打印当前光标的位置,按utf8来,读一个字母为进1,一个中文进3,GBK,中文进2,按字节移动
file.seek(0) # 重设光标的位置,按字节移动,一个中文3个字节,例如:当断点后,可以记录传输的位置,并从断点的位置开始重传

其他方法:

f.fileno() # 返回一个操作令牌:当一个对象被你使用时,你会获得这个对象的操作令牌,这个操作令牌是唯一的,且为整型

f.isatty() # 判断对象是否为终端,返回:True、false


写模式:w

file=open('小重山2','w',encoding='utf8')  #当 小重山2 这文件不存在,会自动创建一个,如果里面有内容会清空掉
file.write('hello')
file.write('alex')      # 结果是不换行:helloalex,换行要加 \nalex
file.writelines(['a','b','c'])  # abc
file.flush() # 当写一条数据后,不存入内存缓存,而是立马写进磁盘,确保安全,但是会降低性能,flush 当内存缓存满了也会自动写进磁盘
file.close()
import sys,time
for i in range(30):
    sys.stdout.write('*')   # 进度条显示
    sys.stdout.flush() # 等于  print("*",end='',flush=True)
    time.sleep(0.2)

# 进阶版:
import  sys
import time
for i in range(101):
    s="\r%s%% %s"%(i,'#'*i)
    sys.stdout.write(s)
    sys.stdout.flush()
    time.sleep(0.1)

# 100% #############################
进度条示例


追加模式:a

file=open('小重山','a',encoding='utf8') # 与写模式不同,不会清空文件内容,而是在文件末尾追加内容,文件不存在会创建
file.write('\nhello world\n') # 追加内容
file.write('alex')  # 追加内容
flush.truncate()  # 把光标后面的全部删除,默认不加位置,全删了,括号内加数字表示从头开始截多少个字节
file.close()


读写模式:r+

光标在开始位置,先读文件,读完文件光标在最后位置,再写内容,追加写,写完光标在文件末尾
f=open("小重山",'r+',encoding='utf8')
print(f.readlines())
f.write("\n岳飞")
f.close()

with open('小重山', 'r', encoding='utf8') as r:
    for line in r:
        print(line.strip())
'''
昨夜寒蛩不住鸣。
惊回千里梦,已三更。
起来独自绕阶行。
人悄悄,帘外月胧明。
白首为功名,旧山松竹老,阻归程。
欲将心事付瑶琴。
知音少,弦断有谁听。

岳飞
'''


写读模式:w+

先清空文本内容,在写内容,光标会在写完内容的后面,想读内容,seek 位置(不常用)
f=open("小重山2",'w+',encoding='utf8')
f.write("\n岳飞")
f.seek(0)  # 如果要读的话要把光标置0才能读
print(f.readlines())
f.close()


追加读模式:a+

光标始终在末尾,读的时候要调整 seek,文件不存在则新建一个
f = open("小重山", 'a+', encoding='utf8')
print(f.tell())
f.seek(0)
print(f.readlines())
f.close()

'''
234
['\n', '昨夜寒蛩不住鸣。\n', '惊回千里梦,已三更。\n', '起来独自绕阶行。\n', '人悄悄,帘外月胧明。\n', '白首为功名,旧山松竹老,阻归程。\n', '欲将心事付瑶琴。\n', '知音少,弦断有谁听。\n', '\n', '岳飞']
'''


b 模式:rb、wb、ab

不用在编码,而是直接把硬盘里存储的字节数据拿出来,所以不用 encoding

什么情况会用到:不是给人看的,而是给机器看的,一般用于传输,读出文件,然后直接进行网络传输

with open('a.txt','rb') as f:
    print(f.read().decode('utf8'))  # 需要知道是什么编码的

with open('a.txt','wb') as f:
    f.write('alex李杰'.encode("utf8"))  # 写内容以什么编码写进去

with open('a.txt','ab') as f:
    f.write('egon爱根'.encode("utf8"))  # 写内容以什么编码写进去

问题来了:用 rb 模式就不知道是什么编码,因为是字节码,如果非要知道是什么编码方式,用 chardet 模块帮忙吧

chardet模块需要安装:pip3 install chardet

import chardet
f = open('兼职白领学生空姐模特护士联系方式utf8.txt', 'rb')
data = f.read()
print(data)  # 全是你看不懂的字节码
print(chardet.detect(data))     # {'encoding': 'GB2312', 'confidence': 0.99, 'language': 'Chinese'}
f.close()
'''
encoding:编码方式
confidence:自信程度...    99%肯定编码编码方式是正确的
language:语言
'''
# 如果不相信模块的自信,那就自己验证一下
print(data.decode('gbk'))


seek 模式:0 1 2,且 seek 模式是针对字节编码的

seek(offset,from)

offset:偏移量

from:方向

0:表示文件开始位置

1:表示文件当前位置

2:表示文件末尾位置

例子:
文件:test5内容
hello元

with open('test5','rb') as f:   # 如果要使用 seek 的模式,必须是 ab、wb、rb 模式
    print(f.read(3))    # 默认模式 0 ,从文件开始取3个字节
    print('----')
    f.seek(-3,2)  # 模式2,从末尾开始往左选3个字节(一个中文字符)
    print(f.read().decode('utf8'))    # 因为是字节编码,转出来内存要解码成utf8编码的unicode


结果:
b'hel'
----


文件内光标移动:

一: read(3):

  1. 文件打开方式为文本模式时,代表读取3个字符

  2. 文件打开方式为b模式时,代表读取3个字节

二: 其余的文件内光标移动都是以字节为单位如seek,tell,truncate

注意:

      1. seek有三种移动方式0,1,2,其中1和2必须在b模式下进行,但无论哪种模式,都是以bytes为单位移动的

          seek控制光标的移动,是以文件开头作为参照的。

          tell当前光标的位置

  2. truncate是截断文件,所以文件的打开方式必须可写,但是不能用w或w+等方式打开,因为那样直接清空文件了,所以truncate要在r+或a或a+等模式下测试效果


3、上下文操作

避免忘记底部加 f.close(),只要退出 with 代码块,会自动 close 对象

with open('小重山','r',encoding='utf8') as f:
    f.read()

# 同时打开多个文件
with open('小重山','r',encoding='utf8') as f_read,open('小重山2','w',encoding='utf8') as f_write:
    for i in f_read:
        f_write.write(i)


4、文件修改

占用硬盘方式:一个负责读,一个负责写,写完后删除源文件,把写完后的文件重命名为源文件名

import os
with open('小重山', 'r', encoding='utf8') as r, open('小重山.swp', 'w', encoding='utf8') as w:
    for line in r:
        if '人悄悄' in line:
            print('true')
            line = line.replace('人悄悄', '人茫茫')
        w.write(line)
os.remove('小重山')
os.rename('小重山.swp', '小重山')

占用内存方式(不推荐):先把文件全部读取出来赋值变量,在变量里替换内容,把光标置0,清空文件,再写内容

f = open('小重山2', 'r+', encoding='utf8')
data = f.read()
if '人茫茫' in data:
    data = data.replace('人茫茫', '人悄悄')
f.seek(0)
f.truncate()
f.write(data)
f.close()

推荐阅读