zoukankan      html  css  js  c++  java
  • python文件操作

    首先,我们需要知道一个概念:应用程序是不能直接对电脑硬件进行操作的

    在操作系统中,操作系统对外提供了文件系统,硬盘上的文件都由文件系统进行资源管理,

    读写硬盘是一种硬件操作,所以我们要想进行文件操作,就必须通过文件系统这个接口来进行文件操作

    因此

    我们要想进行文件读写等操作,就必须先向操作系统发起系统调用,
    由操作系统的内核来进行文件的读写操作,
    操作系统把执行结果返回给应用程序,
    最后则应用程序把执行结果呈现在用户面前
    

    python提供了一个进行文件读写操作的系统调用方法:open()

    open()是python内置函数,我们可以通过调用open()函数来向操作系统发起系统调用,进行文件的读写操作
    

    open()函数的用法

    新建一个open_func.py文件,再新建一个file1.txt文件

    file1.txt文件内容为:

    离离原上草,
    一岁一枯荣。
    野火烧不尽,
    春风吹又生。
    

    先在open_func.py文件中打开file1.txt

    >>> f=open("file1.txt")     # 没有指定file1.txt文件的绝对路径,所以这里用的是相对路径
                                # 第二个参数为读取文件的模式,不写默认为"r",即读取模式
    							# 把打开文件的句柄赋值给一个变量f
    >>> print(f)
    <_io.TextIOWrapper name='file1.txt' mode='r' encoding='UTF-8'>
    >>> f.read()				# f.read()会读取指定文件的指定长度字符的内容,如果没有指定读取长度,则读取所有内容
    '离离原上草,
    一岁一枯荣。
    野火烧不尽,
    春风吹又生。
    '
    >>> f.read()				# 再次调用f.read()方法,其打印结果为空,也说明上一次f.read()读取指定文件的所有内容
    ''
    >>> f.close()				# 关闭文件
    

    需要注意的点:

    • 打开一个文件操作完成后一定要关闭这个文件,否则被打开的文件会一直存在于系统内存中,占用系统资源

    指定读取长度的方法:f.read()

    [root@bogon ~]# cat file2.txt		# 在系统命令提示符下查看文件file2.txt的内容
    python
    linux
    mysql
    
    >>> f=open("file2.txt")             # 以默认方式打开一个不存在的文件file2.txt,会抛出异常
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    FileNotFoundError: [Errno 2] No such file or directory: 'file2.txt'
    

    在python解释器中进行操作

    >>> f=open("file2.txt","r")         # 以读模式打开文件
    >>> f.read(2)						# 读取两个字符
    'py'
    >>> f.read(5)						# 再向后读取5个字符
    'thon
    '
    >>> f.read(5)						# 再次继续读取5个字符
    'linux'
    >>> f.close()						# 关闭文件
    

    一次读取一行内容的方法:f.readline()

    >>> f=open("file1.txt")     # 再次打开file1.txt文件
    >>> f.readline()			# f.readline()方法执行一次读取文件的一行内容
    '离离原上草,
    '
    >>> f.readline()			# 再次执行f.readline()方法,会接着光标在文件中的内容再次读取文件的一行内容
    '一岁一枯荣。
    '
    >>> print(f.readline(),end="")		# 这次使用print()方法打印f.readline()方法读取的一行内容,并指定文件结尾
    野火烧不尽,
    >>> print(f.readline(),end="")
    春风吹又生。
    >>> f.readline()			# 文件已经被读取完了,再次调用f.readline()方法读取文件内容会返回空
    ''
    >>> f.close()               # 因为文件已经被读取完,光标已经被移动到文件的末尾了,所以关闭文件
    

    读取整个文件内容生成列表的方法:f.readlines()

    >>> f=open("file1.txt")     # 打开文件
    >>> f.readlines()           # f.readlines()会一次性读取文件的所有内容,并把每一行做为一个元素放入一个列表中
    ['离离原上草,
    ', '一岁一枯荣。
    ', '野火烧不尽,
    ', '春风吹又生。
    ']
    >>> f.write("aaa")          # 向文件中写入一行"aaa",因为是以读的方式打开文件,所以调用f.write()方法向文件中写入一行是会提示错误:无法写入
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    io.UnsupportedOperation: not writable
    >>> f.close()
    

    现在再以"w"的方式打开文件

    >>> f=open("file1.txt","w")		# 以"w"的方式打开文件
    >>> f.close()					# 关闭文件
    重新打开一个命令窗口,查看file1.txt文件的内容
    

    在前面的例子里,file1.txt文件里是有内容的,但是在这里查看文件内容却是空了

    [root@bogon ~]# cat file1.txt 		# 可以看到文件中没有任何内容
    [root@bogon ~]# ll file1.txt 		# 文件大小变为0了
    -rw-r--r-- 1 root root 0 Jan 27 22:46 file1.txt
    

    在上面的例子里,我们可以看到,以"w"的方式打开文件时,会清除指定文件原有的内容

    实际上,在python中,以"r"方式打开文件时,如果被打开的文件不存在时,是会抛出异常的
    而以"w"模式打开文件时,如果文件不存在则新建这个文件,如果文件已经存在,则清空这个文件的原有内容
    

    再看下一个例子

    >>> f=open("file1.txt","w")			# 以"w"模式打开file1.txt
    >>> f.write("hello world")			# 向文件中写入一行内容
    11
    >>> f.write("hello python")			# 向文件中再次写入一行内容
    12
    >>> f.close()						# 关闭文件
    

    在系统命令行中查看file1.txt文件的内容及大小

    [root@bogon ~]# cat file1.txt 		# 查看文件内容
    hello worldhello python[root@bogon ~]# ll file1.txt
    -rw-r--r-- 1 root root 23 Jan 27 22:59 file1.txt
    

    查看文件内容可以看到文件中没有换行符,所以在向文件中写入内容时,需要我们自己在末尾处添加换行符

    >>> f=open("file1.txt","w")			# 以"w"模式打开file1.txt
    >>> f.write("hello python
    ")		# 向文件中添加一行,在行尾添加换行符
    13		
    >>> f.write("hello world
    ")		# 再次向文件中添加一行,在行尾也添加换行衔
    12
    >>> f.close()						# 关闭文件
    

    再次在系统命令提示符中查看文件内容及大小

    [root@bogon ~]# cat file1.txt		# 查看文件内容,可以看到现在已经可以正常显示了
    hello python	
    hello world
    [root@bogon ~]# ll file1.txt		# 查看文件大小
    -rw-r--r-- 1 root root 25 Jan 27 23:03 file1.txt
    

    在对文件进行读操作时,f.readlines会一次性读取文件的所有内容,并把每一行做为一个元素添加到列表中
    在对文件进行写操作时,也有一个f.writelines方法.

    把一个以字符串为元素的列表写入到文件中的方法:f.writelines()

    f.writelines()方法可以把一个列表的元素做为行写入到文件中

    需要注意的是:列表中的元素必须是字符串类型

    >>> f=open("file1.txt","w")
    >>> f.writelines(["python
    ","linux
    ","mysql
    "])		# 调用f.writelines()方法把一个列表写入到一个文件中
    >>> f.close()
    

    在系统命令提示符窗口中查看文件内容及大小

    [root@bogon ~]# cat file1.txt 		# 查看文件内容
    python
    linux
    mysql
    [root@bogon ~]# ll file1.txt
    -rw-r--r-- 1 root root 19 Jan 27 23:09 file1.txt
    

    可以看到字符串元素的列表已经被写入到文件中去了。

    以"a"模式打开文件并进行操作

    以"a"模式打开文件时,如果指定文件不存在,则创建指定文件
    如果指定文件已经存在,则把光标移动到文件末尾,在文件最后一行进行添加内容操作

    >>> f=open("file1.txt","a")     # 以"a"模式打开文件
    >>> f.write("nginx
    ")          # 向文件末尾追加一行内容
    6
    >>> f.write("javascript
    ")     # 向文件末尾再次追加一行内容
    11
    >>> f.close()                   # 关闭文件
    

    在系统命令提示符窗口中查看文件内容及大小

    [root@bogon ~]# cat file1.txt 	# 可以看到文件file1.txt的末尾已经添加了两行内容
    python
    linux
    mysql
    nginx
    javascript
    [root@bogon ~]# ll file1.txt	# 文件大小发生改变
    -rw-r--r-- 1 root root 36 Jan 27 23:16 file1.txt
    

    注意点:

    在向文件中添加内容时,实际上是在内存中向文件添加内容的,只有等到文件被关闭的时候,解释器才会把内存中被修改的文件内容同步到文件中,在这个期间是有风险的,比如在文件未被保存到硬盘上之前,主机突然断电,那么这个文件的内容就有可以被损坏
    

    这时可以使用f.flush()方法把内存中被修改的文件内容强行保存到硬盘中

    手动把内存中的文件保存到硬盘上的方法:f.flush()

    >>> f=open("file1.txt","a")         # 以追加模式打开文件
    >>> f.write("mongodb
    ")			# 向文件中添加一行内容
    8
    >>> f.write("openstack
    ")          # 再次向文件中添加一行内容
    10
    >>> f.flush()                       # 调用f.flush()方法,把内存中的文件内容保存到硬盘中
    

    在系统命令提示符窗口中查看文件内容及大小

    [root@bogon ~]# cat file1.txt		# 在前面,并没有关闭文件,在这里还是可以看到添加后的文件内容
    python
    linux
    mysql
    nginx
    javascript
    mongodb
    openstack
    [root@bogon ~]# ll file1.txt		# 文件大小发生改变
    -rw-r--r-- 1 root root 54 Jan 28 10:57 file1.txt
    

    f.closed查看文件是否关闭,返回一个布尔值

    这个例子接着上面的例子进行操作

    >>> f.closed        # 在上面的例子里,调用f.flush()方法把内存中的文件内容保存到硬盘上,并没有关闭文件,查看文件是否关闭,返回False,说明文件没有关闭
    False
    >>> f.close()       # 关闭文件
    >>> f.closed        # 再次查看文件是否关闭,返回True说明文件已经关闭了
    True
    

    把光标移动到文件指定位置的方法:f.seek(offset[,whence])

    参数说明:

    第一个参数为移动的字节数,第二个参数表示从哪个位置开始移动,
    0表示以文件开始为参照点
    1表示以当前位置为参数点
    2表示以文件末尾位置为参照点
    

    例子:

    >>> f=open("file1.txt","rb")        # 在这里必须以"b"模式打开文件,否则会抛出异常
    >>> f.seek(5)                       # 当前光标在文件首部,把光标从文件首部向后移动5个字节
    5
    >>> f.seek(5,1)                     # 再以光标当前所有位置为参照,向后移动五个字节
    10
    >>> f.tell()                        # 查看当前光标所在位置
    10
    >>> f.seek(3,1)                     # 以光标当前所在位置为参照,向后移动3个字节
    13
    >>> f.tell()                        # 查看当前光标所有位置
    13
    >>> f.seek(-2,2)                    # 把光标移动到文件末尾,然后再向前移动2个字节
    52
    >>> f.read()                        # 读取光标所在处到文件末尾的所有内容
    b'k
    '
    >>> f.tell()                        # 查看光标所在位置
    54
    >>> f.close()
    

    查看当前光标所在位置的方法:f.tell()

    f.tell()方法的位置为字节,返回值为数字
    

    例子:

    >>> f=open("file1.txt","r")
    >>> f.read()
    'python
    linux
    mysql
    nginx
    javascript
    mongodb
    openstack
    '
    >>> f.seek(10)
    10
    >>> f.tell()
    10
    >>> f.read()
    'ux
    mysql
    nginx
    javascript
    mongodb
    openstack
    '
    >>> f.tell()
    54
    

    以光标所在位置为参照,截取指定长度的内容,其余内容被删除:f.truncate()

    例子:

    >>> f=open("file2.txt","w")         # 以写模式打开文件
    >>> f.write("1111111
    ")            # 向文件中写入一行内容
    8
    >>> f.write("2222222
    ")            # 向文件中写入第二行内容
    8
    >>> f.write("3333333
    ")            # 向文件中写入第三行内容
    8
    >>> f.truncate(5)                   # 从文件开始位置向后截取5个字节的长度的内容
    5
    >>> f.close()
    

    在系统命令提示符下查看文件内容

    [root@bogon ~]# cat file2.txt
    11111[root@bogon ~]#
    

    其余的用法

    f.name              # 获取被打开文件的文件名
    f.encoding          # 获取文件的被打开的编码方式
    f.readable()        # 判断文件当前是否可读
    f.writable()        # 判断文件当前是否可写
    

    例子:

    >>> f=open("file1.txt","r")         # 以读模式打开文件file1.txt
    >>> f.name                          # 查看文件名
    'file1.txt'    	
    >>> f.encoding                      # 查看文件以哪种编码方式被打开
    'UTF-8'
    >>> f.readable()					# 以读模式打开此文件,所以判断文件是否可读,返回值为True
    True
    >>> f.writable()					# 以读模式打开此文件,所以判断文件是否可写,返回值为False
    False	
    >>> f.close()						# 关闭文件
    >>> f=open("file2.txt","w")         # 以写模式打开文件file2.txt
    >>> f.name
    'file2.txt'
    >>> f.encoding
    'UTF-8'
    >>> f.readable()					# 以写模式打开文件,所以在这里判断文件是否可读时,返回False
    False
    >>> f.writable()					# 以写模式打开文件,判断文件可写返回值为True
    True
    >>> f.close()
    

    在python中除了上面说的三种打开文件的办法外,还有另外一种打开文件的方法,那就是以二进制模式打开文件,即"rb","wb","ab"

    现有另一个文件file2.txt,内容为

    离离原上草,
    一岁一枯荣。
    野火烧不尽,
    春风吹又生。
    

    "rb"模式打开文件file2.txt,查看读取到的内容

    >>> f=open("file2.txt","rb")    # 以读模式打开文件file2.txt
    >>> f.read()					# 查看文件内容时,可以看到是bytes格式的
    b'xe7xa6xbbxe7xa6xbbxe5x8ex9fxe4xb8x8axe8x8dx89xefxbcx8c
    xe4xb8x80xe5xb2x81xe4xb8x80xe6x9exafxe8x8dxa3xe3x80x82
    xe9x87x8exe7x81xabxe7x83xa7xe4xb8x8dxe5xb0xbdxefxbcx8c
    xe6x98xa5xe9xa3x8exe5x90xb9xe5x8fx88xe7x94x9fxe3x80x82
    '
    
    >>> f=open("file2.txt","rb")
    >>> f.read().decode("utf8")     # 因为写入时是以"utf8"编码格式写入的,所以在这里要解码成"utf8"格式的
    '离离原上草,
    一岁一枯荣。
    野火烧不尽,
    春风吹又生。
    '
    
    >>> f=open("file3.txt","wb")    # 以写模式打开文件file3.txt
    >>> f.write("python")			# 此时直接向f对象中写入内容会抛出异常:写入的内容需要是bytes对象,不能是字符串格式的
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    TypeError: a bytes-like object is required, not 'str'
    >>> f.write("python
    ".encode("utf8"))		# 编码成'utf8'格式,再写入
    7
    >>> f.write("你好呀
    ".encode("utf8"))
    10
    >>> f.close()
    

    在系统命令提示符下查看文件大小及内容

    [root@bogon ~]# cat file3.txt
    python
    你好呀
    [root@bogon ~]# ll file3.txt
    -rw-r--r-- 1 root root 17 Jan 28 16:41 file3.txt
    

    以"b"模式打开文件的好处:

    1.读取文件的时候就是二进制格式的,不容易产生乱码
    2.处理非文本类型的文件时,写入文件的时候就需要以二制格式写入,否则会抛出异常
    

    例子:

    用python的二进制方法把一个张图片aa.jpg复制一份bb.jpg
    
    read_file=open('aa.jpg','rb')
    write_file=open("bb.jpg","wb")
    write_file.write(read_file.read())
    
    [root@bogon ~]# ll *.jpg
    -rw-r--r-- 1 root root 95406 Jan 19 08:38 aa.jpg
    -rw-r--r-- 1 root root 95406 Jan 28 17:15 bb.jpg
    

    总结:

    打开文件时,需要指定文件路径和打开方式。打开文件后,即可获取指定文件的文件句柄,然后通过操作文件句柄来操作指定文件
    	
    	打开文件的模式有:
    	r		只读模式,打开文件默认模式,文件必须存在,不存在则抛出异常
    	w		只写模式,文件不存在则创建,存在则清空原有内容
    	a		追加模式,可以读取文件,文件不存在则创建,存在则向文件追加内容
    
    “+”表示可以同时读写某个文件
    
    r+		读写(可读可写)
    w+		写读(可读可写)
    a+		写读(可读可写)
    
    "b"表示以字节的方式操作
    
    rb
    wb
    ab
    
    以b方式打开文件时,读取到的内容是字节类型,写入时也需要提供字节类型,不能指定编码
    

    小demo:

    用python方法,替换文件中的内容

    查看初始文件内容

    [root@bogon ~]# cat test.txt 
    aaaapythonaaaapythonaa
    bbbblinuxbbblinuxbbb
    cccmysqlcccmysqlccc
    dddnginxdddnginxddd
    

    现在想打test.txt文件中所有的nginx换成httpd

    脚本如下:

    import os
    
    
    read_f = open("test.txt", "r")
    write_f = open(".text.txt.swap", "w")
    
    for line in read_f:
    	if 'nginx' in line:
    		line = line.replace("nginx", "httpd")
    	write_f.write(line)
    
    read_f.close()
    write_f.close()
    
    os.remove("test.txt")
    os.rename(".text.txt.swap", "test.txt")
    

    运行这个python脚本,然后查看test.txt的内容

    [root@localhost ~]# cat test.txt 
    aaaapythonaaaapythonaa
    bbbblinuxbbblinuxbbb
    cccmysqlcccmysqlccc
    dddhttpddddhttpdddd
    

    会发现文件test.txt的内容已经被修改了

    with上下文管理

    使用open打开文件时,很容易会忘记关闭被打开的文件,这要一来被打开的文件一直运行在内存中,无形中造成了系统资源的浪费

    这时可以使用with上下文管理来进行文件操作,以解决因为忘记关闭文件而造成的系统资源的浪费

    使用with重构上面的内容替换的例子

    import os
    
    with open("a.txt","r") as read_f,open(".a.txt.swap","w") as write_f:
        for line in read_f:
            if "nginx" in line:
                line=line.replace("nginx","httpd")
            write_f.write(line)
    
    os.remove("a.txt")
    os.rename(".a.txt.swap","a.txt")
    

    也可以完成同样的功能,而且不用手动关闭被打开的文件

  • 相关阅读:
    You don't have permission to access / on this server.
    WampServer修改端口及菜单Localhost
    如何手机访问电脑服务器上的网页?
    Zed Shaw:程序员的常见健康问题
    js中匿名函数的N种写法
    HDU 1561 树形DP背包问题
    COJ 1156 Switching bulbs
    POJ 2891 Strange Way to Express Integers
    FZU 1402 猪的安家 中国剩余定理
    HDU 1573 解同余模线性方程组
  • 原文地址:https://www.cnblogs.com/renpingsheng/p/8372083.html
Copyright © 2011-2022 走看看