文件操作的初识

  • 用 python 代码对文件进行各种操作。

    基本构成:

    • 文件路径:path
    • 打开方式:读、写、追加、读写、写读……
    • 编码方式:utf-8 / gbk / gb2312……
    f = open('文件路径或者相对路',encoding='编码方式',mode='模式')	# 格式构成
    cotent = f.read()
    print(content)
    f.close()
  • 代码解释:

    • open:

      ​ 内置函数,open 底层调用的是操作系统的接口。

    • f:

      ​ 变量,约定俗成的变量名有(f1,fh,file_handler,f_h),这个变量还有一个名字,叫文件句柄。对亠件进行的任何操作,都得通过文件句柄加'.'的方式。

    • encoding:

      ​ 可以不写,如果不写,默认的编码本就是系统默认的编码。

      ​ Windows: gkb

      ​ Linux: utf-8

      ​ MacOS: utf-8

    • mode:

      ​ 就是定义你的操作方式:r 为读模式。

    • f.read():

      ​ 你想操作文件,比如读文件,给文件写内容,等等,都必须通过文件句柄进行操作。

    • f.colse():

      ​ 关闭文件。(必须关闭,否则会常驻内存。)

  • 文件操作的三个步骤:

    • 打开文件。

    • 对文件句柄进行相应的操作。

    • 关闭文件。

      # 打开文件,得到文件句柄并赋值给一个变量
      f = open('文件.txt', 'r', encoding='utf-8') # 默认打开模式就为 r # 通过句柄对文件进行操作
      date = f.read() # 关闭文件
      f.close()
  • 报错的原因:

    • UnicodeDecodeError:文件存储时与文件打开时编码本不一致。

    • 路径分隔符产生的问题:

      解决方法:在路径前加个 r
      r'C:\Users\Desktop\文件.txt'

文件操作的:读

