第九节 文件操作

1. 引言

  1. 将数据存储在变量序列和对象中,都是暂时的,程序结束之后就会消失,俗话说“好记性不如烂笔头”,计算机也是如此,一个程序执行之后需要将非常重要的结果,把数据存储起来就非常重要。
  2. 所以需要将数据,保存在 文件之中 才能永久存储,即使重启电脑,文件中的数据依旧还在,所以python提供了操作文件的对象。

2. 基本的文件操作

2.1 打开文件

  1. 思考一个问题? 把大象关进冰箱需要几步 ?
    • 打开冰箱。
    • 把大象放进去。
    • 关闭冰箱。
  2. python中操作文件也同上述案例差不多。
    • 新建文件, 或者 打开文件
    • 读 或者 写 数据。
    • 关闭文件。
  3. 文件打开语法格式: open(文件名[ ,访问模式])
    • 注意1:文件必须存在,否则会抛出异常
    • 注意2: 文件模式。
    '''
    文件的打开语法格式:
        open(文件名[,访问模式])
        文件名 必选参数
        访问模式 可选参数
    '''
    #注意1:文件如果不存在,会抛出异常.FileNotFoundError
    file = open("D://file.txt")
    print(file)#<_io.TextIOWrapper name='D://file.txt' mode='r' encoding='cp936'>
    

2.1.1 mode 访问模式

  1. 上述案例中,如果使用open函数打开文件时,只传入了文件名, 那么我们 只能读取文件
    • 要想在打开文件中写入数据, 就必须指明文件的 访问模式 。
    • rb,wb,ab 模式都是以二进制的方式操作文件,通常这几种模式用于处理二进制文件,如:声音,图像,视频等。
访问模式说明
r以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。
w打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
a打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
rb以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。这是默认模式。
wb以二进制格式打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
ab以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
r+打开一个文件用于读写。文件指针将会放在文件的开头。
w+打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
a+打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。
rb+以二进制格式打开一个文件用于读写。文件指针将会放在文件的开头。
wb+以二进制格式打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
ab+以二进制格式打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。如果该文件不存在,创建新文件用于读写。
  1. 需要注意的事项:
    • r , rb,r+,rb+ 文件必须存在。
    • w,wb,w+,wb+ 文件存在,则将其覆盖,否则创新文件。

2.1.2 文件不存在,则创建文件

  1. 打开一个 不存在的文件时,如果不指定访问模式会抛出异常。

    • FileNotFoundError
  2. 所以,打开一个文件时,如果文件不存在,需要先创建该文件。

    • 需要指定访问模式。指定参数为 w ,w+,a,a+ 这样,当打开的文件不存在时,就不会报错,可以新创建文件 (如果存在则覆盖)。
    #注意2:文件如果不存在,就会创建新文件,如果存在就覆盖(即使原来有数据).
    #指定了访问模式  w+ 
    	file = open("D://file1.txt",'w+')
    	print(file)#<_io.TextIOWrapper name='D://file1.txt' mode='w+' encoding='cp936'>
    

2.1.3 二进制打开文件

  1. open()函数不仅可以打开文本,而且还可以 使用二进制形式 打开非文本文件,例如:图片,音频,视频等
    • 使用二进制方式打开,如rb
#2.打开图片文件以二进制的方式。
	file = open('F://01.png','rb')
	print(file) #<_io.BufferedReader name='F://01.png'>

