一,文件的基础操作

对文件操作的流程

  • [x] :打开文件,得到文件句柄并赋值给一个变量
  • [x] :通过句柄对文件进行操作
  • [x] :关闭文件

创建初始操作模板文件

[root@localhost scripts]# seq 12 >> test
[root@localhost scripts]# ls
test test.py
[root@localhost scripts]# cat test
1
2
3
4
5
6
7
8
9
10
11
12

1.1 文件的按行读取(readline)

#文件的基本操作过程演示:

#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# author:Mr.chen f = open("test") #相对路径打开文件
first_line = f.readline() #读取文件的一行,并赋值
print (first_line) #打印第一行
for num in range(4) : #循环迭代4次
print (f.readline()) #在读一行继续打印(重复4次)
f.close() #关闭文件 #输出结果 [root@localhost scripts]# python3 test.py
1 2 3 4 5

特别提示:

只要文件没有执行f.close()进行关闭,那么继续f.readline()的话都是读取下一行

如果执行了f.close(),在重新进行f = open()的话,就会重新开始读行

#操作演示

#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# author:Mr.chen f = open("test")
print (f.readline())
print (f.readline())
f.close() f = open("test")
print (f.readline())
print (f.readline())
f.close() #输出结果 [root@localhost scripts]# python3 test.py
1 2 1 2

1.2 文件的按行读取和一次性读取(readline,read)

#代码演示:

#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# author:Mr.chen f = open("test")
print (f.readline()) #打印一行
print ("*"*50) #分隔标志
print (f.read()) #打印剩余所有行
f.close() #输出结果: [root@localhost scripts]# python3 test.py
1 **************************************************
2
3
4
5
6
7
8
9
10
11
12

1.3 文件的指针

一个文件被打开,如果从头到尾都被读了一遍,默认就不能再读了

#代码演示:

f = open("test")
print (f.read())
print ("-"*50)
print (f.read()) #没有产生作用
f.close() #输出结果 [root@localhost scripts]# python3 test.py
1
2
3
4
5
6
7
8
9
10
11
12 --------------------------------------------------

这是为什么呢?因为文件的读取其实是有一个叫做指针的东西存在的,当你读了一行,指针就会出现在下一行上,最终直到文件的末尾.由于末尾没有下一行了,因此就不能再读了。如果我们想继续从头再读,那就需要调整文件指针的位置。

1.4 文件的编码

当我们在Linux读取文件的时候,不会有任何编码问题,因为Linux默认就是utf-8的格式。假如我们在windows上读取含有中文的文件内容,就会出现乱码。

在Linux上就没有这个问题,因为Linux默认就是用utf-8去转码。

二,文件的基础打开模式

2.1 文件的读模式(r)

# 读模式(r)

f = open("test","r")    #r,就表示以只读的方式打开文件,这种方式不可写入数据
print (f.read())
f.close() #输出结果 1
2
3
4
5
6
7
8
9
10
11
12

如果不写r,默认就是r模式

2.2文件的写模式w(不能读,会清空源文件内容,文件不存在会创建)

# 写模式(w)

f = open("yunjisuan","w",encoding="utf-8")
for i in range(10) :
f.write("我写了{}行数据\n".format(i))
f.close() #输出结果 [root@localhost scripts]# cat yunjisuan
我写了0行数据
我写了1行数据
我写了2行数据
我写了3行数据
我写了4行数据
我写了5行数据
我写了6行数据
我写了7行数据
我写了8行数据
我写了9行数据

特别提示:

如果写入的文件并不存在,则默认会创建这个文件

假如写入的文件存在,在写入的时候,会先清空源文件所有内容

2.3 文件的追加模式a(不可读;不存在则创建文件;存在则只追加内容)

# 追加模式(a)

