评论

收藏

[python] 20210519 文件读与写详解

编程语言 编程语言 发布于:2021-06-24 10:25 | 阅读数:345 | 评论:0

文件操作流程:
1. 打开文件,得到文件句柄并赋值给一个变量
2. 通过句柄对文件进行操作
3. 关闭文件
1-1 打开文件
data = open("donotcry",encoding = "utf-8").read()
print(data)
-->
Talk to me softly. There is something in your eyes
…… 
Tonight
# python 默认编码 是 utf-8;如果打开不指定,windows 默认用 gbk 打开
# 不是同一个编码,所以必须告诉程序,用 utf-8 打开
# 文件打开后,后续如果要操作,需要通过打开的文件对象操作
# 如果想把文件打开后进行更多的操作,必须把打开的文件对象赋一个变量
1-2 操作文件
f = open("donotcry",encoding = "utf-8")    # 文件句柄
# 文件句柄就是这个文件的内存对象,句柄里面包含文件的文件名,字符集,大小,内存,硬盘上的起始位置等
data = f.read()
data2 = f.read()
print(data)
-->
Talk to me softly. There is something in your eyes
…… 
Tonight
print('------------- data2 -------------',data2)
-->
------------- data2 ------------- 
# 文件句柄 打开后,从第一行开始读,在执行第二遍时,光标到了文件最后一行
# 在读时,光标后面没东西了,所以读不到了
# 所以文件就读不到了,读完了;想从中间读,移动回光标即可
f.write('南京市长江大桥')
# -->
# f.write('南京市长江大桥')
# io.UnsupportedOperation: not writable
# 报错因为,已经读了,要么读,要么写
1-2-1
f = open("blank",'r',encoding = "utf-8")
# 'r' 代表读模式,没有写上,就默认是读模式,不过应该写上的
# 有读就有写;'w' 代表写,是通过创建一个文件写入,所以会覆盖之前的
# 写就不能读,读就不能写
1-2-2
f = open("blank",'w',encoding = "utf-8")
# 这是不能读的
f.write('静水流深')
f.write('沧笙踏歌')
-->
静水流深沧笙踏歌
# 打开 blank 文件查看,结果是写到一行的,重新 运行 'w' 之前的内容就会被冲掉
1-2-3 想读也想写 怎么办?
f = open("blank",'a',encoding = "utf-8")     # a = append 追加
f.write('静水流深。。。\n')
f.write('沧笙踏歌')
# 打开 blank 文件查看
-->
静水流深沧笙踏歌静水流深。。。
沧笙踏歌
# 直接追加在后面了,但是,追加不能读
2-1 如果只想打印前五行,怎么办?
f = open("donotcry",'r',encoding="utf-8")  # 文件句柄
print(f.readline())
print(f.readline())
print(f.readline())
print(f.readline())
print(f.readline())
# -->
# Talk to me softly. There is something in your eyes
# Don't hang your head in sorrow and please don't cry
# I know how you feel inside I've been there before
# Somethin' is changin' inside you And don't you know
# Don't you cry tonight I still love you baby Don't you cry tonight
# 如果 想读 500 行, copy 500 次?写代码的原则,避免重复代码
2-2 如果只想打印前五行,怎么办?
f = open("donotcry",'r',encoding="utf-8")  # 文件句柄
for i in range(5):
  print(f.readline()) 
-->
Talk to me softly. There is something in your eyes
Don't hang your head in sorrow and please don't cry
I know how you feel inside I've been there before
Somethin' is changin' inside you And don't you know
Don't you cry tonight I still love you baby Don't you cry tonight
2-3 现在想把 文件进行 循环;每循环一次,打印一次,到第 10 行的时候,不打印
2-3-1 # 注意 前面的都是 readline(),现在变成 readlines()
f = open("donotcry",'r',encoding="utf-8")  # 文件句柄
for line in f.readlines():
  #  print(line) 有空行,是因为每个后面,默认有 \n
  # 如果不想有空行,可以用 strip() 去掉
  print(line.strip())
-->
Talk to me softly. There is something in your eyes
……
Tonight
2-3-2
# 第 10 行 不打印 怎么写?
# low loop
f = open("donotcry",'r',encoding="utf-8")  # 文件句柄
for index,line in enumerate(f.readlines()):
  if index == 9:
    print('----- 我是分割线 -----')
    continue
  print(line.strip())
2-4 
# f.readline 只适合读小文件,大文件不合适,会占用内存
# 如果读大文件怎么办?
# 循环一行,删掉一行,内存中只保存一行
# high bige
for line in f:
  print(line)