2.1.4 打开文件时,指定编码方式

  1. 纯文本文件 的编码格式有很多,有gbk,utf-8等。

    • 在打开文本文件时 也可以指定编码格式`
    • encoding=' 编码格式'
  2. open() 函数默认的是 gbk 编码, 所以当读取时 utf-8 的文本文件会乱码。
    在这里插入图片描述

    #2.打开文本文件open()默认的编码格式是gbk
    	file = open('D://01.txt','r').read()
    	print(file)
    
  • 读的结果,所以需要读时设置编码格式。
    在这里插入图片描述

    file = open('D://01.txt','r',encoding='utf-8').read()
    print(file)
    
    

    在这里插入图片描述

2.2 关闭文件

  1. 打开的文件,切记要使用close方法关闭。即使文件会在程序退出后自动关闭,但是考虑到数据的安全性,在每次使用完文件之后,都要使用close方法关闭文件,为什么要关闭?

    • 因为一旦程序崩溃很可能导致文件中的数据没有保存。
  2. close() 方法先刷新缓冲区中还有写入的信息, 然后再关闭文件,这样可以将没有写入文件的内容写入文件中。在关闭文件后,就不能进行写入操作了。

    #close关闭文件操作
    	file = open('D://01.txt','w')
    	file.close()#关闭文件
    

2.2.1 with 打开语句结构

  1. 打开文件后,要及时将其关闭。如果忘记关闭可能会带来意向不到的问题,所以为了避免类似事情发生,在python中使用with语句打开文件。

    with open('filename') as filewith-body
    
    • fileopen 的内容保存到 file 变量中。
    • 其中的with-body:用于指定with 语句体,可以执行一些相关的操作,如下操作。
    with open('D://01.txt',mode='r') as file:
        data = file.read() #使用file读取文件
        print(data)
    

2.3 文件的读写

2.3.1 写入文件内容

  1. 文件最重要的能力就是 接收数据或者提供数据。

    • 文件的读写,无非是将数据写入文件或者从文件中读取数据。
  2. 向文件中写入数据,需要使用 write 方法完成。

    • 在操作某个文件时,每调用一次write方法,写入的数据就 会追加到文件末尾。
  3. 操作步骤

    • 打开文件
    • 写入数据
    • 刷新数据
    • 关闭文件
    #打开文件,访问模式 w准备写
    	file = open('D://01.txt','w')
    # 写数据
    	file.write("你好,周杰伦")
    	file.write("\n") #换行
    	file.write("你的歌曲,夜曲")
    #刷新文件flush(),之后的流还可以使用。
    	file.flush()
    	file.write("暗号")
    	file.close()
    #file.write("七里香")#ValueError: I/O operation on closed file.
    
  • 访问模式是 mode 为 w 就是如果存在就覆盖,不存在就创建。
    在这里插入图片描述

2.3.2 读取文件

2.3.2.1 read()读取
  1. 文件对象提供了read()方法读取,语法格式:
    • 下列方法中的size表示要从文件中读取的数据长度,单位为字节。如果没有指定size, 那么就表示 读取文件的全部数据。
    	file.read(size)
    
  2. 注意在底层编码是不同的一个汉字和一个英文,但是在字符串中,使用read(1)时,读取汉字和英文都视为一个字节
    #r+读写, r只读
    with open('D://01.txt',mode='r+') as file:
        data = file.read(1)#读取第一个字符.
        print(data)
    
2.3.2.2 readline() 读取一行
  1. 在使用read()方法读取文件时,如果文件很大,一次读取全部内容到内存,容易造成内存不足,所以通常会采用逐行读取。

    • 文件对象提供了readline() 方法用于每次读取一行数据。
    file.readline()
    
  2. 每次读取一行。

    • 这样会发现一个问题,只能读一行。
    with open('d://01.txt',mode='r') as file:
        data  = file.readline()
        print(data)
    
  3. 怎么解决每次只读一行的问题 ?

    • readline()方法 如果没有读取,返回空字符串,循环结束。
#第一种方式使用while循环方式
	with open('d://01.txt',mode='r') as file:
	    line = file.readline()
	    #readline()会返回下一行
	    while line:
	        print(line)
	        #继续读取下一行
	        line = file.readline() #步长
	
	print("-"*40)
	
# 第二种处理方式使用for循序的方式
	with open('d://01.txt',mode='r') as file:
	    for line in file:
	        print(line)
2.3.2.3 readlines() 读取全部行
  1. read()不使用size一样, 读取全部,但是 不同处在于 返回的是一个列表。
    #返回的是一个列表
    with open('d://01.txt',mode='r') as file:
        data = file.readlines()
        print(data)
    
  2. 这样相当于同 read() 读取的方法一样了。
    • 所以,用readline()一样,使用循环读取。
    with open('d://01.txt', mode='r') as file:
        data = file.readlines()#返回一个列表
        for i in data: #遍历列表
            print(i)
    
    

2.3.3 备份案例的三种方式

  1. 在实际操作中,文件的 读写可以已完成很多功能,像 文件的备份 就是文件的读写功能的应用。
    • 需求, 读取一个文件内容,将文件写入到另一个磁盘中进行备份,相当于文件的 Ctrl+C ,Ctrl+V。
2.3.3.1 纯文本文件
  1. 第一种备份情况,使用读写操作进行。
    • 如果是纯文本文件,需要注意使用 读写编码,使用同一个文本格式。
    '''
    1.原生读写备份
        1.源文件-->备份文件
        2.目的文件
    注意编码: 如果是存文本格式,同一使用 r和 w
            同一使用编码格式,encoding='utf-8'
    '''
    #源文件
    old_file="D://三年级上.txt"
    #目的文件
    new_file="D://backup_三年级上.txt"
    
    #打开源文件,r 只读
    with open(old_file,mode='r',encoding='utf-8') as source:
        #读取源文件
        data = source.read()
    
    #创建文件进行写入 w 文件不存在就创建.
    with open(new_file,mode='w',encoding='utf-8')  as target:
        target.write(data)
    
    print("文件写入成功!")
    
2.3.3.2 二进制文件
  1. 如果备份视频,图片,就需要使用二进制读写,上述的纯文本形式就不能实现了。

    • 访问模式 就需要使用二进制 rb 和 wb
    • 二进制就不需要 使用编码格式 encoding='gbk'可以省略。
    '''
    2. 备份视频,图片等.
    '''
    # 源文件,压缩文件
    old_file = "D://day06.rar"
    # 目的文件
    new_file = "D://backup_day06.rar"
    # 以二进制方式打开源文件,省略编码格式 encoding='utf-8'
    with open(old_file, mode='rb') as source:
        # 读取源文件
        data = source.read()
    # 创建文件进行写入 wb文件不存在就创建.
    with open(new_file, mode='wb')  as target:
        target.write(data)
    #最后提示程序
    print("以二进制形式备份成功!")
    
2.3.3.3 函数备份
  1. 在之前我们学过函数了,写程序设计需要封装方法,接下来备份程序使用函数操作。
    • 将上述代码封装到函数中。
    '''
    封装函数万能备份.
    '''
    def backup_file(old_file,new_file):
        # 以二进制方式打开源文件,省略编码格式 encoding='utf-8'
        with open(old_file, mode='rb') as source:
            # 读取源文件
            data = source.read()
        # 创建文件进行写入 wb文件不存在就创建.
        with open(new_file, mode='wb')  as target:
            target.write(data)
        #最后提示程序
        print("备份成功!")
    
    #函数调用
    a = "D://三年级下.txt"
    b = "D://back_up_三年级下.txt"
    #传递参数
    backup_file(a,b)
    
    • 使用python自带的函数copytree()方法进行备份。
    import shutil #导入python自带函数库
    a = "D://01"
    b = "D://01_backup"
    #可以复制文件夹,及其子目录
    shutil.copytree(a,b)
    print("执行完毕")
    
    

2.3.4 文件的定位读写

  1. 文件的读写都是从文件的头开始,到文件的尾巴结束,但是在实际的开发中,可能需要从文件的某个特定位置开始读写,这时候就需要对文件的读写位置进行定位
  2. tell() 用于 获取当前位置seek() 用于 设置新的位置
    • 它们一起使用,可以使我们在文件处理过程中 自由地控制和定位文件指针的位置。
2.3.4.1 tell() 方法获取定位
  1. 在文件的读写过程中,想知道文件读取到了 文件的哪个位置, 则可以使用 tell() 方法来获取,

    • 该方法会返回文件的指针的当前内容。abcdefgabcdefg
    • 每次的读取位置都会累计,直到读取最大长度为止。
    '''
    1.文件定位读写 
    abcdefgabcdefg
    '''
    # 打开一个文件
    with open("D://02.txt", mode='r', encoding='utf-8') as file:
        data = file.read(5)#read(size)
        print(data)
        position = file.tell()
        print(position)
        data = file.read(10) #最大长度就是14个 超过就按最大算
        print(data)
        # 查找当年位置
        position = file.tell()
        print(position)
    
    • 输出结果
    	abcde
    	5
    	fgabcdefg
    	14
    
2.3.4.2 seek()方法指定位置
  1. 如果要从指定的位置开始读取或者写入文件上的数据,则使用seek() 方法实现。
    • 可以指定开始的位置
    '''
    1.文件定位读写
    '''
    # 打开一个文件
    with open("D://02.txt", mode='r', encoding='utf-8') as file:
        data = file.read(10)#read(size)
        print(data)
        position = file.tell()
        print(position)
        print("-"*40) #华丽的分割线
        #从新定位在第8个字符
        file.seek(8)
        #定位之后从新获取,从第8个开始在读3个字符
        data2 =file.read(3)
        print(data2)
        position = file.tell()
        print(positio
    
  • 输出结果:

    abcdefgabc
    10
    ----------------------------------------
    bcd
    11
    

3. python中os模块

  1. python中的内置os模块除了可以对 目录进行操作,还可以对文件 进行一些高级操作:
    • 具体常用函数如下:
函数说明
remove(path)删除path指定的文件路径
rename(src,dst)将文件或目录src,重命名为dst
stat(path)返回path指定文件信息
mkdir(path)创建一个新文件目录
getcwd()返回当前工作目录
abspath()os.path 模块提供,用于获取文件或者目录的绝对路径
exists()os.path 模块提供,判断文件夹是否存在
rmdir()os 模块提供,删除为空的最后一级文件目录
listdir(path)os 模块提供,列出当前目录列表。

3.1 文件和目录,重命名

  1. os 模块 是 Python 中用于与操作系统进行交互的标准库模块,通过 os 模块, 程序中执行系统命令、访问环境变量、操作文件和目录等。

3.1.1 rename() 重命名

  1. OS 模块 中提供的 重命名文件和目录 rename(src,dst)的函数。

    • 注意1: 如果是指定的路径,是文件,则重命名文件,如果指定的,是目录,则重命名目录
  2. 重命名目录和文件名。

    • 使用前注意导入库,import os
    • 如果 修改的源文件不存在,则抛出异常FileNotFoundError: [WinError 2] 系统找不到指定的文件。
    import os  # 使用os模块
    # 指定文件
    os.rename("D://python.txt", "D://python_修改.txt")
    # 指定目录
    os.rename("D://python", "D://python_修改")
    print("执行成功")
    

3.2 文件,删除操作

  1. OS模块中的remove()操作可以对文件进行移除。
    • 使用时需要先导入函数模块 import os
    os.remove("D://python_修改.txt")
    print("移除成功")
    

3.3 文件目录,相关操作

3.3.1 路径概述

  1. 用于定位一个 文件或者目录的字符串 被称为一个路径,通常路径有两种:
    • 相对路径,通常使用的 一些符号及其符号所代表的意义 概述如下:
      • “./”:表示当前的文件所在的目录。
      • “…/”:表示当前的文件所在的上一层的目录。
      • “/”:表示当前的文件所在的根目录。
    • 绝对路径,指文件具体的物理位置 C://user/root/1.txt
3.3.1.1 相对路径
  1. 如何理解相对路径,可以通过我们操作pycharm工程中的文件来举例子:
    • 例如:在工程中 创建一个1.txt文件,其实该文件的 绝对路径D://commsoft/pythonprogect/day01/1.txt,但是我们在工程中只需要使用相对路径即可访问。
    • 输出当前目录print(os.getcwd()) ,注意到如 OS 模块。
      在这里插入图片描述
3.3.1.2 绝对路径
  1. 绝对路径是指在使用文件时指定的实际路径,它不依赖当前的工作目录,使用os.path 模块提供的adspath()方法。
    • 使用os.path.asbpath(path)
    #返回绝对路径,os.path.asbpath(path)
    with open("../1.txt", encoding="utf-8") as file:
        data = file.read()  # 我是周杰伦
        print(os.path.abspath("../1.txt")) #D:\commonSoft\fileproject\1.txt
        print(data)
    
3.3.1.3 拼接路径
  1. 使用os.path.join()拼接路径的好处就是可以正确的处理不同路径之间的分隔符。

    • 如果直接使用+ 号连接两个路径中奖必须使用分隔符+“/” , 但是如果使用拼接os.path.join(),就可以省略考虑连接问题。
    • 以下为代码片段
        print(file_path+file_name)
        print(file_path+new_name)
        print("-"*40)
        print(os.path.join(file_path,file_name))
        print(os.path.join(file_path,new_name))
    
    • 输出结果:
    D:/记录表[吴琼老师]-新建文本文档 - 副本 (3).txt
    D:/记录表[吴琼老师]-[吴琼老师]-新建文本文档 - 副本 (3).txt
    D:/记录表\[吴琼老师]-新建文本文档 - 副本 (2).txt
    D:/记录表\[吴琼老师]-[吴琼老师]-新建文本文档 - 副本 (2).txt
    
    

3.3.2 判断目录和文件,是否存在

  1. 在实际程序开发中,需要对文件夹进行一些操作,如新建文件夹,但是在新建之前需要判断,该目录是否存在。

    • 需要使用os.path 模块中的 exists(path) 方法。
    import os
    #使用 os.path 模块中的 exists()方法
    	a = os.path.exists("D://os创建")
    	print(a) #如果存在返回True反之 false
    
  2. 如果将判断的目录该为文件,就可以判断文件是否存在。

    import os
    #使用 os.path 模块中的 exists()方法,可以用于判断文件是否存在
    	a = os.path.exists("D://python.pdf")
    	print(a) #如果存在返回True反之 false
    

3.3.3 创建文件(一级和多级)目录

  1. 如何创建一个文件目录,os模块中给出了两个创建目录的函数,一个用于创建一级目录,另一个用于创建多级目录

    • 创建单级目录,使用 mkdir(path)
    ##1.使用os模块进行创建os.mkdir()
    	# a = os.mkdir("D://os创建")
    	# #FileExistsError: [WinError 183]
    	# print(a) #如果存在则会报异常
    
    #2.所以在创建时需要判断exists()方法使用
    	if not os.path.exists("D://os创建"):
    	    #不存在则创建
    	    os.mkdir("D://os创建")
    	    print("目录创建成功")
    	else:
    	    print("该目录已经存在")
    
  2. 如何创建多级目录,需要使用os模块中的 makedirs(path) 函数。

    import os #导入模块os
    #判断文件夹是否存在
    	if not os.path.exists("D://1//2//3"):
    	    os.makedirs("D://1//2//3")
    	    print("创建成功")
    	else:
    	    print("文件已创建")
    

3.3.4 删除目录

  1. os模块的中提供了删除目录的方式。
    • 只能删除 为空的目录,删除时 记得判断目录
    import os
    if os.path.exists("D://1//2//3"):
        #如果存在则删除,只能删除为空目录
        os.rmdir("D://1//2//3")#删除//3目录
        print("删除成功")
    else:
        print("目录不存在")
    
  2. 如果想删除多级目录怎么办?
    • 则需要使用 shutil模块中的函数rmtree()谨慎使用
    import shutil # 导入shutil模块
    # 该操作谨慎使用。
    shutil.rmtree("D://1") #将D盘 1文件和子目录都删除掉
    print("删除成功")
    

3.3.5 列出目录列表

  1. 显示当前目录中的内容,只能显示当前级。
    • 相当于列出同级列表中的内容,如windows 中的dir
    	#列出D:// 目录下 , 所有内容.
    	a = os.listdir("D://")
    	print(a) 
    

3.3.6 遍历目录内容

  1. 遍历同循环有相同的意思,输出该目录和子目录中所有内容。

    • 使用os模块中的 walk()函数。
    import os
    data = os.walk("D://1")
    print(type(data),data)#<generator object walk at 0x000001EFDEA5BBA0>
    
    #需要遍历输出内容
    for i in data:
        print(i) #循环遍历每一级目录,并输出目录中内容.
    
  2. 在生成器对象上进行循环遍历时,可以使用多个变量来接收生成器对象返回的内容。os.walk()函数每次返回三个值, 分别是

    • 当前目录路径、当前目录下的所有子文件夹名称列表、当前目录下的所有文件名称列表。通过使用三个变量(i, j, k)来接收这三个值,对应的意义如下:

      • 变量 i:当前目录路径,即根目录路径。
      • 变量 j:当前目录下的所有子文件夹名称列表。
      • 变量 k:当前目录下的所有 文件名 称列表。
    import os
    
    data = os.walk("D://1")
    print(type(data), data)  # <generator object walk at 0x000001EFDEA5BBA0>
    
    # 需要遍历输出内容,使用os.path.join拼接字符串
    for i, j, k in data:
        # 显示目录
        for a in j:
            print(os.path.join(i, a))
        # 显示具体文件
        for a in k:
            print(os.path.join(i, a))
    
    

4.综合案例:

4.1 复制并修改文件名

  1. 要求复制文件,并且从新命名,命名为 : 复制_源文件名称。
    • 提示1: 涉及一个拼接文件名称操作。
    • 提示2: 截取源文件名称操作。
    #备份方法
    def backup(old_file):
        #打开文件.
        with open(old_file, mode='rb') as file_old:
            data = file_old.read() #读取文件
    
        if old_file:#判断文件是否为空
            file_name = old_file.rfind(".")  # 找文件中.从后面找第一个出现
            if file_name > 0:  #判断长度.
                file_type = old_file[file_name:]  #切片[start:)截取文件类型
                # 拼接新文件: 文件名old_file[:file_name]+_复制_+文件类型
                new_file = old_file[:file_name]+ "--复制" + file_type
            with open(new_file, mode='wb') as file_new:
                file_new.write(data)  # 将旧文件内容写入到新文件中.
        return True
    
    # 调用方法
    backup("D://三年级下.txt")
    

4.2 批量修改文件名

  1. 如果一个个单独修改文件名,修改的文件如果很多,则效率显然是底下的,这时我们就需要借助刚学习的文件操作,编写一个批量修改的小程序。

  2. 假设现在有一批文件的名称需要批量修改,查看下列修改前后的对比。

    import os
    
    file_path = "D:/记录表"  # 操作文件路径
    dir_list = os.listdir(file_path)  # 显示文件路径
    # 遍历所有文件名称
    for file_name in dir_list:
        # 创建一个标识,根据标志进行操作.
        new_name = '[吴琼老师]-' + file_name
        #1.拼接路径,
        # old_file = file_path+"\\"+ file_name  # 源文件路径
        # new_file = file_path+"\\"+ new_name  # 新文件路径
        #2.也可以使用拼接字符串os.path.join()
        old_file = os.path.join(file_path,file_name)
        new_file = os.path.join(file_path,new_name)
        #重命名
        os.rename(old_file,new_file)
    

    在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

吴琼老师

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

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

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

打赏作者

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

抵扣说明:

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

余额充值