f = open("yunjisuan","a",encoding="utf-8")
f.write("-"*50)
f.write("\n")
for i in range(10) :
f.write("我写了{}行数据\n".format(i))
f.close() #输出结果 [root@localhost scripts]# cat yunjisuan
我写了0行数据
我写了1行数据
我写了2行数据
我写了3行数据
我写了4行数据
我写了5行数据
我写了6行数据
我写了7行数据
我写了8行数据
我写了9行数据
--------------------------------------------------
我写了0行数据
我写了1行数据
我写了2行数据
我写了3行数据
我写了4行数据
我写了5行数据
我写了6行数据
我写了7行数据
我写了8行数据
我写了9行数据

三,文件读取操作(r)的运用技巧

3.1 按行读取文件的内容

#读取文件的前5行

f = open("yunjisuan","r",encoding="utf-8")
for i in range(5) :
print (f.readline()) #读取文件的前8行,但是第5行不输出 f = open("yunjisuan","r",encoding="utf-8")
for i in range(8) :
data = f.readline()
if i != 4 :
print (data)

特别提示:

读取文件前8行,但是第5行不输出,不能写成如下形式。请同学们思考这是为什么?

#错误的实现访问

f = open("yunjisuan","r",encoding="utf-8")
for i in range(8) :
if i != 4 :
print (f.readline())

3.2 按行迭代输出一个文件的所有内容

#按行输出一个文件的所有内容

f = open("test","r",encoding="utf-8")
for line in f :
print (line) #按行输出文件所有内容,第5行不输出 f = open("test","r",encoding="utf-8")
num = 1
for line in f :
if num != 5 :
print (line)
num += 1

3.3 优化文件的读取输出

为何输出时,有那么多的空行?

因为print本身就会在输出内容的后边加上\n的换行符,而从文件读取一行的行尾也是有一个\n的。因此在输出时,就变成了两次还行。所以我们需要去掉文件内容中附带\n.

#代码演示

f = open("test","r",encoding="utf-8")

for line in f :
print (line) #输出结果
[root@localhost scripts]# python3 test.py
1
#都是空行
2
#因为在输出时有两个\n
3 4 5 #去掉多余的换行符再输出 f = open("test","r",encoding="utf-8") for line in f :
print (line.strip()) #输出结果 [root@localhost scripts]# python3 test.py
1
2
3
4
5

3.4 f是个什么东西?

#代码演示:

>>> f = open("test","r",encoding="utf-8")
>>> print (r)
>>> print (f)
<_io.TextIOWrapper name='test' mode='r' encoding='utf-8'>

由上述操作可知,f只是一个内存对象。这个内存对象是指向文件的,也就是说,它是一行一行从文件中拿数据的。因此,可以用在读取大文件上。

3.5 read,readline,readlines区别

#代码演示:

f = open("test","r",encoding="utf-8")
print (f.readline()) #输出readline的值
f.close()
f = open("test","r",encoding="utf-8")
print (type(f.readline())) #输出readline的类型
f.close()
f = open("test","r",encoding="utf-8")
print (f.readlines()) #输出readlines的值
f.close()
f = open("test","r",encoding="utf-8")
print (type(f.readlines())) #输出readlines的类型
f.close()
f = open("test","r",encoding="utf-8")
print (f.read()) #输出read的值
f.close()
f = open("test","r",encoding="utf-8")
print (type(f.read())) #输出read的类型
f.close()

输出结果

[root@localhost scripts]# python3 test.py
1 #readline()是按行读取输出 <class 'str'> #输出为字符串格式
['1\n', '2\n', '3\n', '4\n', '5\n'] #readlines()将所有值输出
<class 'list'> #输出为列表格式
1
2
3
4 #read()也是将所有值输出
5 <class 'str'> #输出为字符串格式

由上述实验可知,由于readlines()和read()都是一次性将所有值输出,因此均不适合大文件的读取。而readline()是按行读取输出,适合读取大型文件。

3.6 为何迭代文件所有内容只能用f这个对象而不是readline()

#代码演示:

