python课程学习-模块二-01-文件处理

1 . 文件处理的流程

1)打开文件,得到文件句柄并赋值给一个变量
2)通过句柄对文件进行操作
3)关闭文件

例:

In [6]: f1 = open('data.txt', 'r', encoding='utf8')

In [7]: print(f1)
<_io.TextIOWrapper name='data.txt' mode='r' encoding='utf8'>

In [8]: f1.read()  # 显示读入的文本
Out[8]: 'Rain雨\n\nRain is falling all around, 雨儿在到处降落,\nIt falls on field and tree, 它落在田野和树梢, \nIt rains on the umbrella here, 它落在这边的雨伞上,\nAnd on the ships at sea. 又落在航行海上的船只。\n'

In [9]: ! cat data.txt  # 文本原文
Rain雨

Rain is falling all around, 雨儿在到处降落,
It falls on field and tree, 它落在田野和树梢, 
It rains on the umbrella here, 它落在这边的雨伞上,
And on the ships at sea. 又落在航行海上的船只。

In [10]: f1.close()

open函数用来打开文件,主要语法如下:

open(file, mode='r', buffering=-1, encoding=None)
open(文件名, 文件打开方式, 缓冲, 编码格式)

其中文件打开方式,缓冲,编码格式都是可选的。
mode:文件打开模式
buffering:可取值有0,1,>1三个,0代表buffer关闭(只适用于二进制模式),1代表line buffer(只适用于文本模式),>1表示初始化的buffer大小;
encoding:表示的是返回的数据采用何种编码,一般采用utf8或者gbk;

如果文件不存在:

In [16]: f1 = open('data-test.txt', 'r')
---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
<ipython-input-16-918e552dcaa9> in <module>()
----> 1 f1 = open('data-test.txt', 'r')

FileNotFoundError: [Errno 2] No such file or directory: 'data-test.txt

2. 文件的打开模式

r,只读模式【默认模式,文件必须存在,不存在则抛出异常】
w,只写模式【不可读;不存在则创建;存在则清空内容】
x,只写模式【不可读;不存在则创建,存在则报错】
a,追加模式【可读;不存在则创建;存在则只追加内容】,文件指针自动移到文件尾。

# 1. 打开文件
>>> f1 = open('data.txt', 'r')
>>> f1.read()
'Rain雨\n\nRain is falling all around, 雨儿在到处降落,\nIt falls on field and tree, 它落在田野和树梢, \nIt rains on the umbrella here, 它落在这边的雨伞上,\nAnd on the ships at sea. 又落在航行海上的船只。\n'
>>> f1.close()

# 写入文件
>>> f1 = open('data.txt', 'w')
>>> f1.write('hello world\n')
12
>>> f1.close()
我们退出查看一下文件:
# cat data.txt
hello world
写入的时候,如果没有这个文本文件,会创建一个新的,如果有,就清空内容后再写入
可以看到,原来的文本都不见了,'w'这种模式相当于把原有文本的内容全部清空,重新写入,要追加输入的话,还要用'a'这种模式。


# 追加写入
>>> f1 = open('data.txt', 'a')  # 追加模式
>>> f1.write('hello world\n')   # 写入新数据
12
>>> f1.read()   # 不能读
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
io.UnsupportedOperation: not readable
>>> f1.close()

>>> f1 = open('data.txt', 'r')  # 读取新文本
>>> f1.read()
'Rain雨\n\nRain is falling all around, 雨儿在到处降落,\nIt falls on field and tree, 它落在田野和树梢, \nIt rains on the umbrella here, 它落在这边的雨伞上,\nAnd on the ships at sea. 又落在航行海上的船只。\nhello world\n'   # 可以看到在最后,'hello world'已经被写入了
>>> f1.read().strip('\n').split('\n') # 想做一下进一步处理,但是文本并不能重复读取,最好是对读取结果赋值
['']
>>> f1.close()
>>> 
>>> f1 = open('data.txt', 'r')  # 再次读取
>>> f1.read().strip('\n').split('\n') # 文本处理
['Rain雨', '', 'Rain is falling all around, 雨儿在到处降落,', 'It falls on field and tree, 它落在田野和树梢, ', 'It rains on the umbrella here, 它落在这边的雨伞上,', 'And on the ships at sea. 又落在航行海上的船只。', 'hello world']
>>> 
>>> f1.close()

