21.Python 操作文件

目录

    • 1. 认识文件和I/O
    • 2. 打开文件
      • 在异常处理语句中打开
      • 在上下文管理中打开
    • 3.读取文件
    • 3. 写入文件
    • 4. 删除文件
    • 5. 复制文件
    • 6. 重命名文件
    • 7. 文件查找和替换

1. 认识文件和I/O

文件是存储在设备上的一组字符或字节序列,可以包含任何内容,它是数据的集合和抽象。

文件包含两种类型:

  • 文本文件:一般由单一特定编码的字符组成。
  • 二进制文件:直接由二进制0和1组成,文件内部数据的组织格式与文件用途有关。

主要区别在于是否有统一的字符编码;都可以使用文本文件方式和二进制文件方式打开,但打开后的操作不同。采用文本方式打开文件,文件经过编码形成字符串;采用二进制方式打开文件,文件被解析为字节流。

I/O 在计算机中是指 Input/Output,也就是Stream(流)的输入和输出。输入和输出是相对于内存来说的,Input Stream(输入流)是指数据从外(磁盘、网络)流进内存,Output Stream(输出流)是数据从内存流出到外面(磁盘、网络)。当程序运行时,数据都是在内存中驻留,由CPU这个超快的计算核心执行,涉及数据交换的地方就需要I/O接口,如磁盘操作、网络操作等。

文件描述符是读写文件时请求操作系统打开的一个对象,也就是程序中要操作的文件对象。

不同编程语言读写文件的操作步骤大体一样:

  1. 打开文件,获取文件描述符。
  2. 操作文件描述符,如读/写。
  3. 关闭文件。

文件读写操作完成后,应该及时关闭。一方面,文件对象占用操作系统的资源;另一方面,操作系统对同一时间打开的文件描述符的数量时有限制的,如果不及时关闭文件,可能会造成数据丢失。因为将数据写入文件时,操作系统不会立刻把数据写入磁盘,而是先把数据放到缓冲区异步写入磁盘。当调用close()方法时,操作系统保证把没有写入磁盘的数据全部写到磁盘上,否则可能丢失数据。

除了内置函数open()外,还可以通过如下途径对本地文件系统进行操作。

  • os模块:是一个与操作系统进行交互的接口,可以直接对操作系统进行操作,直接调用操作系统的可执行文件、命令。os模块包含文件系统和进程管理。
  • os.path模块:提供一些与路径相关的操作函数。
  • stat模块:能解析os.stat()os.fstat()os.lstat()等函数返回的对象的学习,也就是能获取文件的系统状态信息(文件属性)
import os # 导入os模块
from os import path # 从os模块中导入path子模块

2. 打开文件

使用内置函数open()可以打开文件,如果指定文件不存在,则创建文件,如果该文件无法打开,会抛出OSError。

fileObj = open(fileName,mode='r',buffering=-1,encoding=None,
							 errors=None,newline=None,closedfd=True,opener=None)

open()函数共包含8个参数,除了第一个参数fileName必须设置外,其它参数都有默认值,可以省略。

  1. fileName:设置打开的文件名,包含所在路径,也可设置文件句柄。

  2. mode:打开模式,即操作权限,使用字符串表示,‘r’、‘w’、‘x’、‘b’可以和’b’、‘t’、‘+'组合使用,打开模式及其组合说明如下:

文件格式相关参数:可以与其它模式参数组合使用,用于指定打开文件的格式,需要根据文件类型进行选择。

  • ‘t’:文本模式。默认以文本格式打开文件。一般用于文本文件。
  • ‘b’:二进制模式。以二进制格式打开文件。一般用于非文本文件,如图片等。

通用读写模式相关参数:可以与文本格式参数组合使用,用于设置基本读、写操作权限,以及文件指针初始位置。

  • ‘r’:只读模式。默认。以只读方式打开一个文件,文件指针被定位到文件头位置。如果文件不存在会报错。
  • ‘w’:只写模式。打开一个文件只用于写入。如果文件已存在,则打开文件,清空文件内容,并把文件指针定位到文件头位置开始编辑;如果该文件不存在,则创建新文件,打开并编辑。
  • ‘w’:追加模式。打开一个文件用于追加,仅有只写权限,无权读操作。如果该文件已存在,文件指针被定位到文件尾位置。新内容被写入到原内容之后;如果该文件不存在,创建新文件并写入。

特殊读写模式相关参数

  • ‘+’:更新模式。打开一个文件进行更新,具有可读、可写权限。注意该模式不能单独使用,需要与r、w、a模式组合使用。打开文件后,文件指针的位置由r、w、a组合模式觉得。
  • ‘+’:新写模式。新建一个文件,打开并写入内容,如果该文件已存在则报错。