# 这个效率是最高的,因为 f 已经被变成了 迭代器
# 现在他不是列表了,所以,需要弄一个计数器。
count = 0
for line in f:
  if count == 9:
    print('----我是分割线----')
    count += 1
    continue
  print(line)
  count += 1
2-5
# readline() 和 readlines 的区别:
# 1. readline() 读取单行; readlines() 读取所有行
# 2. readlines() 是连续调用 readline() 直到文件读取完毕
# 3. readline() 返回当前行; readlines() 返回列表
2-5-1
In [32]: f = open('trial')
In [33]: x = f.read()
In [34]: f.close()
In [35]: x
Out[35]: 'abc\n123\nxyz'
In [36]: f = open('trial')
In [37]: a = f.readline()
In [38]: a
Out[38]: 'abc\n'
In [42]: f.readline()
Out[42]: '123\n'
In [44]: f.readline()
Out[44]: 'xyz'
In [46]: f.readline()
Out[46]: ''
2-5-2
In [54]: f.readlines()
Out[54]: ['abc\n', '123\n', 'xyz']
In [59]: for line in lines:
  ...:   print(repr(line))
  ...:
'abc\n'
'123\n'
'xyz'
In [60]: for line in lines:
  ...:   print(line.strip())
  ...:
abc
123
xyz
3-1 # tell 和 seek 函数
f = open("donotcry",'r',encoding = "utf-8")   # 文件句柄
print(f.tell())
--->
0
# 打开文件后,看光标的位置
# tell 打印光标的位置
3-1-1
f = open("donotcry",'r',encoding = "utf-8")   # 文件句柄
print(f.tell())
print(f.readline())
print(f.tell())
--->
0
Talk to me softly. There is something in your eyes
52
多少个字符,就默认读多少个数
3-1-2
可以指定读取个数
f = open("donotcry",'r',encoding = "utf-8")   # 文件句柄
print(f.tell())
print(f.read(5))
print(f.tell())
--->
0
Talk 
5
# tell() 是按字符计数的
3-1-3
f = open("donotcry",'r',encoding = "utf-8")   # 文件句柄
print(f.tell())
print(f.readline())
print(f.readline())
print(f.tell())
--->
0
Talk to me softly. There is something in your eyes
Don't hang your head in sorrow and please don't cry
105
3-1-4
f = open("donotcry",'r',encoding = "utf-8")   # 文件句柄
print(f.tell())
print(f.readline())
print(f.readline())
print(f.readline())
print(f.tell())
# 读取三行内容后,想移回光标
# seek 是查找光标
# 如果想回到第二行,回不去的,除非有记录
f.seek(0)
print(f.readline())
# seek 和 tell 搭配使用
--->
0
Talk to me softly. There is something in your eyes
Don't hang your head in sorrow and please don't cry
I know how you feel inside I've been there before
156
Talk to me softly. There is something in your eyes
3-2-1
encoding 打印文件编码
f = open("donotcry",'r',encoding = "utf-8")   # 文件句柄
print(f.encoding)
--->
utf-8
3-2-2
fileno 返回文件句柄在文件中的编号
f = open("donotcry",'r',encoding = "utf-8")   # 文件句柄
print(f.fileno())
--->
3
# 操作系统会有一个专门的接口 负责调动所有文件,读文件不是python自己读的
# 而是调用操作系统 io 读取的
3-2-3
# name 就是打印文件名字
# isatty 查看是否是终端设备,比如和打印机的交互可能会用到
# seekable  比如 tty 文件,终端设备文件是移不回去的,比如在 linux 上,一切皆文件
# 如果是二进制,字符串是可以移动的,如果可以移动,返回true;否则,返回 false
# readable 是否可读,writable 判断是否可写
3-2-4
# flush 刷新
# 写入文件时,如果刚刚写完一行断电了,这一行,可能就没有写进去
# 因为这一行,可能还是在内存的缓存中的
# 文件读写有一个缓存的机制,硬盘的读写比内存的读写慢
# 会导致瓶颈卡在这里,必须写到硬盘里才可以继续下一行
# 为了解决这个问题,没写完一行,暂时存在内存的缓存里,只要达到大小就一次性刷到硬盘上
# 所以写的是一行,其实可能是若干行一起写入的
# 这时有没有一种可能要求数据的实时一致性?
# 要求 百分百确认,写入了就是写入了
# 确保缓存里的东西刷到硬盘,所以需要强制刷新
# 比如存钱等场景,会用到
f = open("donotcry",'w',encoding="utf-8")   # 文件句柄
f.write("hello 1\n")
3-2-5
# 打印进度条,就是借助 flush 方法
import sys
sys.stdout.write()
# sys.stdout 标准输出
# sys.stdin  标准输入
# write 操作屏幕,往屏幕上面输出东西
>>> import sys
>>>
>>> sys.stdout.write("#")
#1
>>> sys.stdout.write("####")
####4
>>> sys.stdout.write("#######")
#######7
>>>
3-2-6
import sys,time
for i in range(50):
  sys.stdout.write("#")
  time.sleep(1)
  # 默认不会换行,从前往后一点点排
