Python文件操作:高效处理文件的技巧

2023年 12月 1日 77.3k 0

文件操作是日常工作中不可或缺的一部分。无论是读取、写入、拷贝还是移动文件,都需要高效的文件操作技巧。本文将带领读者深入探索文件操作的世界,并分享实用的技巧和工具。通过掌握这些技能,您将能够更加轻松地管理和处理文件,提高工作效率和数据处理能力。

一、文件读写操作

在学习文件操作之前,先来回顾一下编码的相关以及数据类型的知识。

  • 字符串类型(str),在程序中用于表示文字信息,本质上是unicode编码中的二进制。
name = "lisa"
  • 字节类型(bytes),可表示文字信息,本质上是utf-8/gbk等编码的二进制(对unicode进行压缩,方便文件存储和网络传输。)
name = "lisa"
data = name.encode('utf-8')
print(data) # b'xe6xadxa6xe6xb2x9bxe9xbdx90'

result = data.decode('utf-8')
print(result) # "lisa"

可表示原始二进制(图片、文件等信息)

1. 读文件

读文本文件:

# 1.打开文件
file_object = open('info.txt', mode='rb')
# 2.读取文件内容,并赋值给data
data = file_object.read()
# 3.关闭文件
file_object.close()

print(data) # b'jack-123nxe6xadxa6xe6xb2x9bxe9xbdx90-123'
text = data.decode("utf-8")
print(text)

# 1.打开文件
file_object = open('info.txt', mode='rt', encoding='utf-8')

# 2.读取文件内容,并赋值给data
data = file_object.read()

# 3.关闭文件
file_object.close()

print(data) # "lisa"

读图片等非文本内容文件:

file_object = open('a1.png', mode='rb')
data = file_object.read()
file_object.close()

print(data) # x91xf6xf2x83x8aQFfvx8b7xccxedxc3}x7fTx9d{.3.xf1{xe8...

注意文件路径操作:

  • 相对路径,你的程序到底在哪里运行的?
  • 绝对路径
# 1.打开文件
file_object = open('/Users/wupeiqi/PycharmProjects/luffyCourse/day09/info.txt', mode='rt', encoding='utf-8')
# 2.读取文件内容,并赋值给data
data = file_object.read()
# 3.关闭文件
file_object.close()
    windows系统中写绝对路径容易出问题:
# file_object = open('C:\new\info.txt', mode='rt', encoding='utf-8')

file_object = open(r'C:newinfo.txt', mode='rt', encoding='utf-8')
data = file_object.read()
file_object.close()
print(data)

读文件时,文件不存在程序会报错:

Traceback (most recent call last):
  File "/Users/wupeiqi/PycharmProjects/luffyCourse/day09/2.读文件.py", line 2, in 
    file_object = open('infower.txt', mode='rt', encoding='utf-8')
FileNotFoundError: [Errno 2] No such file or directory: 'infower.txt'
# 判断路径是否存在?
import os

file_path = "/Users/wupeiqi/PycharmProjects/luffyCourse/day09/info.txt"
exists = os.path.exists(file_path)
if exists:
    # 1.打开文件
    file_object = open('infower.txt', mode='rt', encoding='utf-8')
    # 2.读取文件内容,并赋值给data
    data = file_object.read()
    # 3.关闭文件
    file_object.close()
    print(data)
else:
    print("文件不存在")

2. 写文件

写文本文件:

# 1.打开文件
# 路径:t1.txt
# 模式:wb(要求写入的内容需要是字节类型)
file_object = open("t1.txt", mode='wb')

# 2.写入内容
file_object.write(    "lisa".encode("utf-8")    )

# 3.文件关闭
file_object.close()
file_object = open("t1.txt", mode='wt', encoding='utf-8')

file_object.write("lisa")

file_object.close()

写图片等文件:

f1 = open('a1.png',mode='rb')
content = f1.read()
f1.close()

f2 = open('a2.png',mode='wb')
f2.write(content)
f2.close()

小案例:利用Python向某个网址发送请求并获取结果(利用第三方的模块)。

下载第三方模块:

pip install requests

使用第三方模块:

import requests

res = requests.get(url="网址")
print(res)
# 案例1:去网上下载一点文本,文本信息写入文件。
import requests

res = requests.get(
    url="https://movie.douban.com/j/search_subjects?type=movie&tag=%E7%83%AD%E9%97%A8&sort=recommend&page_limit=20&page_start=20",
    headers={
        "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36"
    }
)

