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

    1、打开与关闭

    1.1、open() close()
    我们使用 open() 函数打开文件。这个函数将返回一个文件对象,我们对文件的读写都将使用这个对象。
    open() 函数需要三个参数,第一个参数是文件路径或文件名,第二个是文件的打开模式,第三个是编码格式。模式通常是下面这样的:
    "r",以只读模式打开,按字符读,也就是rt模式
    "w",以写入模式打开,如果文件存在将会清空所有内容,然后写入
    "a",以追加模式打开,写入到文件中的任何数据将自动添加到末尾
    "b",以二进制的方式打开
    r+:读文件并在文件最后进行追加内容
    w+:文件有可读可写权限
    rb:以二进制格式进行读,可用于在网络中传输。例如从gbk的windows系统中传递utf-8的linux系统就不需要编码了,直接解码就可以,效率上和r没啥区别,按字节读
    wb:以二进制格式进行写,并且需要指定编码格式
    如果用二进制方法读写,就不需要指定编码格式了
    默认的模式为只读模式,也就是说如果你不提供任何模式,open()函数将会以只读模式打开文件。

    f = open('1.txt', 'wb')
    f这个变量称为文件句柄,一般命名为f,f1,fh,file_handle等。

    坑:
    当文件路径是'C:UsersiDesktop1.txt'时会报错
    原因:文件路径中含有 、U、 时会认为是一个转义符
    解决方法:1、推荐路径前加r,写成r'C:UsersiDesktop1.txt'
                 2、再加一个,写成'C:\UsersiDesktop1.txt'
                      3、换成/


    f.tell() 显示光标目前所在的位置,按字节计算,不是字符
    f.seek(20)按字节查找,光标从第20个字节开始,其中1个汉字占3个字节
    f.truncate(100)截取从文档最开始到第100个字符串,且只能从最头开始截取不能从中间截取,且只能以a或r+模式打开文件
    f.flush()强制刷新硬盘,例如在f.write('1')时如果没有f.close()则不会立刻写入硬盘,这时可以使用flush()方法强制写入硬盘,一般用于日志实时显示时用。

    f.seek(参数1, 参数2): 参数1表示移动几个字节(注意不是字符),参数2表示参照物(0表示文件开头,1表示当前光标位置,2表示文件结尾)


    当程序执行结束后,我们需要关闭文件,如果不关闭会持续占用一些内存和操作系统资源,不关闭的文件也有可能造成数据丢失。

    我们使用方法 close() 完成这个操作,重复关闭不会有任何影响:
    file.close()

    1.2 with语句
    在实际情况中,我们应该尝试使用 with 语句处理文件对象,它会在文件用完后会自动关闭,就算发生异常也没关系。它是 try-finally 块的简写:

    1 with open('/etc/protocols') as file:
    2     count = 0
    3     for line in file:
    4         count += 1
    5     print(count)

    结果为:158
    这个程序中我们将打印文件的行数,可以看到代码块中并没有使用 close,但当代码执行到 with 代码块之外时,文件会被自动关闭。

    2、读取文件内容(read()、read(n)、readline()、readlines()、for循环)

    此处我们创建一个文件test.txt,这个文件的内容包括两行:
    Hello
    I love Python

    2.1、read()
    使用read()可以一次性读取整个文件的内容到字符串:

    1 f1 = open('1.txt',encoding='utf-8', mode='r') #这里1.txt和python程序在同一个路径下,所以只写了相对路径
    2 content = f1.read()
    3 print(content)
    4 f1.close()

    结果为:
    Hello
    I love Python

    当然也可以使用 with,避免忘记了 close:

    1 filename = '/home/test.txt'
    2 with open(filename) as file:
    3     file.read()

    2.2、read(size)
    read(size)有一个可选的参数size,用于指定字符长度,不是字节长度。如果没有指定size或者指定为负数,就会读取并返回整个文件。当文件大小为当前机器内存两倍时,就会产生问题。反之,会尽可能按比较大的size读取和返回数据。

    1 f1 = open('1.txt',encoding='utf-8', mode='r')
    2 content = f1.read(10)
    3 print(content)
    4 f1.close()

    结果为:
    Hello
    I l

    项目开发中,我们需要谨慎使用read()读取整个文件,因为有可能你的系统内存并不足够存储整个文件的内容。当read()执行后,再次执行将不会有任何内容的输出。

    2.3、readline()
    在处理文本文件的时候,我们通常会采用逐行处理,readline()就是用来每次读取文件的一行

    1 filename = '1.txt'
    2 f1 = open(filename,encoding='utf-8', mode='r')
    3 content = f1.readline()
    4 print(content)
    5 content = f1.readline()
    6 print(content)
    7 f1.close()

    结果为:
    Hello

    I love Python

    2.4、readlines()
    readlines()可以读取所有行,但不同于read(),这个函数的返回的是一个列表,列表中每个元素都是对应文本文件中一行内容的字符串:

    1 filename = '1.txt'
    2 f1 = open(filename,encoding='utf-8')
    3 content = f1.readlines()
    4 print(content)
    5 f1.close()

    ['ufeffHello ', 'I love Python']

    -------------------------------------------------------
    延伸
    1、发现读txt文件时最前面多了一个ufeff,当编码格式改成utf-8-sig时就正常
    f1 = open(filename,encoding='utf-8-sig')

    utf-8与utf-8-sig两种编码格式的区别:
    As UTF-8 is an 8-bit encoding no BOM is required and anyU+FEFF character in the decoded Unicode string (even if it’s the firstcharacter) is treated as a ZERO WIDTH NO-BREAK SPACE.
    UTF-8以字节为编码单元,它的字节顺序在所有系统中都是一样的,没有字节序的问题,也因此它实际上并不需要BOM(“ByteOrder Mark”)。但是UTF-8 with BOM即utf-8-sig需要提供BOM。

    2、打开文件时with open(filename, mode='r', encodint='utf-8) as f1:
    如果打开文件的方式写在filename后可以省略mode=,直接写'r'或'w',如果写在编码格式后面,就不能简写了,必须写成mode='r'

    --------------------------------------------------------
    2.5、for循环遍历文件句柄
    你可以for循环遍历文件句柄来读取文件中的每一行

    1 filename = '1.txt'
    2 f1 = open(filename,encoding='utf-8')
    3 content = f1.readlines()
    4 for i in content:
    5     print(i, end='')
    6   或print(i.strip())
    7 f1.close()

    结果为:
    Hello
    I love Python

    read() readline() readlines()的区别
    read()是以字符串形式显示所有内容
    readline()是以字符串形式每次显示一行内容,运行多次可逐行显示
    readlines()是以列表的形式显示所有内容


    对于大文件推荐用for循环读文件,例子:
    写一个程序,这个程序接受用户输入的字符串作为将要读取的文件的文件名,并且在屏幕上打印文件行数和文件内容:

    1 filename = input("Enter the file name: ")
    2 with open(filename) as file:
    3     count = 0
    4     for line in file:
    5         count += 1
    6         print(line)
    7     print('Lines:', count)

    运行程序:
    Enter the file name: /home/test.txt
    Hello World
    I love Python
    Lines: 2

    3、写入文件

    3.1、mode='w'写入模式
    最常用的写入文件的方法是 write(),通过write()方法打开一个文件然后我们随便写入一些文本。

    1 filename = '1.txt'
    2 with open(filename, encoding='utf-8',mode='w') as file:
    3     file.write('testline1')
    4     file.write('testline2')

    这个程序中,我们将文件以'w'模式打开,然后写入两段内容。
    ['testline1testline2']

    这时候发现文件中原来的内容已经被完全覆盖了,并且写入的内容占了一行(因为没有写入换行符的原因)。
    可见w这种模式是将文件先清空,再写入
    如果文件不存在,会先创建空文件,再写入

    3.2、mode='a'追加模式
    如果我们想向文件中增加内容如何操作呢?可以使用 'a' 追加模式打开文件:

    1 filename = '/home/shiyanlou/test.txt'
    2 with open(filename, mode='a') as file:
    3     file.write('testline3')
    4     file.write('testline4')

    再次读取,可以看到新增加的字符串附加到了原来的内容后面:
    ['testline1testline2testline3testline4']

    1 with open(filename,mode='a') as file:
    2      file.write(str+'
    ')

    在写入参数str后加“ ”则会在每次完成写入后,自动换行到下一行,下次写入时便会在下一行写入

    4、例子

    例子1:更改文件中的内容,将haha改为Python

     1 import os
     2 file = 'G:/python/1.txt'
     3 file_new = 'G:/python/1_new.txt'
     4 
     5 with open(file,mode='r',encoding='utf-8') as f:
     6     with open(file_new,mode='w',encoding='utf-8') as f_new:
     7         for line in f:
     8             if 'haha' in line:
     9                 line = line.replace('haha','Python')
    10             f_new.write(line)
    11         
    12 os.remove('G:/python/1.txt')
    13 os.rename('G:/python/1_new.txt','G:/python/1.txt')

    同时打开两个文件可以写成

    1 with open(file,mode='r',encoding='utf-8') as f,open(file_new,mode='w',encoding='utf-8') as f_new:

    或写成

    1 with open(file,mode='r',encoding='utf-8') as f,
    2     open(file_new,mode='w',encoding='utf-8') as f_new:

    如果想要拷贝一个图片或音视频文件,就需要用二进制方法打开,用rb和wb

    1 with open('1.jpg', 'rb') as file_1:
    2     with open('2.jpg', 'wb') as file_2:
    3         for i in file_1:
    4             file_2.write(i)

    例子2 :利用命令行参数进行操作

     1 import sys,os
     2 file = sys.argv[1]
     3 old_str = sys.argv[2]
     4 new_str = sys.argv[3]
     5 new_file = 'g:/python/1_new.txt'
     6 with open(file,mode='r',encoding='utf-8') as f,open(new_file,mode='w',encoding='utf-8') as f_new:
     7     for line in f:
     8         if old_str in line:
     9             line = line.replace(old_str,new_str)
    10         f_new.write(line)11 
    12 os.remove(file)
    13 os.rename(new_file,file)

    在命令行里输入:
    python test.py g:/python/1.txt Python haha
    将Python替换成haha

    获取sys.args的第2个参数和第3个参数也可以写成下面这样:

    _, old_str, new_str = sys.argv

     例子3:实现tail -f的效果

    通过代码实现tail -f access.log不断读取文件更新内容的效果

    1 import time
    2 with open('access.log', 'rb') as f:
    3     f.seek(0,2)    #将光标移动到文件末尾
    4     while True:
    5         line = f.readline()
    6         if line:
    7             print(line.decode(), end='')
    8         else:
    9             time.sleep(0.05)

     必须用二进制b的模式打开,因为seek的第二个参数如果

    • 为0时(文件开头为参照点),可以用r或rb模式
    • 为1(当前光标位置为参照点)或2(文件末尾为参照点)时,用r模式打开会报错,必须用rb模式打开
    • r模式默认就是rt模式,也就是用文本模式打开

    5、os.path 文件与文件夹操作

    在这里简单介绍下 os.path 这个非常常用的标准库,这个库主要的用途是获取和处理文件及文件夹属性。
    下面代码举例介绍几个常用的方法,更多的内容在使用到的时候查阅文档。

    os.path.abspath(path) 返回文件的绝对路径
    os.path.basename(path) 返回文件名
    os.path.dirname(path) 返回文件路径
    os.path.isfile(path) 判断路径是否为文件
    os.path.isdir(path) 判断路径是否为目录
    os.path.exists(path) 判断路径是否存在
    os.path.join(path1[, path2[, ...]]) 把目录和文件名合成一个路径

    实验代码内容,需要在 Python 交互环境中操作:
    需要先导入os模块
    >>> import os
    >>> filename = '/home/1/test.txt'
    >>> os.path.abspath(filename)
    '/home/1/test.txt'x
    >>>
    >>> os.path.basename(filename)
    'test.txt'
    >>> os.path.dirname(filename)
    '/home/1'
    >>>
    >>> os.path.isfile(filename)
    True
    >>>
    >>> os.path.isdir(filename)
    False
    >>> os.path.exists(filename)
    True
    >>> os.path.join('/home/1', 'test.txt')
    '/home/1/test.txt'
    >>>

  • 相关阅读:
    台州 OJ 3847 Mowing the Lawn 线性DP 单调队列
    洛谷 OJ P1417 烹调方案 01背包
    快速幂取模
    台州 OJ 2649 More is better 并查集
    UVa 1640
    UVa 11971
    UVa 10900
    UVa 11346
    UVa 10288
    UVa 1639
  • 原文地址:https://www.cnblogs.com/dxnui119/p/9868902.html
Copyright © 2011-2022 走看看