Python中的文件和流

1.打开文件

open函数用于打开文件,通过该函数的第1个参数指定要打开的文件名(可以是相对路径,也可以是绝对路径)。

open函数的第2个参数用于指定文件模式(用一个字符串表示)。这里的文件模式是指操作文件的方式,如只读、写入、追加等

使用open函数打开文件时,默认是读模式,如果要想向文件中写数据,需要通过open函数的第2个参数指定文件模式。
在这里插入图片描述
写模式和追加模式的区别:如果文件存在,写模式会覆盖原来的文件,而追加模式会在原文件内容的基础上添加新的内容。

在文件模式中,有一些文件模式需要和其他文件模式放到一起使用,如open函数不指定第2个参数时,默认以读模式打开文本文件,也就是“rt”模式。如果以写模式打开文本文件,需要使用“wt”模式。对于文本文件来说,用文本模式(t)打开文件和用二进制模式(b)打开文件的区别不大,都是以字节为单位读写文件,只是在读写行结束符时有一定的区别。

在上表中,最后一项“+”文件模式,表示读写模式,必须与其他文件模式一起使用,如“r+”、“w+”、“a+”。这三个组合文件模式都可以对文件进行读写操作,它们之间的区别如下:

r+:文件可读写,如果文件不存在,会抛出异常;如果文件存在,会从当前位置开始写入新内容,通过seek函数可以改变当前的位置,也就是改变文件的指针。

w+:文件可读写,如果文件不存在,会创建一个新文件;如果文件存在,会清空整个文件,并写入新内容。

a+:文件可读写,如果文件不存在,会创建一个新文件;如果文件存在,会将要写入的内容添加到原文件的最后。也就是说,使用“a+”模式打开文件,文件指针会直接跳到文件的尾部,如果要使用read方法读取文件内容,需要使用seek方法改变文件指针,如果调用seek(0)会直接将文件指针移到文件开始的位置。

2.操作文件的基本方法

2.1 读文件和写文件

使用open函数成功打开文件后,会返回一个TextIOWrapper对象,然后就可以调用该对象中的方法对文件进行操作。TextIOWrapper对象有如下4个常用的方法。

write(string):向文件写入内容,该函数会返回写入文件的字节数。

read([n]):读取文件的内容,n是一个整数,表示从文件指针指定的位置开始读取的n个字节。如果不指定n,该函数会读取从当前位置往后的所有的字节。该函数会返回读取的数据。

seek(n):重新设置文件指针,也就是改变文件的当前位置。如果使用write函数写入内容后需要调用seek(0)才能读取刚才写入的内容。

close():关闭文件,对文件进行读写操作后,关闭文件是一个好习惯。

f = open('./files/test1.txt','w')   # 以 写 模式打开test1.txt文件
print(f.write("I love "))           # 向test1.txt文件中写入“I love ”, 运行结果  7
f.close()                           # 关闭test1.txt文件

f = open('./files/test1.txt','r')   # 以 读 模式打开test1.txt文件
print(f.read(7))                    # 从test1.txt文件中读取7字节的数据,运行结果 I love
f.close()

try:
    f = open('./files/test2.txt','r+')   # 如果test2.txt文件不存在,会抛出异常
except Exception as e:
    print(e)

# a+
f = open('./files/test2.txt', 'a+') # 用追加可读写模式打开test2.txt文件
print(f.write('hello'))             # 向test2.txt文件写入"hello",  运行结果 5
f.close();

f = open('./files/test2.txt','a+')
print('-----1------')
print(f.read())  # 读取向test2.txt文件的内容,由于目前文件指针已经在文件的结尾,所以什么都不会读出来
f.seek(0)        # 将文件指针设置到文件开始的位置
print('-----2------')
print(f.read())  # 读取文件的全部内容,运行结果   hello
f.close();

# w+
try:
    f = open('./files/test2.txt','w+')  # 用写入可读写的方式打开test2.txt文件,该文件的内容会清空
    print(f.read())                     # 读取文件的全部内容,什么都没读出来
    f.write('How are you?')             # 向文件写入"How are you?"
    f.seek(0)                           # 重置文件指针到文件的开始位置
    print(f.read())                     # 运行结果    How are you?
finally:
    f.close()                           # 关闭文件,建议在finally中关闭文件

2.2 管道输出

在Linux 、UNIX、Mac OS X等系统的shell中,可以在一个命令后面写另外一个命令,前一个命令的执行结果将作为后一个命令的输入数据,这种命令书写方式被称为管道,多个命令之间要使用 “|” 符号分隔。

例子: ps aux | grep mysql
在上面的管道命令中先后执行了两个命令,首先执行ps aux命令查看当前系统的进程以及相关信息,然后将查询到的数据作为数据源提供给grep命令,grep mysql 命令表示查询进程信息中所有包含mysql字样的进程。

在Python程序中,可以通过标准输入来读取管道传进来的数据,所以Python命令也可以使用在管道命令中。