f = open("test","r",encoding="utf-8")
for line in f.readline():
print (line)
f.close()
print ("-"*50)
f = open("test","r",encoding="utf-8")
for line in f:
print (line)
f.close() #输出结果 [root@localhost scripts]# python3 test.py
1 #迭代readline仍旧只输出了一行 --------------------------------------------------
1 #代码f则输出了文件所有内容 2 3 4 5

由测试可知,readline()执行一次才能读取一行数据然后输出一行数据。因此,我们可以通过频繁执行readline()来获取文件内容,但是我们无法去直接迭代它。而f是一个指向内存的地址,其实它还是一个我们以后会学的迭代器这么个东西。在这里我们不要深究。记住就好。

3.7 去掉计数器迭代一个文件所有内容,并且第4行不输出

#代码演示:

f = open("test","r",encoding="utf-8")
for index,line in enumerate(f):
if index+1 != 4:
print (index+1,line)
f.close() #输出结果
[root@localhost scripts]# python3 test.py
1 1 2 2 3 3 5 5

3.8 文件的指针(tell,seek)

创建文件模板

[root@localhost scripts]# cat test
I am a students!
who are you ?
I am a students!
who are you ?
I am a students!
who are you ?
I am a students!
who are you ?

代码操作

f = open("test","r",encoding="utf-8")
print (f.tell()) #查看指针位置
f.readline() #按行读取
print (f.tell())
f.readline()
print (f.tell()) f.close() #输出结果
[root@localhost scripts]# python3 test.py
0
17 #指针是按字符计算的,一个字符计算1
31 #代码演示: f = open("test","r",encoding="utf-8")
print (f.tell())
f.read(4)
print(f.tell()) f.close() #输出结果 [root@localhost scripts]# python3 test.py
0
4

指针回调

#代码演示:

f = open("test","r",encoding="utf-8")
print (f.tell())
print (f.readline())
print(f.tell())
f.seek(0) #将指针回调到0位置
print (f.tell())
print (f.readline())
f.close() #输出演示: [root@localhost scripts]# python3 test.py
0
I am a students! 17
0
I am a students!

四,文件写入操作(w)的运用技巧

4.1 文件的缓冲原理(buffer)

我们知道当我们写入文件内容的时候,如果目标文件不存在默认会创建一个空文件,如果目标文件存在内容,那么默认会清空目标文件。然后才会写入我们想要写入的数据,但是它是如何写入数据的呢?一行一行写入?还是一次性写入呢?

#代码演示:

f = open("yun","w",encoding="utf-8")
f.write("我好吗?\n")
f.write("我好吗?\n")
f.write("我好吗?\n")
decide = input("稍等一下:") #我们执行完写入代码利用用户输入代码卡住这里,看看f.write()写入操作到底写入文件了没有
f.close()

当我们执行上述代码后,卡在用户输入界面,我们去看那个文件是否被写入了内容,查看的结果是空的,文件里什么都没有。

[root@localhost scripts]# cat yun

#空空如也
  • 这是为什么呢?这是因为,当我们将数据写入文件的时候,如果一行一行进行数据写入,那么需要不断的进行I/O操作,而控制我们写入速度的是线程,而操作线程的又是CPU,所以我们的写入速度是非常快的。而磁盘的I/O速度,是非常慢的。如果我们一行一行进行数据写入,那么就会让我们线程一直等在这里,这会非常的没有效率。
  • 因此,文件会默认先将数据写入到内存的(buffer)里,然后在一次性写入到文件中。
  • 在代码里就是当文件被关闭时,默认数据从(buffer)一次性写入到文件中。
#当执行了代码f.close()之后...

[root@localhost scripts]# cat yun
我好吗?
我好吗?
我好吗?

那么写入到缓冲buffer的这个动作,我们可以看的到吗?作为开发,我们当然能看到。

#代码演示

f = open("yun","w",encoding="utf-8")
f.write("我好吗?\n")
f.write("我好吗?\n")
f.write("我好吗?\n")
print(f.buffer) #打印buffer的内存地址
decide = input("稍等一下:")
f.close() #输出结果 <_io.BufferedWriter name='yun'> #只是一个指向文件名的内存地址,这个就是buffer。数据是存在内存中的。

