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'
    >>>

  • 相关阅读:
    zookeeper java调用及权限控制
    走进C++程序世界------IO标准库介绍
    Unity3d 镜面折射 vertex and frag Shader源代码
    servlet上传文件报错(二)
    模仿linux内核定时器代码,用python语言实现定时器
    6.12交流
    python学习(三) 使用字符串
    JAVA面试(四)
    python学习(二) 列表和元组
    C++面试题(三)
  • 原文地址:https://www.cnblogs.com/dxnui119/p/9868902.html
Copyright © 2011-2022 走看看