# 管道输出
# 从标准输入读取所有的数据,并按行将数据保存到列表中,然后过滤出所有包含“readme”的行,并输出这些行
'''
ls -al ~ :列出home目录中所有的文件和目录。
python demo02.py :从管道接收数据(文件和目录列表),并过滤出所有包含readme的文件和目录。
sort:对过滤结果进行排序。
'''
import sys
import os
import re
# 从标准输入读取全部数据
text = sys.stdin.read()

#os.linesep字符串给出当前平台使用的行终止符
files = text.split(os.linesep)  # 将字符串形式的文件和目录列表按 行 拆分,然后保存到列表中
for file in files:
    result = re.match('.*readme.*',file)  # 匹配每一个文件名和目录名,只要包含"readme",就符合条件。
    if result != None:
        print(file)    # 输出满足条件的文件名和目录名
# 现在切换到控制台,进入demo02.py文件所在的目录,然后执行下面的命令。
ls -al ~ | python demo02.py | sort
# 执行上面的命令,根据home目录中的具体内容,会输出不同的结果。

2.3 读行和写行

读写一整行是纯文本文件最常用的操作,尽管可以使用read和write方法加上行结束符来读写文件中的整行,但比较麻烦。因此,要读写一行或多行文本,建议使用readline方法、readlines方法和writelines方法。注意:并没有writelines方法,写一行文本需要直接使用write方法。

readline方法用于从文件指针当前位置读取一整行文本,也就是说,遇到行结束符停止读取文本,但读取的内容包含行结束符。
readlines方法从文件指针当前的位置读取后面所有的数据,并将这些数据按行结束符分隔后,放到列表中返回。
writelines方法需要通过参数指定一个字符串类型的列表,该方法会将列表中的每一个元素值作为单独的一行写入文件。

# 读行与写行

import os
f = open('./files/urls.txt', 'r+')  # 以读写模式打开urls.txt文件
url = ''                            # 保存当前读上来的文本
while True:
    url = f.readline()          # 从urls.txt文件读一行文本
    url = url.rstrip()          # 将最后的行结束符去掉
    if url == '':               # 当读上来的是空串,结束循环
        break;
    else:
        print(url)              # 输出读上来的行文本
print('--------------')
f.seek(0)                        # 将文件指针重设置为0

print(f.readlines())                       # 读urls.txt文件中的所有行
f.write('http://baidu.com' + os.linesep)   # 向urls.txt文件中添加一个新行
f.close()                                  # 关闭文件

f = open("./files/urls.txt", 'a+')         # 使用“a+模式”再次打开urls.txt文件

# 定义一个要写入urls.txt文件的列表
urlList = ['https://google.com' + os.linesep,'https://jd.com' + os.linesep]

f.writelines(urlList)   # 将urlList写入urls.txt文件
f.close()              # 关闭urls.txt文件

结果:

https://geekori.com
https://geekori.com/que.php
http://ningedu.com
http://baidu.com
http://baidu.com
http://baidu.com
https://google.com
https://jd.com
http://baidu.com
--------------
['https://geekori.com\n', 'https://geekori.com/que.php\n', 'http://ningedu.com\n', 'http://baidu.com\n', 'http://baidu.com\n', 'http://baidu.com\n', 'https://google.com\n', 'https://jd.com\n', 'http://baidu.com\n', '\n', 'https://google.com\n', '\n', 'https://jd.com\n', '\n', 'http://baidu.com\n', '\n', 'https://google.com\n', '\n', 'https://jd.com\n', '\n']

Process finished with exit code 0

3.使用FileInput对象读取文件

如果需要读取一个非常大的文件,使用readlines函数会占用太多内存,因为该函数会一次性将文件所有的内容都读到列表中,列表中的数据都需要放到内存中,所以非常占用内存。
解决方法:

方法1. 可以使用for循环和readline方法逐行读取。
方法2. 可以使用fileinput模块中的input函数读取指定的文件。
input方法返回一个FileInput对象,通过FileInput对象的相应方法可以对指定文件进行读取,FileInput对象使用的缓存机制,并不会一次性读取文件的所有内容,所以比readlines函数更节省内存资源。

# 使用FileInput对象读取文件

# readlines

import fileinput
fileobj = fileinput.input('./files/urls.txt')  # 使用input方法打开urls.txt文件
print(type(fileobj))             # 输出fileobj的类型
 
print(fileobj.readline().rstrip())  # 读取urls.txt文件第1行

for line in fileobj:                # 通过for循环输出urls.txt文件的其它行
    line = line.rstrip()
    
    if line != '':                   # 如果file不等于空串,输出当前行号和内容        
        print(fileobj.lineno(),':',line)  
    else:
        # 输出当前正在操作的文件名
        print(fileobj.filename())   # 必须在第一行读取后再调用,否则返回None
    
    # 注意:filename方法必须在第1次读取文件内容后调用,否则返回None

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

少云清

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值