4.2 文件的写入刷新(flush)

  • 当我们写入数据时候,我们已经知道了实际是写入到内存的缓冲区buffer的。当最后遇到f.close()时,数据才会被一次性写入到文件。
  • 但是,假如我们就需要随时刷新数据进入文件呢?我们怎么办?
#代码演示:

f = open("yun","w",encoding="utf-8")
f.write("我好吗?\n")
f.write("我好吗?\n")
f.flush() #即时刷新buffer中的数据到文件
f.write("我好吗?\n")
decide = input("稍等一下:")
f.close() #输出结果 [root@localhost scripts]# cat yun
我好吗?
我好吗?

由上述实验,我们可知当我们想要即时将buffer里的数据刷新到文件里,那么我们只需要执行f.flush即可。

4.3 通过flush刷新规则实现文件的安装进度条显示

平时我们用的print输出其实默认在输出一个换行符的。如此Linux才会换行显示

#代码演示:

print (1)
print (2)
print (3) #输出结果 1
2
3

可是我们知道进度条都是一行显示的因此我们不能用print,我们需要用一种叫做标准输出的东西,在sys模块里。

#代码演示:

#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# author:Mr.chen import sys sys.stdout.write("1") #默认不输出换行符
sys.stdout.write("2")
sys.stdout.write("3") #输出结果 123

特别提示:

sys.stdout.write()标准输出只能输出str格式的字符串

应用这个输出我们就可以实现进度条了。

#代码演示:

import sys,time                                                      

for i in range(20):
sys.stdout.write("#")
time.sleep(0.1) #输出结果 ####################

虽然我们已经设置了,每次输出间隔0.1秒,但是我们发现20个#仍旧是一次性输出的。这是因为,标准输出也是等到你整个进程都结束了才输出#号,因此我们修改一下

#代码演示:

#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# author:Mr.chen import sys,time for i in range(20):
sys.stdout.write("#")
sys.stdout.flush() #刷新每次的写入到屏幕
time.sleep(0.1)

如上修改过的代码就可以实现Linux安装进度条显示了。

五 文件追加操作(a)的运用技巧

5.1 文件的追加截断(truncate)

截取文件的一部分内容,然后写回源文件

文件初始模版:

[root@localhost scripts]# cat yun
123456789012345678901234567890 #一共30个字符

执行代码:

#代码演示

f = open("yun","a",encoding="utf-8")
f.truncate(20) #执行结果 [root@localhost scripts]# cat yun
12345678901234567890 #只剩下了20个字符

六,作业

1,继续完成阶段性作业