# 网络传输的原始二进制信息(bytes)
# res.content

file_object = open('files/log1.txt', mode='wb')
file_object.write(res.content)
file_object.close()

案例2:去网上下载一张图片,图片写入本地文件。

import requests

res = requests.get(
    url="https://hbimg.huabanimg.com/c7e1461e4b15735fbe625c4dc85bd19904d96daf6de9fb-tosv1r_fw1200",
    headers={
        "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36"
    }
)

# 网络传输的原始二进制信息(bytes)
# res.content

file_object = open('files/美女.png', mode='wb')
file_object.write(res.content)
file_object.close()

注意事项:

(1)路径

  • 绝对路径
  • 相对路径

(2)文件不存在时,w模式会新建然后再写入内容;文件存在时,w模式会清空文件再写入内容。

二、文件打开模式

上文我们基于文件操作基本实现了读、写的功能,其中涉及的文件操作模式:rt、rb、wt、wb,其实在文件操作中还有其他的很多模式。

========= ===============================================================
Character Meaning
--------- ---------------------------------------------------------------
'r'       open for reading (default)
'w'       open for writing, truncating the file first
'x'       create a new file and open it for writing
'a'       open for writing, appending to the end of the file if it exists

'b'       binary mode
't'       text mode (default)

'+'       open a disk file for updating (reading and writing)

The default mode is 'rt' (open for reading text).

关于文件的打开模式常见应用有:

只读:r,rt,rb

  • 存在,读
  • 不存在,报错

只写:w,wt,wb

  • 存在,清空再写
  • 不存在,创建再写

只写:a,at,ab (常用于【尾部追加】)

  • 存在,尾部追加。
  • 不存在,创建再写。

三、常见功能

在上述对文件的操作中,我们只使用了write和read来对文件进行读写,其实在文件操作中还有很多其他的功能来辅助实现更好的读写文件的内容。

read,读

读所有【常用】:

f = open('info.txt', mode='r',encoding='utf-8')
data = f.read()
f.close()
f = open('info.txt', mode='rb')
data = f.read()
f.close()
- 读n个字符(字节)【会用到】
f = open('info.txt', mode='r', encoding='utf-8')
# 读1个字符
data = f.read(1)
f.close()

print(data) # 武
f = open('info.txt', mode='r',encoding='utf-8')

# 读1个字符
chunk1 = f.read(1)
chunk2 = f.read(2)
print(chunk1,chunk2)

f.close()
f = open('info.txt', mode='rb')

# 读1个字节
data = f.read(3)
f.close()

print(data, type(data))  # b'xe6xadxa6' 
f = open('info.txt', mode='rb')

# 读1个字节
chunk1 = f.read(3)
chunk2 = f.read(3)
chunk3 = f.read(1)
print(chunk1,chunk2,chunk3)

f.close()

readline,读一行:

f = open('info.txt', mode='r', encoding='utf-8')

v1 = f.readline()
print(v1)

v2 = f.readline()
print(v2)

f.close()
f = open('info.txt', mode='r', encoding='utf-8')
v1 = f.readline()
print(v1)
f.close()

f = open('info.txt', mode='r', encoding='utf-8')
v2 = f.readline()
print(v2)
f.close()

readlines,读所有行,每行作为列表的一个元素:

f = open('info.txt', mode='rb')

data_list = f.readlines()

f.close()

print(data_list)

循环,读大文件(readline加强版)【常见】:

f = open('info.txt', mode='r', encoding='utf-8')
for line in f:
    print(line.strip())
f.close()

write,写:

f = open('info.txt', mode='a',encoding='utf-8')
f.write("lisa")
f.close()
f = open('info.txt', mode='ab')
f.write( "lisa".encode("utf-8") )
f.close()

flush,刷到硬盘:

f = open('info.txt', mode='a',encoding='utf-8')

while True:
    # 不是写到了硬盘,而是写在缓冲区,系统会将缓冲区的内容刷到硬盘。
  f.write("lisa")
    f.flush()

f.close()
file_object = open('files/account.txt', mode='a')

while True:
    user = input("用户名:")
    if user.upper() == "Q":
        break
    pwd = input("密码:")
    data = "{}-{}n".format(user, pwd)
    file_object.write(data)
    file_object.flush()

file_object.close()

移动光标位置(字节):

f = open('info.txt', mode='r+', encoding='utf-8')