组合模式:文件格式与通用读写模式可以组合使用,另外,通过组合+模式可以为只读、只写模式增加写、读的权限。

r 模式组合

  • ‘r+’:文本格式读写。以文本格式打开一个文件用于读、写。文件指针被定位到文件头的位置。新写入的内容被覆盖原有文件部分或全部内容;如果文件不存在则报错。
  • ‘rb’:二进制格式只读。以二进制格式打开一个文件,只能够读取。文件指针被定位到文件头的位置。一般用于非文本文件,如图片等。
  • ‘rb+’:二进制格式读写。以二进制格式打开一个文件用于读、写。文件指针被定位到文件头位置。新写入的内容将覆盖原有文件部分或全部内容;如果文件不存在则报错。一般用于非文本文件。

w 模式组合

  • ‘w+’:文本格式写读。以文本格式打开一个文件用于写、读。如果该文件已存在,则打开文件,清空原有内容,进入编辑模式;如果该文件不存在,则创建新文件,打开并执行写、读操作。
  • ‘w+’:二进制格式只写。以二进制格式打开一个文件,只能够写入。如果该文件已存在,则打开文件,清空原有内容,进入编辑模式;如果该文件不存在,则创建新文件,打开并执行只写操作。一般用于非文本文件。
  • ‘wb+’:二进制格式写读。以二进制格式打开一个文件用于写、读。如果该文件已存在,则打开文件,清空原有内容,进入编辑模式;如果该文件不存在,创建新文件,打开并执行写、读操作。一般用于非文本文件。

a 模式组合

  • ‘a+’:文本格式读写。以文本格式打开一个文件用于读、写。如果文件已存在,则打开文件,文件指针被定位到文件尾位置,新写入的内容添加在原有内容的后面;如果该文件不存在,则创建新文件,打开并执行写、读操作。
  • ‘ab’:二进制格式只写。以二进制格式打开一个文件用于追加写入。如果该文件已存在,则打开文件,文件指针被定位到文件尾位置,新写入的内容在原有内容的后面;如果该文件不存在,创建新文件,打开并执行只写操作。
  • ‘ab+’:二进制格式读写。以二进制格式打开一个文件用于追加写入。如果该文件已存在,则打开文件,文件指针被定位到文件尾位置,新写入的内容在原有内容的后面;如果该文件不存在,创建新文件,打开并执行写、读操作。
  1. buffering:设置缓冲方式。0表示不缓冲,直接写入磁盘;1表示行缓冲,缓冲区碰到\n换行符时写入磁盘;如果为大于1的正整数,则缓冲区文件大小达到该数字大小时写入磁盘;如果为负值,则缓冲区的缓冲大小为系统默认。

  2. encoding:指定文件的编码方式,该参数只在文本模式下使用。

  3. errors:报错级别。

  4. newline:设置换行符(仅适用于文本模式)。

  5. closefd:布尔值,默认为True,表示fileName参数为文件名(字符串型);如果为False,则fileName参数为文件描述符。

  6. opener:传递可调用对象。

# 新建一个test.txt文件,内容包含‘中国’,执行以下命令以文本文件和二进制文件打开
f = open('test.txt','rt',encoding='utf-8') # t表示文本格式方式
print(f.readline()) # 输出:中国
f.close() # 文件使用结束后要关闭,释放文件的使用授权
f = open('test.txt','rb') # b表示二进制格式方式
print(f.readline()) # 输出:b'\xe4\xb8\xad\xe5\x9b\xbd'
f.close() # 关闭文件

在异常处理语句中打开

使用异常处理机制打开文件的方法:在try语句块中调用open()函数,在except语句块中妥善处理文件操作异常,在finally语句块中关闭文件。

fileName = 'test1.txt' # 创建的文件名
try:
    fp = open(fileName,'w+') # 创建文件,w+ 模式打开文件,如果不存在,则创建,不会抛出异常
    print('%s 文件创建成功'%fileName) # 提示创建成功
except IOError:
    print('文件创建失败,%s 文件不存在'%fileName) # 提示创建失败
finally:
    fp.close() # 关闭文件
# 输出:test1.txt 文件创建成功

fileName = 'test2.txt'
try:
    fp = open(fileName,'r') # r 模式只能打开已存在的文件,当打开不存在的文件时,抛出异常
except IOError:
    print('文件创建失败,%s 文件不存在'%fileName) # 提示创建失败
finally:
    fp.close() # 关闭文件