Python运维开发基础07-文件基础的更多相关文章

  1. python运维开发(二十一)----文件上传和验证码+session

    内容目录: 文件上传 验证码+session 文件和图片的上传功能 HTML Form表单提交,实例展示 views 代码 HTML ajax提交 原生ajax提交,XMLHttpRequest方式上 ...

  2. Python运维开发基础01-语法基础【转】

    开篇导语 整个Python运维开发教学采用的是最新的3.5.2版,当遇到2.x和3.x版本的不同点时,会采取演示的方式,让同学们了解. 教学预计分为四大部分,Python开发基础,Python开发进阶 ...

  3. Python运维开发基础01-语法基础

    标签(空格分隔): Mr.chen之Python3.0执教笔记(QQ:215379068) --仅供北大青鸟内部学习交流使用 开发不是看出来的,开发一定是练出来的: 想学好开发,没有捷径可走,只有不断 ...

  4. Python运维开发基础09-函数基础【转】

    上节作业回顾 #!/usr/bin/env python3 # -*- coding:utf-8 -*- # author:Mr.chen # 实现简单的shell命令sed的替换功能 import ...

  5. Python运维开发基础08-文件基础【转】

    一,文件的其他打开模式 "+"表示可以同时读写某个文件: r+,可读写文件(可读:可写:可追加) w+,写读(不常用) a+,同a(不常用 "U"表示在读取时, ...

  6. Python运维开发基础07-文件基础【转】

    一,文件的基础操作 对文件操作的流程 [x] :打开文件,得到文件句柄并赋值给一个变量 [x] :通过句柄对文件进行操作 [x] :关闭文件 创建初始操作模板文件 [root@localhost sc ...

  7. Python运维开发基础06-语法基础【转】

    上节作业回顾 (讲解+温习120分钟) #!/usr/bin/env python3 # -*- coding:utf-8 -*- # author:Mr.chen # 添加商家入口和用户入口并实现物 ...

  8. Python运维开发基础03-语法基础 【转】

    上节作业回顾(讲解+温习60分钟) #!/usr/bin/env python3 # -*- coding:utf-8 -*- # author:Mr.chen #只用变量和字符串+循环实现“用户登陆 ...

  9. Python运维开发基础02-语法基础【转】

    上节作业回顾(讲解+温习60分钟) #!/bin/bash #user login User="yunjisuan" Passwd="666666" User2 ...

  10. Python运维开发基础10-函数基础【转】

    一,函数的非固定参数 1.1 默认参数 在定义形参的时候,提前给形参赋一个固定的值. #代码演示: def test(x,y=2): #形参里有一个默认参数 print (x) print (y) t ...

随机推荐

  1. sudo-tcpdump提权法

    当当前用户可以通过sudo执行tcpdump时,可以用来进行提权 tcpdump中有两个参数-z和-Z,前者用来执行一个脚本,后者用来指定tcpdump以哪个用户运行,当可以通过sudo执行时,则可以 ...

  2. MyEclipse10 中设置Jquery提醒,亲测可用

    最近做练习需要用到Jquery,在myeclipse中默认没有提示功能.然后在网上找解决方案,有一种方案说使用spket,然后搜索安装,折腾了半天还是不行,脑细胞死掉几百个.. 然后在网上搜到另外一种 ...

  3. Centos 7 系统详解

      安装CentOS 7系统后,变化竟然这么大? 一.Runlevel首先一条,原来一直用的CentOS-6.5-x86_64-minimal.iso光盘镜像(400M左右无图形系统小巧便捷),而7目 ...

  4. 判断一颗二叉树是否为二叉平衡树 python 代码

    输入一颗二叉树,判断这棵树是否为二叉平衡树.首先来看一下二叉平衡树的概念:它是一 棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树.因此判断一颗二叉平衡树的关键在于 ...

  5. 使 docker 容器可以正常 mount privileged

    [docker]privileged参数 privileged参数   $ docker help run ... --privileged=false Give extended privilege ...

  6. JAVA使用ItextPDF

    1.背景 在某些业务场景中,需要提供相关的电子凭证,比如网银/支付宝中转账的电子回单,签约的电子合同等.方便用户查看,下载,打印.目前常用的解决方案是,把相关数据信息,生成对应的pdf文件返回给用户. ...

  7. C#中时间计算方法汇总

    这几天要做一个关于时间数据统计的页面,发现有些东西还是比较用的,现总结如下. DateTime dt = DateTime.Now;  //当前时间 DateTime startWeek = dt.A ...

  8. MD文件

    了解一个项目,恐怕首先都是通过其Readme文件了解信息.如果你以为Readme文件都是随便写写的那你就错了.github,oschina git gitcafe的代码托管平台上的项目的Readme. ...

  9. (判断)window.open()窗口被关闭后执行事件

    $(function() { // start ready var $article_share=$('#body .article').find('li.share'); // $article_s ...

  10. 再记录一次delete出错的经历

    调试的时候进行到delete语句时出现问题,我做的操作是在函数体内用int*申请了N个内存空间,这让我十分纳闷,为什么不能delete呢? 回忆到之前delete出错也遇过一次问题 手动封装OpenC ...