3-2-7
import sys,time
for i in range(20):
  sys.stdout.write("#")
  # 这是等缓存区满了,统一打出来,所以需要刷新
  sys.stdout.flush()  # 刷新
  time.sleep(0.1)
# 屏幕也被当做一个文件输出,这个stdout.flush() 和前面的 flush 是一样的
3-2-8
f.closed()   # 判断文件是否关闭 返回 true 或 false
f.truncate()  # 如果里面什么也不写,文件会被清空
3-2-9
f = open("donotcry",'a',encoding="utf-8")
f.truncate(10) 
# 'w' 会清空,'w'是创建一个新文件,改成 'a'
# 从文件开头,开始截断 [指针在开头]
3-2-10
f = open("donotcry",'a',encoding="utf-8")
f.seek(10)
f.truncate(20) 
# 移动不好使,无论光标在哪里,都是从头开始截断
4-1
# 既能读,又可以写入的方式,r+
f = open("blank",'r+',encoding="utf-8")  # 文件句柄
# r+ 就是读写,又能读,又能写
print(f.readline())
print(f.readline())
print(f.readline())
f.write("------- Wow -------")
print(f.readline())
--->
静水流深沧笙踏歌静水流深。。。
沧笙踏歌------- Wow -------
# 结果是 ------- Wow ------- 写在了最后面
4-2
# 有读写,就有写读
# f = open("blank",'r+',encoding="utf-8") # 文件句柄 读写 
# f = open("blank",'w+',encoding="utf-8") # 文件句柄 写读
# 区别是,写读是先创建一个文件,然后写入
# 先创建文件,写四行
f = open("blank",'w+',encoding="utf-8") 
f.write("------- Wow -------1\n")
f.write("------- Wow -------2\n")
f.write("------- Wow -------3\n")
f.write("------- Wow -------4\n")
# 打印位置
print(f.tell())
f.seek(10)
print(f.readline())
f.write("should be at the begining of the second line")
--->
------- Wow -------1
------- Wow -------2
------- Wow -------3
------- Wow -------4
should be at the begining of the second line
# 结果还是追加在后面了,没有办法在中间修改
# 写读模式,没有什么用处
# 读写模式,可以打开,可以追加
4-3-1
# 还有一个追加读
# f = open("blank",'a+',encoding="utf-8") 追加读写
# 追加默认不能读
# f = open("blank",'r+',encoding="utf-8") 用的最多
4-3-2
# 还有一种模式
# f = open("blank",'rb',encoding="utf-8")  以二进制格式读文件
f = open("blank",'rb',encoding="utf-8")
print(f.readline())
print(f.readline())
print(f.readline())
# 里面的不是 二进制 那么能够读取吗
--->
ValueError: binary mode doesn't take an encoding argument
# 二进制的模式是不能传 encoding 参数的
# 因为是 二进制,所以不需要编码了
4-3-3
f = open("blank",'rb')
print(f.readline())
print(f.readline())
print(f.readline())
--->
b'------- Wow -------1\r\n'
b'------- Wow -------2\r\n'
b'------- Wow -------3\r\n'
# 结果也是能读的,前面的 b 是 字节类型,表示二进制
# \r\n 是 windows 的换行格式
# python3 中 网络传输,只能用 二进制;二进制文件 就用 二进制打开,网络传输,也用二进制
4-3-4
# 有 rb 就有 wb
f = open("blank",'wb')   
f.write("hello bianry\n")
f.close()
--->
TypeError: a bytes-like object is required, not 'str'
# 如何将 字符串 转换成 bytes? 用 encode
4-3-5
f = open("blank",'wb')   
f.write("hello bianry\n".encode())
f.close()
# 没有跟字符集,就默认使用程序的字符集
--->
hello bianry
# 默认 utf-8
# 二进制不只是指 0101,是说这个文件是以 二进制编码的;内部的处理是按二进制处理
# 3.0 上需要明确区分,二进制就是二进制,字符串就是字符串
关注下面的标签,发现更多相似文章