​ 文件操作的读,有四种模式(r、rb、r+、r+b),r+ 和 r+b 不常用, rb 操作的是非文本的文件,比如:图片、视频、音频。每种模式有五种方法(read()、read(n)、readline()、readlines()、for)。

  • r 模式

    ​ 以只读方式打开文件,文件的指针将会放在文件的开头。是文件操作最常用的模式,也是默认模式,如果一个文件不设置mode,那么默认使用r模式操作文件。

    举例:

    f = open('文件.txt', mode='r', encoding='utf-8')
    msg = f.read()
    f.close()
    print(msg)
    • read() 一次性全部读取

      read() 将文件中的内容全部读取出来; 弊端:如果文件很大就会非常的占用内存,容易导致内存崩溃。

      f = open('测试', mode='r', encoding='utf-8')
      msg = f.read()
      f.close()
      print(msg) # 输出结果:
      这是一行测试
      A:这是第二行
      B:这是第三行
      C:这是第几行
      D:这是我也不知道第几行
      就这么地吧.
    • read(n) 指定读取到什么位置

      在 r 模式下,n 按照字符读取

      f = open('测试', mode='r', encoding='utf-8')
      msg = f.read(4)
      f.close()
      print(msg) # 输出结果:
      这是一行
    • readline() 按行读取

      readline() 每次只读取一行,注意: readline() 读取出来的数据在后面都有一个\n,解决这个问题只需要在我们读取出来的文件后边加一个strip()就OK了

      f = open('测试', mode='r', encoding='utf-8')
      msg1 = f.readline()
      msg2 = f.readline().strip()
      msg3 = f.readline()
      msg4 = f.readline()
      f.close()
      print(msg1)
      print(msg2)
      print(msg3)
      print(msg4) # 输出结果:
      这是一行测试 A:这是第二行
      B:这是第三行 C:这是第几行
    • readlines() 返回一个列表

      readlines() 返回一个列表,列表里面每个元素是原文件的每一行,如果文件很大,占内存,容易崩盘。

      f = open('测试', mode='r', encoding='utf-8')
      print(f.readlines()) # 还可以这么写的,哈哈
      f.close() # 输出结果:
      ['这是一行测试\n', 'A:这是第二行\n', 'B:这是第三行\n', 'C:这是第几行\n', 'D:这是我也不知道第几行\n', '就这么地吧.']

    上面这四种都不太好,如果文件超大,内容超多,他们就很容易将内存撑爆,所以,我们还有第五种方法。

    • for 循环

      可以通过for循环去读取,文件句柄是一个迭代器,他的特点就是每次循环只在内存中占一行的数据,非常节省内存。

      f = open('测试', mode='r', encoding='utf-8')
      for line in f:
      print(line) # 去掉 \n 可以这样写: print(line.strip())
      # 这种方式就是在一行一行的进行读取,它就执行了下边的功能 '''
      print(f.readline())
      print(f.readline())
      print(f.readline())
      .......
      '''
      # 输出结果:
      这是一行测试 A:这是第二行 B:这是第三行 C:这是第几行 D:这是我也不知道第几行 就这么地吧.

    特别注意: 读完的文件一定必须要关闭

  • rb 模式

    rb模式:以二进制格式打开一个文件用于只读。文件指针将会放在文件的开头。记住下面讲的也是一样,带b的都是以二进制的格式操作文件,他们主要是操作非文字文件:图片,音频,视频等,并且如果你要是带有b的模式操作文件,那么不用声明编码方式。

    f1 = open('图片.jpeg', mode='rb')
    tu = f1.read()
    f1.close()
    print(tu) # 输出结果:
    b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x00\x00H\x00H\x00\x00\xff\xe1\x00\xb0Exif\x............后面还有.老长老长了..此处省略了.

    rb模式也有read read(n) readline(),readlines() for循环这几种方法,这里就不一一演示了。

文件操作的:写

​ 文件操作的写,有四种模式(w、wb、w+、w+b),w+ 和 w+b 不常用, wb 操作的是非文本的文件,比如:图片、视频、音频。操作方法是:write('要写入的内容')

  • w 模式

    如果文件不存在,用 w 模式操作文件,它会先创建文件,然后写入内容。

    f = open('这是一个新创建的文件', encoding='utf-8', mode='w')
    f.write('果然是一个新创建的文件')
    f.close()

    如果文件存在,利用w模式操作文件,先清空原文件内容,在写入新内容。

    f = open('这是一个新创建的文件', encoding='utf-8', mode='w')
    f.write('这是清空后重新写入的内容')
    f.close()
  • wb 模式

    wb模式:以二进制格式打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。一般用于非文本文件如:图片,音频,视频等。

    >>举个例子 :

    我先以rb的模式将一个图片的内容以bytes类型全部读取出来,然后在以wb将全部读取出来的数据写入一个新文件,这样我就完成了类似于一个图片复制的流程。具体代码如下:

    # 第一步:将原图片通过 rb 模式读取出来。
    f = open('图片.jpeg', mode='rb')
    content = f.read()
    f.close()
    # 第二步:将读取出来的数据通过 wb 模式写入新文件。
    f1 = open('图片1.jpeg', mode='wb')
    f1.write(content)
    f1.close()

文件操作的:追加

就是在文件中追加内容。这里也有四种文件分类主要四种模式:a,ab,a+,a+b,我们只讲a

  • a 模式

    如果文件不存在,利用a模式操作文件,那么它会先创建文件,然后写入内容。

    f = open('追加文本', encoding='utf-8', mode='a')
    f.write('这个文件是没有的,我是新创建的')
    f.close()

    如果文件存在,利用a模式操作文件,那么它会在文件的最后面追加内容。

    f = open('追加文本', encoding='utf-8', mode='a')
    f.write('这是己存在的文件,我是新追加的内容')
    f.close()

文件操作的其它模式

​ 咱们还有一种模式没有讲,就是那种带+号的模式。什么是带+的模式呢?+就是加一个功能。比如刚才讲的r模式是只读模式,在这种模式下,文件句柄只能进行类似于read的这读的操作,而不能进行write这种写的操作。所以我们想让这个文件句柄既可以进行读的操作,又可以进行写的操作,那么这个如何做呢?这就是接下来要说这样的模式:r+ 读写模式,w+写读模式,a+写读模式,r+b 以bytes类型的读写模式.........

在这里咱们只讲一种就是r+,其他的大同小异,自己可以练练就行了。

#1. 打开文件的模式有(默认为文本模式):
r,只读模式【默认模式,文件必须存在,不存在则抛出异常】
w,只写模式【不可读;不存在则创建;存在则清空内容】
a, 只追加写模式【不可读;不存在则创建;存在则只追加内容】 #2. 对于非文本文件,我们只能使用b模式,"b"表示以字节的方式操作(而所有文件也都是以字节的形式存储的,使用这种模式无需考虑文本文件的字符编码、图片文件的jgp格式、视频文件的avi格式)
rb
wb
ab
注:以b方式打开时,读取到的内容是字节类型,写入时也需要提供字节类型,不能指定编码 #3,‘+’模式(就是增加了一个功能)
r+,读写【可读,可写】
w+,写读【可写,可读】
a+,写读【可写,可读】 #4,以bytes类型操作的读写,写读,写读模式
r+b,读写【可读,可写】
w+b,写读【可写,可读】
a+b,写读【可写,可读】
  • r+ 模式 读并追加 顺序不能错

    r+: 打开一个文件用于读写。文件指针默认将会放在文件的开头。

    f = open('文件的读写.txt', encoding='utf-8', mode='r+')
    content = f.read()
    print(content)
    f.write('这是新写入的内容')
    f.close()

      注意:如果你在读写模式下,先写后读,那么文件就会出问题,因为默认光标是在文件的最开始,你要是先写,则写入的内容会讲原内容覆盖掉,直到覆盖到你写完的内容,然后在后面开始读取。

小总结:

三个大方向:

​ 读, 四种模式: r rb r+ r+b

​ 写, 四种模式 : w,wb, w+,w+b

​ 追加 四种模式: a, ab, a+,a+b

相应的功能:

​ 对文件句柄的操作:read read(n) readline() readlines() write()

文件操作的其它功能

  • f.tell() 获取光标的位置 单位是:字节

    f = open('测试', encoding='utf-8', mode='r')
    print(f.tell())
    content = f.read()
    print(f.tell())
    f.close() # 原文件内容
    这是一行测试
    A:这是第二行
    B:这是第三行
    C:这是第几行
    D:这是我也不知道第几行
    就这么地吧. # 输出结果:
    0 # 开始的位置
    122 # 结束的位置
  • f.seek() 调整光标的位置 (注意:移动单位是byte , 如果是utf-8的中文部分要是3的倍数)

    f = open('测试', encoding='utf-8', mode='r')
    f.seek(9)
    content = f.read()
    print(content)
    f.close() # 原文件内容
    这是一行测试
    A:这是第二行
    B:这是第三行
    C:这是第几行
    D:这是我也不知道第几行
    就这么地吧. # 输出结果:
    行测试
    A:这是第二行
    B:这是第三行
    C:这是第几行
    D:这是我也不知道第几行
    就这么地吧.
  • f.flush() 强制刷新

    f = open('测试', encoding='utf-8', mode='w')
    f.write('fafdsfsfsadfsaf')
    f.flush()
    f.close()

打开文件的另一种方式(常用的是这种)

  • with open() as ....

    # 优点1:不用手动关闭文件句柄
    # 利用with上下文管理这种方式,它会自动关闭文件句柄。
    with open('测试', encoding='utf-8', mode='r') as f:
    print(f.read()) # 优点2:可以加多个 open 操作
    # 一个with 语句可以操作多个文件,产生多个文件句柄。
    with open('测试', encoding='utf-8', mode='r') as f,\
    open('测试', encoding='utf-8', mode='w') as f1:
    print(f.read())
    f1.write('kckckckckckckkck')

      这里要注意一个问题,虽然使用with语句方式打开文件,不用你手动关闭文件句柄,比较省事儿,但是依靠其自动关闭文件句柄,是有一段时间的,这个时间不固定,所以这里就会产生问题,如果你在with语句中通过r模式打开t1文件,那么你在下面又以a模式打开t1文件,此时有可能你第二次打开t1文件时,第一次的文件句柄还没有关闭掉,可能就会出现错误,他的解决方式只能在你第二次打开此文件前,手动关闭上一个文件句柄。

文件的修改

​ 文件的数据是存放于硬盘上的,因而只存在覆盖、不存在修改这么一说,我们平时看到的修改文件,都是模拟出来的效果,具体的说有两种实现方式:

  • 文件操作改的流程:

    1,以读的模式打开原文件。

    2,以写的模式创建一个新文件。

    3,将原文件的内容读出来修改成新内容,写入新文件。

    4,将原文件删除。

    5,将新文件重命名成原文件。

  • 方式一:将硬盘存放的该文件的内容全部加载到内存,在内存中是可以修改的,修改完毕后,再由内存覆盖到硬盘(word,vim,nodpad++等编辑器)

    import os	# 调用系统模块
    with open('测试', encoding='utf-8') as f1,\
    open('测试.bak', encoding='utf-8',mode='w') as f2:
    old_content = f1.read() # 全部读入内存,如果文件很大,会卡死
    new_content = old_content.replace('文', 'wen') # 在内存中完成修改
    f2.write(new_content) # 一次性写入新文件
    os.remove('测试') # 删除原文件
    os.rename('测试.bak', '测试') # 将新建的文件重命名为原文件 # 原文件内容
    **文件操作改的流程:**
    1,以读的模式打开原文件。
    2,以写的模式创建一个新文件。
    3,将原文件的内容读出来修改成新内容,写入新文件。
    4,将原文件删除。
    5,将新文件重命名成原文件。
    # 修改后的内容
    **wen件操作改的流程:**
    1,以读的模式打开原wen件。
    2,以写的模式创建一个新wen件。
    3,将原wen件的内容读出来修改成新内容,写入新wen件。
    4,将原wen件删除。
    5,将新wen件重命名成原wen件。
  • 方式二:将硬盘存放的该文件的内容一行一行地读入内存,修改完毕就写入新文件,最后用新文件覆盖源文件(这种是常用的)

    import os
    with open('测试', encoding='utf-8') as f1,\
    open('测试.bak', encoding='utf-8',mode='w') as f2:
    for line in f1: # 一行一行的改,占内存少
    new_line = line.replace('wen', '文')
    f2.write(new_line)
    os.remove('测试')
    os.rename('测试.bak', '测试') # 原文件内容
    **wen件操作改的流程:**
    1,以读的模式打开原wen件。
    2,以写的模式创建一个新wen件。
    3,将原wen件的内容读出来修改成新内容,写入新wen件。
    4,将原wen件删除。
    5,将新wen件重命名成原wen件。 # 修改后的内容
    **文件操作改的流程:**
    1,以读的模式打开原文件。
    2,以写的模式创建一个新文件。
    3,将原文件的内容读出来修改成新内容,写入新文件。
    4,将原文件删除。
    5,将新文件重命名成原文件。

记录我的 python 学习历程-Day08 文件的操作的更多相关文章

  1. 《转》Python学习(15)-对文件的操作(二)

    转自 http://www.cnblogs.com/BeginMan/p/3169020.html 一.文件系统 从系统角度来看,文件系统是对文件存储器空间进行组织和分配,负责文件存储并对存入的文件进 ...

  2. Python学习日记之文件读取操作

    Python内置了文件读写的函数open,read 用法示例: open('/home/root/files.txt ') 在打开文件后,操作完成后可以使用close()关闭文件,但比较好的文件读写方 ...

  3. 记录我的 python 学习历程-Day02-while 循环/格式化输出/运算符/编码的初识

    一.流程控制之--while 循环 循环就是重复做同一件事,它可以终止当前循环,也可以跳出这一次循环,继续下一次循环. 基本结构(基本循环) while 条件: 循环体 示例 # 这是一个模拟音乐循环 ...

  4. 记录我的 python 学习历程-Day13 匿名函数、内置函数 II、闭包

    一.匿名函数 以后面试或者工作中经常用匿名函数 lambda,也叫一句话函数. 课上练习: # 正常函数: def func(a, b): return a + b print(func(4, 6)) ...

  5. 记录我的 python 学习历程-Day06 is id == / 代码块 / 集合 / 深浅拷贝

    一.is == id 用法 在Python中,id是内存地址, 你只要创建一个数据(对象)那么就会在内存中开辟一个空间,将这个数据临时加载到内存中,这个空间有一个唯一标识,就好比是身份证号,标识这个空 ...

  6. 记录我的 python 学习历程-Day05 字典/字典的嵌套

    一.字典的初识 为什么要有字典 字典与列表同属容器型数据类型,同样可以存储大量的数据,但是,列表的数据关联性不强,并且查询速度比较慢,只能按照顺序存储. 什么是字典 先说一下什么叫可变与不可变的数据类 ...

  7. 记录我的 python 学习历程-Day11 两个被忽视的坑、补充知识点、函数名的应用、新版格式化输出、迭代器

    补充知识点 函数形参中默认参数的陷阱 针对不可变数据类型,它是没有陷阱的 def func(name, sex='男'): print(name) print(sex) func('Dylan') # ...

  8. 记录我的 python 学习历程-Day12 生成器/推导式/内置函数Ⅰ

    一.生成器 初识生成器 生成器的本质就是迭代器,在python社区中,大多数时候都把迭代器和生成器是做同一个概念. 唯一的不同就是: 迭代器都是Python给你提供的已经写好的工具或者通过数据转化得来 ...

  9. 记录我的 python 学习历程-Day03 数据类型 str切片 for循环

    一.啥是数据类型 ​ 我们人类可以很容易的分清数字与字符的区别,但是计算机并不能呀,计算机虽然很强大,但从某种角度上看又很傻,除非你明确的告诉它,1是数字,"汉"是文字,否则它是分 ...

随机推荐

  1. Laravel 菜鸟的晋级之路

    第一阶段:简单的增删改查 这是最开始接触Laravel的一个阶段.如果有PHP经验,那么应该能很快找到MVC的路径,然后驾轻就熟的开始写起来.虽然还显得有些笨拙,不过很快就能做出一些内容了.如果没有P ...

  2. 微信中使用popup等弹窗组件时点击输入框input键盘弹起导致IOS中按钮无效处理办法

    因为在IOS微信中在弹窗中使用input使键盘弹起,使弹窗的位置上移,当键盘关闭时页面还在上面,弹窗位移量也在上面,只有下拉才能回到原位,这样弹窗也消失了.我的处理办法就是在键盘弹起和消失的时候,让页 ...

  3. ASP.NET Core +Highchart+ajax绘制动态柱状图

    一.项目介绍利用前端Highchart,以及ajax向后台获取数据,绘制动态柱状图.hightchart其他实例可查看官网文档.[Highchart](https://www.highcharts.c ...

  4. linux网络配置(ifcfg)

    将linux主机接入到网络需要配置哪些配置项? IP/NETMASK:本地通信. 路由(网管):跨网络通信. DNS服务器地址:基于主机名通信. DNS服务器有三种:主/备用DNS服务器/第三备份dn ...

  5. 题解-洛谷P2010-回文日期

    原题链接: https://www.luogu.org/problem/P2010 题目简述: 牛牛习惯用8位数字表示一个日期,其中,前4位代表年份,接下来2位代表月份,最后22位代表日期.显然:一个 ...

  6. .net core 学习 读取配置文件

    在空项目中是没有配置文件的,首先要新建一个,配置文件内容如下,下面来读取各个内容 { "ConnectionStrings": { "DefaultConnection& ...

  7. 【JavaEE】之MyBatis插入数据后获取自增主键

    很多时候,我们都需要在插入一条数据后回过头来获取到这条数据在数据表中的自增主键,便于后续操作.针对这个问题,有两种解决方案: 先插入,后查询.我们可以先插入一条数据,然后根据插入的数据的各个字段值,再 ...

  8. pycharm启动vue项目

    一 移动vue项目问题 1 移植到其他windows or mac 2 重新安装依赖 基于情况2(我们把除了第一个文件都复制到一个新的文件夹) 重新依据配置文件去安装各种各样的依赖(也就是根据配置文件 ...

  9. svn+apache搭建版本控制服务器

    Centos7(linux)搭建版本控制服务器(svn+apache) 1.简介: 版本控制服务器: 版本控制(Revision control)是一种软体工程技巧,籍以在开发的过程中,确保由不同人所 ...

  10. 浅谈css样式之list-type

    在我们的工作学习中,大多数人使用列表标签的时候总一般的选择是把list-type设置成none.不过可能很多人对于这个属性的细节并没有很深的了解.甚至会把list-type和list-type-sty ...