# 移动到指定字节的位置
f.seek(3)
f.write("lisa")

f.close()
注意:在a模式下,调用write在文件中写入内容时,永远只能将内容写入到尾部,不会写到光标的位置。

获取当前光标位置:

f = open('info.txt', mode='r', encoding='utf-8')

p1 = f.tell()
print(p1)  # 0

f.read(3)  # 读3个字符 3*3=9字节

p2 = f.tell()
print(p2)  # 9

f.close()
f = open('info.txt', mode='rb')

p1 = f.tell()
print(p1)  # 0

f.read(3)  # 读3个字节

p2 = f.tell()
print(p2)  # 3

f.close()

四、上下文管理

之前对文件进行操作时,每次都要打开和关闭文件,比较繁琐且容易忘记关闭文件。以后再进行文件操作时,推荐大家使用with上下文管理,它可以自动实现关闭文件。

with open("xxxx.txt", mode='rb') as file_object:
    data = file_object.read()
    print(data)

在Python 2.7 后,with又支持同时对多个文件的上下文进行管理,即:

with open("xxxx.txt", mode='rb') as f1, open("xxxx.txt", mode='rb') as f2:
    pass

五、文件修改

文件操作改的流程如下所示:

  • 以读的模式打开原文件。
  • 以写的模式创建一个新文件。
  • 将原文件的内容读出来修改成新内容,写入新文件。
  • 将原文件删除。
  • 将新文件重命名成原文件。
import os
# 1, 以读的模式打开原文件。
# 2,以写的模式创建一个新文件。
with open('jack自述',encoding='utf-8') as f1,
  open('jack自述.bak',encoding='utf-8',mode='w') as f2:
# 3,将原文件的内容读出来修改成新内容,写入新文件。
  old_content = f1.read()
  new_content = old_content.replace('jack', 'SB')
  f2.write(new_content)
os.remove('jack自述')
os.rename('jack自述.bak','jack自述')

六、面试题

文件操作,大文件如何读取内容 [ 50G的日志文件 ]:

def read_large_file(file_path, chunk_size=4096):
    with open(file_path, 'r') as file:
        while True:
            data = file.read(chunk_size)
            if not data:
                break
            yield data

# 使用示例
for chunk in read_large_file('large_log_file.log'):
    # 处理每个块的数据
    process_chunk(chunk)

在Python的文件操作中,readline()和readlines()是用于读取文件内容的两种常见方法,有什么区别?

  • readline()方法用于每次读取文件的一行内容,并将光标移动到下一行。每次调用readline(),它会返回文件中的下一行文本作为字符串。如果文件结束,readline()会返回空字符串。
  • readlines()方法则会一次性读取整个文件的所有行,并将每一行作为一个字符串存储在一个列表中。该方法返回一个包含所有行的列表。

区别:

  • 返回类型:readline()方法返回一个字符串,即一行的文本内容。readlines()方法返回一个列表,其中每个元素是一个字符串,即每行的文本内容。
  • 读取方式:readline()方法按行顺序逐个读取,每次调用读取一行。而readlines()方法一次读取整个文件,并将每行作为一个字符串保存在列表中。
  • 内存占用:readlines()方法将整个文件内容存储在内存中的列表中,可能会占用较多的内存。而readline()方法只加载一行内容,所以对内存的占用更加有限。

以下是示例代码来展示readline()和readlines()的使用:

# 使用readline()方法逐行读取文件

with open('file.txt', 'r') as file:
    line = file.readline()
    while line:
        print(line)
        line = file.readline()

# 使用readlines()方法读取所有行

with open('file.txt', 'r') as file:
    lines = file.readlines()
    for line in lines:
        print(line)

上述代码中,假设有一个名为file.txt的文本文件。

  • 第一个示例使用readline()方法逐行读取文件内容并打印,直到文件结束。
  • 第二个示例使用readlines()方法一次性读取整个文件的所有行,并使用for循环逐行打印。

需要注意的是,在以上示例中,为了演示目的,我们使用with open语句来打开文件,这样可以自动关闭文件句柄,确保文件操作的正确性和安全性。

七、文件路径和目录操作

在python中有一些专门的模块去操作文件路径与目录:

例如os模块:

1. os

首先导入:

import os

获取当前脚本绝对路径:

import os

abs_path = os.path.abspath(__file__)
print(abs_path)

获取当前文件的上级目录:

import os

base_path = os.path.dirname( os.path.dirname(路径) )
print(base_path)