“+” 表示可以同时读写某个文件
r+,读写【可读,可写】
w+,写读【可读,可写】,消除文件内容,然后以读写方式打开文件。
x+,写读【可读,可写】
a+,写读【可读,可写】,以读写方式打开文件,并把文件指针移到文件尾。

“b”表示以字节的方式操作,以二进制模式打开文件,而不是以文本模式。
rb 或 r+b
wb 或 w+b
xb 或 w+b
ab 或 a+b

>>> f1 = open('data.txt', 'rb')
>>> f1.read()
b'Rain\xe9\x9b\xa8\n\nRain is falling all around, \xe9\x9b\xa8\xe5\x84\xbf\xe5\x9c\xa8\xe5\x88\xb0\xe5\xa4\x84\xe9\x99\x8d\xe8\x90\xbd\xef\xbc\x8c\nIt falls on field and tree, \xe5\xae\x83\xe8\x90\xbd\xe5\x9c\xa8\xe7\x94\xb0\xe9\x87\x8e\xe5\x92\x8c\xe6\xa0\x91\xe6\xa2\xa2\xef\xbc\x8c \nIt rains on the umbrella here, \xe5\xae\x83\xe8\x90\xbd\xe5\x9c\xa8\xe8\xbf\x99\xe8\xbe\xb9\xe7\x9a\x84\xe9\x9b\xa8\xe4\xbc\x9e\xe4\xb8\x8a\xef\xbc\x8c\nAnd on the ships at sea. \xe5\x8f\x88\xe8\x90\xbd\xe5\x9c\xa8\xe8\x88\xaa\xe8\xa1\x8c\xe6\xb5\xb7\xe4\xb8\x8a\xe7\x9a\x84\xe8\x88\xb9\xe5\x8f\xaa\xe3\x80\x82\nhello world\n'
>>> f1.close()
可以看到,读取的数据都是二进制的形式展示的

注:以b方式打开时,读取到的内容是字节类型,写入时也需要提供字节类型,不能指定编码

3. read,readline,readlines的区别

read() #一次读取全部的文件内容。
readline() #每次读取文件的一行。
readlines() #读取文件的所有行,返回一个字符串列表。

我们以下面的例子进行说明:

>>> f1 = open('data.txt', 'r')
>>> f2 = open('data.txt', 'r')
>>> f3 = open('data.txt', 'r')
>>> 
>>> f1.read()  # read会一次性全部读入,并且不会对文本进行处理
'Rain雨\n\nRain is falling all around, 雨儿在到处降落,\nIt falls on field and tree, 它落在田野和树梢, \nIt rains on the umbrella here, 它落在这边的雨伞上,\nAnd on the ships at sea. 又落在航行海上的船只。\nhello world\n'
>>> f2.readline()  # readline是每次只读取一行,相当于迭代器,这样对于大文件来说不占用太多内存空间
'Rain雨\n'
>>> f2.readline()
'\n'
>>> f2.readline()
'Rain is falling all around, 雨儿在到处降落,\n'
>>> f2.readline()
'It falls on field and tree, 它落在田野和树梢, \n'
>>> 
>>> f2.readlines()  # readlines会把f2剩下的文本读取出来,形成列表的形式
['It rains on the umbrella here, 它落在这边的雨伞上,\n', 'And on the ships at sea. 又落在航行海上的船只。\n', 'hello world\n']
>>> f3.readlines()  # 当然,也可以一次性全部读取,形成列表
['Rain雨\n', '\n', 'Rain is falling all around, 雨儿在到处降落,\n', 'It falls on field and tree, 它落在田野和树梢, \n', 'It rains on the umbrella here, 它落在这边的雨伞上,\n', 'And on the ships at sea. 又落在航行海上的船只。\n', 'hello world\n']

4. 文件修改