# 输出:文件创建失败,test2.txt 文件不存在

在上下文管理中打开

with语句时一种上下文管理协议,是文件操作的通用结构。它能简化try…except…finally异常处理机制的流程,语法和示例如下:

'''
with open(文件) as file对象:
		操作file对象
'''
with open('test.txt','r',encoding='utf-8') as file: # 打开文件
    for line in file.readlines(): # 迭代每行字符串
        print(line) # 打印每一行字符串

3.读取文件

使用file对象的readline()readlines()read()方法可以读取文件的内容。

  • file.read(size=-1):从文件中读取整个文件内容。参数可选,如果给出,读取前size长度的字符串或字节流。
  • file.readline(size=-1):从文件中读取一行内容,包含换行符。参数可选,如果给出,读取该行前size长度的字符串或字节流。
  • file.readlines(hint=-1):从文件中读取所有行,以每行为元素形成一个列表。参数可选,如果给出,读取hint行。
  • file.seek(offset[,whence]):改变当前文件操作指针的位置,参数offset表示需要移动偏移的字节数;参数whence表示偏移参照点,默认值为0,表示文件的开头;当值为1时,表示当前位置;当值为2时,表示文件的结尾。
f = open('test.txt','r',encoding='utf-8')
s = f.read()
print(s) # 显示内容
print(f.tell()) # 获取文件对象的当前指针位置
f.seek(0) # 改变指针到文件头位置
print(f.tell()) # 查看指针位置
ls = f.readlines() # 读取
print(ls) # 打印内容,列表存储:['北京\n', '人生苦短,我爱python\n', '我是five']
f.close() # 关闭

file对象内部记录文件指针的位置,以便下次操作。只要file对象没执行close()方法,文件指针就不会释放。

使用forwhile循环遍历文件

# for
f = open('test.txt','r',encoding='utf-8')
for line in f:
    print(line)
f.close()
# while
f = open('test.txt','r',encoding='utf-8')
while True: # 执行无限循环
    line = f.readline() # 读取每行文本
    if line: # 如果不是尾行,则显示读取的文本
        print(line)
    else: # 如果时尾行,则跳出循环
        break
f.close() # 关闭

3. 写入文件

使用文件对象的write()writelines()方法可以为文件写入内容。

  • f.write(s):向文件写入一个字符串或字节流,并返回写入的字符长度。
  • f.writelines(lines):将一个元素为字符串的列表写入文件。

writelines()方法不会换行写入每个元素,如果换行写入每个元素,就需要手动添加换行符\n。使用该方法写文件的速度更快。如果需要写入文件的字符串非常多,可以使用writelines()方法提高效率;如果只需要写入少量的字符串,直接使用write()方法即可。

ls = [
    ['指标','2014年','2015年','2016年'],
    ['居民消费价格指数','102','101.4','102'],
    ['食品','103.1','102.3','104.6'],
    ['烟酒及用品','994','102.1','101.5'],
    ['衣着','102.4','102.7','101.4'],
    ['家庭设备用品','101.2','101','100.5'],
    ['医疗保健和个人用品','101.3','102','101.1'],
    ['交通和通信','99.9','98.3','98.7'],
    ['游乐教育文化','101.9','101.4','101.6'],
    ['居住','102','100.7','101.6'],
]
f = open('cpi.csv','w',encoding='utf-8') # w 模式,存在文件,则清空内容,不存在则新建
for row in ls:
    f.write(','.join(row)+'\n')
f.close()

逗号分隔的存储格式叫做CSV格式,常见通用的相对简单的文件格式,一维数据保存成CSV格式后,各元素采用逗号分隔,形成一行。二维数据由一维数据组成,每一行时一维数据,整个CSV文件时一个二维数据

# 转换为二维列表对象,再进一步打印成表格形状
f = open('cpi.csv','r') # r 默认打开文本文件
ls = [] # 定义空列表
for line in f:
    ls.append(line.strip('\n').split(',')) # 去除换行符 逗号分隔符分隔
f.close() # 关闭
print(ls) # 打印数据列表
print('-'*100) # 分隔区分
for row in ls: # 遍历列表
    line = '' # 定义空字符串
    for item in row:
        line += '{:10}\t'.format(item) # 指定宽度格式化打印
    print(line) # 遍历打印

21.Python 操作文件_第1张图片

4. 删除文件

删除文件需要使用os模块,调用os.remove()方法可以删除指定的文件。

在删除文件之前需要先检测文件是否存在。如果文件不存在,直接进行删除操作,将抛出异常。调用os.path.exists()方法可以检测指定的文件是否存在。