路径拼接:

import os

p1 = os.path.join(base_path, 'xx')
print(p1)

p2 = os.path.join(base_path, 'xx', 'oo', 'a1.png')
print(p2)

判断路径是否存在:

import os

exists = os.path.exists(p1)
print(exists)

-创建文件夹:

import os

os.makedirs(路径)

path = os.path.join(base_path, 'xx', 'oo', 'uuuu')
if not os.path.exists(path):
    os.makedirs(path)

是否是文件夹:

import os

file_path = os.path.join(base_path, 'xx', 'oo', 'uuuu.png')
is_dir = os.path.isdir(file_path)
print(is_dir) # False

folder_path = os.path.join(base_path, 'xx', 'oo', 'uuuu')
is_dir = os.path.isdir(folder_path)
print(is_dir) # True

删除文件或文件夹:

os.remove("文件路径")

path = os.path.join(base_path, 'xx')
shutil.rmtree(path)

除了路径操作之外,再给出一些稍微常见的函数,如下所示:

2. os.listdir

listdir,查看目录下所有的文件   查看一个目录下所有的文件【第一层】

使用Python代码实现遍历一个文件夹的操作。

import os


def print_directory_contents(sPath):
    """
    这个函数接收文件夹的名称作为输入参数
    返回该文件夹中文件的路径
    以及其包含文件夹中文件的路径
    """
    for s_child in os.listdir(sPath):
        s_child_path = os.path.join(sPath, s_child)
        if os.path.isdir(s_child_path): 
            # 如果是文件夹,走递归操作
            print_directory_contents(s_child_path)
        else:
            # 就一定是文件
            print(s_child_path)

target_path = 'xxxx'
print_directory_contents(target_path)

使用listdir求文件夹的大小:

import os
lst = [r'D:code']
size = 0
while lst:
    path = lst.pop()
    name_lst = os.listdir(path)
    for name in name_lst:
        full_path = os.path.join(path,name)
        if os.path.isdir(full_path):
            lst.append(full_path)
        elif os.path.isfile(full_path):
            size += os.path.getsize(full_path)
print(size)

3. os.walk

Python标准库os模块的walk函数提供了遍历一个文件夹的功能,它返回一个生成器。walk,查看目录下所有的文件(含子孙文件)

import os

"""
data = os.listdir("/Users/jack/PycharmProjects/luffyCourse/day14/commons")
print(data)
# ['convert.py', '__init__.py', 'page.py', '__pycache__', 'utils.py', 'tencent']
"""

"""
要遍历一个文件夹下的所有文件,例如:遍历文件夹下的所有mp4文件
"""

data = os.walk("/Users/jack/Documents/视频教程/路飞Python/mp4")
for path, folder_list, file_list in data:
    for file_name in file_list:
        file_abs_path = os.path.join(path, file_name)
        ext = file_abs_path.rsplit(".",1)[-1]
        if ext == "mp4":
            print(file_abs_path)

使用walk来计算文件夹的总大小:

import os
g = os.walk('D:软件')
s=0
for i in g :
    path,dir_list,name_list = i
    for j in name_list:
        s+=os.path.getsize(os.path.join(path,j))
print(f'该文件夹大小为:{s/1024**2}MB')

八、shutil

shutil库是Python的一个标准高级文件操作模块,它与os模块形成互补的关系。os模块主要提供了对文件或文件夹的新建、删除、查看等基本操作,还支持对文件以及目录的路径操作。然而,对于复制、移动、删除、压缩、解压等复杂操作,os模块一般不提供,这时候就需要用到shutil库了。

shutil库中包含了一些实用的函数,如copy(), move(), rmtree()等,这些函数可以帮助我们进行文件和文件夹的复制、移动和删除等操作。例如,我们可以使用shutil.copy()函数来复制文件,只需要指定源文件路径和目标文件路径即可。此外,shutil库还提供了一些其他的实用函数,如make_archive()函数,它可以帮助我们将多个文件或文件夹打包成一个归档文件。由于对比于os模块,使用的没有那么频繁,所以这里对于shutil的使用稍微简化,感兴趣可以查看官方文档。

同样的首先导入:

import shutil

删除文件夹:

path = os.path.join(base_path, 'xx')
shutil.rmtree(path)

拷贝文件夹:

shutil.copytree("/Users/jack/Desktop/图/csdn/","/Users/jack/PycharmProjects/CodeRepository/files")