文件修改的方式:

4.1 硬盘型

逐行读取readline,匹配后修改为新内容,把新内容写入到新文件中,如果内容过多,就flushall到硬盘中。然后把新文件重命名文老文件名(os.rename)。这种方式会比较占硬盘。

例:

import os
file = 'novel'
new_file = 'new_novel'
f1 = open(file, 'r+', encoding='utf-8')
f2 = open(new_file, 'w+', encoding='utf-8')
data = f1.readlines()

for line in data:
    keys = '雨伞'
    if keys in line:
        print("find 雨伞")
        f2.write(line.replace(keys, '花折伞'))
    else:
        f2.write(line)

f1.close()
f2.close()

os.remove(file)
os.rename(new_file, file) 
# 本来想直接rename的,结果在windows上报错了,只好先删除源文件,再重命名新文件,否则不成功。
但是在MAC和linux上直接执行rename是没有报错信息的,可以直接rename

4.2 内存型

把文件内容全部读入到内存中,在内存中修改好之后,重新写入到原来的文本里,把原来的内容全部覆盖掉
但是当文件非常大的时候,这种方式就不适合了。这种方式比较占内存,处理速度快。

file = 'novel'
fr = open(file, 'r+', encoding='utf-8')
data = fr.readlines()
fr.close()

# 重新以写的模式读入文本
fw = open(file, 'w', encoding='utf-8')
for line in data:
    keys = '雨伞'
    if keys in line:
        print("find 雨伞")
        fw.write(line.replace(keys, '花折伞'))
    else:
        fw.write(line)
fw.close()

5. with…open…as

当你做文件处理,你需要获取一个文件句柄,从文件中读取数据,然后关闭文件句柄。

正常情况下,代码如下:

file = open("/tmp/foo.txt")
data = file.read()
file.close()

这里有两个问题。一是可能忘记关闭文件句柄;二是文件读取数据发生异常,没有进行任何处理。

然而with可以很好的处理上下文环境产生的异常。下面是with版本的代码:

with open("/tmp /foo.txt") as file:
    data = file.read()

with的基本思想是with所求值的对象必须有一个enter()方法,一个exit()方法。紧跟with后面的语句被求值后,返回对象的enter()方法被调用,这个方法的返回值将被赋值给as后面的变量。当with后面的代码块全部被执行完之后,将调用前面返回对象的exit()方法。

6. 其它文件操作方法

指定读取size:

In [14]: f1 = open('novel', 'r')

In [15]: data = f1.read(10)

In [16]: data
Out[16]: 'Rain雨\n\nRai'

In [17]: f1.read()
Out[17]: 'n is falling all around, 雨儿在到处降落,\nIt falls on field and tree, 它落在田野和树梢, \nIt rains on the umbrella here, 它落在这边的花折伞上,\nAnd on the ships at sea. 又落在航行海上的船只。\nhello world\n'

In [18]: f1.close()

fp.flush() #把缓冲区的内容写入硬盘
fp.fileno() #返回一个长整型的”文件标签“
fp.isatty() #文件是否是一个终端设备文件(unix系统中的)
fp.tell() #返回文件操作标记的当前位置,以文件的开头为原点
fp.next() #返回下一行,并将文件操作标记位移到下一行。把一个file用于for … in file这样的语句时,就是调用next()函数来实现遍历的。
fp.seek(offset[,whence]) #将文件打操作标记移到offset的位置。这个offset一般是相对于文件的开头来计算的,一般为正数。但如果提供了whence参数就不一定了,whence可以为0表示从头开始计算,1表示以当前位置为原点计算。2表示以文件末尾为原点进行计算。需要注意,如果文件以a或a+的模式打开,每次进行写操作时,文件操作标记会自动返回到文件末尾。
fp.truncate([size]) #把文件裁成规定的大小,默认的是裁到当前文件操作标记的位置。如果size比文件的大小还要大,依据系统的不同可能是不改变文件,也可能是用0把文件补到相应的大小,也可能是以一些随机的内容加上去。记得文件要以’w’或’w+’模式打开。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值