import os # 导入os模块
f = 'test2.txt' # 指定要操作的文件
if os.path.exists(f): # 判断文件是否存在
    os.remove(f) # 存在则删除文件
    print('%s 文件删除成功'% f) # 提示删除成功
else: # 不存在则提示
    print('%s 文件不存在'% f)

5. 复制文件

文件对象没提供直接复制文件的方法,但是可以使用read()write()方法,可以间接实现复制文件的操作。

music_name = '火车日记.mp3' # 定义文件名
with open(music_name,'rb') as music: # 以字节流方式打开文件,赋予读权限
    new_name = 'a.mp3' # 定义复制后的文件名
    with open(new_name,'wb') as new_music: # 以字节方式打开文件,赋予写权限
        buffer = 1024 # 定义一次读1024字节
        while True: # 循环读取
            content = music.read(buffer) # 读取内容
            if not content: # 当文件读取结束
                break # 跳出循环
            new_music.write(content) # 写内容

shutil 模块是另一个文件、目录的管理接口,提供了一些用于复制文件、目录的方法。其中,copyfile()方法可以实现文件的复制,copyfile(src,dst),该方法把src指向的文件复制到dst指向的文件。参数src表示源文件的路径,参数dst表示目标文件的路径,两个参数都是字符串类型。

6. 重命名文件

使用os模块的rename()方法可以对文件或目录进行重命名。

'.'表示当前目录,os.listdir()方法能够返回指定目录包含的文件和子目录的名字列表。

import os
path = os.listdir('.') # 获取当前目录下所有文件或文件夹名称列表
print(path) # 显示列表:['a.mp3', 'cpi.csv', 'test1.txt', '火车日记.mp3', 'test.txt', 'open_file.ipynb']
if 'test1.txt' in path: # 如果存在test1.txt
    os.rename('test1.txt','test2.txt') # 将test1.txt改名为test2.txt
elif 'test2.txt' in path: # 如果存在test2.txt
    os.rename('test2.txt','test1.txt') # 将test2.txt改为test1.txt

在实际中,通常需要把某一类文件修改为另一种类型,即修改文件的扩展名。

# 把扩展名为htm的文件修改为html
import os
path = os.listdir('.') # 获取当前目录下所有文件或目录名称列表
for filename in path: # 遍历当前目录下所有文件
    pos = filename .find('.') # 获取文件扩展名前的点号下标位置
    if filename[pos+1:] == 'htm': # 如果文件扩展名为htm
        newname = filename[:pos+1] + 'html' # 定义新的文件名,改扩展名为html
        os.rename(filename,newname) # 重命名文件

7. 文件查找和替换

文件内容的搜索和替换可以结合字符串查找和替换来实现。

# 新建一个文件filtered_words.txt,包含'程序员、北京朝阳、上海'内容
def filterwords(file_name): # 定义敏感词过滤函数
    with open(file_name,'r') as f:
        content = f.read()
        word_list = content.split('\n') # 将文件内容转换成列表格式
        print('脱敏前:',word_list)
        text = input('敏感词过滤:') # 输入测试内容
        new_word_list = [] # 定义一个新列表
        for word in word_list: # 遍历敏感词列表
            if text in word: # 测试内含敏感词
                length = len(text) # 获取敏感词长度
                word = word.replace(text,'*'*length) # 用*替换敏感词
            new_word_list.append(word) # 内容追加
        return '脱敏后:'+str(new_word_list) # 返回脱敏后内容
file = 'filtered_words.txt'
print(filterwords(file))
'''
脱敏前: ['程序员、北京朝阳、上海']
脱敏后:['程序员、**朝阳、上海']
'''

新建一个test3.txt文件,内容如下图,然后从中查找字符串’five’,并统计出现的次数;替换其中的’five’字符串为’python’

21.Python 操作文件_第2张图片

# 查找
import re # 导入正则模块
f1 = open('test3.txt','r') # 以只读模式打开文件
count = 0 # 定义计数变量
for s in f1.readlines(): # 读取文件每一行字符串,然后迭代
    li = re.findall('five',s) # 在每行字符串搜索字符串'five'
    if len(li) > 0: # 如果字符串长度大于0,说明存在指定字符串
        count = count + li.count('five') # 累计求和出现次数
print('查找到',str(count),'个five') # 输出显示字符串出现次数
f1.close() # 关闭
# 输出:查找到 9 个five

# 替换
f1 = open('test3.txt')
f2 = open('test4.txt','w')
for i in f1.readlines():
    f2.write(i.replace('five','python')) # 替换
f1.close()
f2.close()

你可能感兴趣的:(Python,python)