拷贝文件::

shutil.copy("/Users/jack/Desktop/图/csdn/WX20201123-112406@2x.png","/Users/jack/PycharmProjects/CodeRepository/")
shutil.copy("/Users/jack/Desktop/图/csdn/WX20201123-112406@2x.png","/Users/jack/PycharmProjects/CodeRepository/x.png")

文件或文件夹重命名:

shutil.move("/Users/jack/PycharmProjects/CodeRepository/x.png","/Users/jack/PycharmProjects/CodeRepository/xxxx.png")
shutil.move("/Users/jack/PycharmProjects/CodeRepository/files","/Users/jack/PycharmProjects/CodeRepository/images")

文件压缩:

"""
# base_name,压缩后的压缩包文件
# format,压缩的格式,例如:"zip", "tar", "gztar", "bztar", or "xztar".
# root_dir,要压缩的文件夹路径
"""
# shutil.make_archive(base_name=r'datafile',format='zip',root_dir=r'files')

解压文件:

"""
# filename,要解压的压缩包文件
# extract_dir,解压的路径
# format,压缩文件格式
"""
# shutil.unpack_archive(filename=r'datafile.zip', extract_dir=r'xxxxxx/xo', format='zip')

九、文件路径相关

在Python中进行文件操作时,路径同样非常重要。正确的路径可以确保程序能够找到需要读写的文件,并且避免覆盖或删除错误的文件。在使用Python进行文件操作时,可以使用绝对路径或相对路径来指定文件的位置。绝对路径是从根目录开始的完整路径,而相对路径则是相对于当前工作目录的路径。因此,在进行文件操作之前,必须先确定文件的路径,并使用合适的方法打开和关闭文件,以确保数据的正确读写和安全性。

1.  转义

windows路径使用的是,linux路径使用的是/。

特别的,在windows系统中如果有这样的一个路径 D:nxxxtxxxx1,程序会报错。因为在路径中存在特殊符 n(换行符)和t(制表符),Python解释器无法自动区分。

所以,在windows中编写路径时,一般有两种方式:

  • 加转义符,例如:"D:\nxxx\txxx\x1"
  • 路径前加r,例如:r"D:\nxxx\txxx\x1"

2. 程序当前路径

项目中如果使用了相对路径,那么一定要注意当前所在的位置。

例如:在/Users/jack/PycharmProjects/CodeRepository/路径下编写 demo.py文件:

with open("a1.txt", mode='w', encoding='utf-8') as f:
    f.write("你好呀")

用以下两种方式去运行:

  • 方式1,文件会创建在 /Users/jack/PycharmProjects/CodeRepository/ 目录下。
cd /Users/jack/PycharmProjects/CodeRepository/
python demo.py
  • 方式2,文件会创建在 `/Users/jack`目录下。
cd /Users/jack
python /Users/jack/PycharmProjects/CodeRepository/demo.py


import os

"""
# 1.获取当前运行的py脚本所在路径
abs = os.path.abspath(__file__)
print(abs) # /Users/jack/PycharmProjects/luffyCourse/day09/20.路径相关.py
path = os.path.dirname(abs)
print(path) # /Users/jack/PycharmProjects/luffyCourse/day09
"""
base_dir = os.path.dirname(os.path.abspath(__file__))
file_path = os.path.join(base_dir, 'files', 'info.txt')
print(file_path)
if os.path.exists(file_path):
    file_object = open(file_path, mode='r', encoding='utf-8')
    data = file_object.read()
    file_object.close()

    print(data)
else:
    print('文件路径不存在')

总结

文件操作是每个开发者和数据处理人员必备的技能。在本文中,我们详细介绍了文件读写、路径和目录操作、文件拷贝以及文件批量处理等方面的技巧和工具。通过学习和应用这些技能,您将能够更加灵活地处理和管理文件,提高工作效率。要记住,好的文件操作习惯对于数据处理和项目管理至关重要。继续探索并不断实践,您将成为一个更加优秀的文件操作专家!

相关文章

JavaScript2024新功能:Object.groupBy、正则表达式v标志
PHP trim 函数对多字节字符的使用和限制
新函数 json_validate() 、randomizer 类扩展…20 个PHP 8.3 新特性全面解析
使用HTMX为WordPress增效:如何在不使用复杂框架的情况下增强平台功能
为React 19做准备:WordPress 6.6用户指南
如何删除WordPress中的所有评论

发布评论