python中的文件操作2

news2024/10/24 16:24:00

文件遍历

在Python中,遍历文件通常指的是逐行读取文件中的内容。这种方式对于处理大型文件特别有用,因为它不需要一次性将整个文件加载到内存中。下面是几种常见的遍历文件内容的方法:

1. 使用with语句和for循环

这是最推荐的方式,因为它会自动管理文件资源,并且代码可读性高。

file_path = 'example.txt'
with open(file_path, 'r') as file:
    for line in file:
        print(line.strip())  # 使用strip()去除每行末尾的换行符

2. 使用readline()方法

如果你想更细致地控制读取过程(例如,在某些条件下提前停止),可以使用readline()方法逐行读取。

file_path = 'example.txt'
with open(file_path, 'r') as file:
    while True:
        line = file.readline()
        if not line:  # 如果readline返回空字符串,则表示已到达文件末尾
            break
        print(line.strip())

3. 使用readlines()方法

虽然这个方法不是真正意义上的“遍历”(因为它会先读取整个文件到一个列表中),但如果你需要获取所有行并且内存足够大时,这也是一个方便快捷的选择。

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

请注意,对于非常大的文件,第三种方法可能会消耗大量内存。通常情况下,第一种使用迭代器直接遍历文件对象的方式最为高效和优雅。

遍历二进制文件

如果你正在处理二进制数据(如图片或视频等),可能需要以块(block)来遍历:

file_path = './data/test_pic.png'

# 复制文件到另一个文件
file_copy = open('./data/test_pic_copy.png', 'wb')

with open(file_path, 'rb') as file:  # 注意模式为'rb'表示二进制模式读取
    while True:
        chunk = file.read(1024)  # 每次读取1024字节
        if not chunk:
            break
        
        # 处理chunk...
        file_copy.write(chunk)

file_copy.close()

在处理文本或二进制数据时选择正确的遍历方式对于编写高效、可维护代码至关重要。

常用方法

当你使用open()函数打开一个文件后,会得到一个文件对象。这个文件对象提供了多种方法来帮助你读取、写入和操作文件。以下是一些常用的方法:

1. read(size=-1)

  • 读取并返回文件中最多size个字符(文本模式)或字节(二进制模式)。如果未指定size或指定为负数,则读取并返回整个文件。
with open('example.txt', 'r') as file:
    content = file.read()
    print(content)

2. readline(size=-1)

  • 读取直到遇到下一个换行符为止,并返回一行字符串。如果指定了size,则在达到size字符后停止。
with open('example.txt', 'r') as file:
    while True:
        line = file.readline()
        if not line:
            break
        print(line.strip())

3. readlines(hint=-1)

  • 读取并返回一个列表,其中包含文件中的行。如果提供了可选参数hint,则当读取的行数足够接近hint时停止。
with open('example.txt', 'r') as file:
    lines = file.readlines()
for line in lines:
    print(line.strip())

4. write(string)

  • 将字符串写入文件,并返回写入的字符数(文本模式)或字节数(二进制模式)。
with open('output.txt', 'w') as file:
    num_chars = file.write("Hello, World!")
    print(f"Written {num_chars} characters.")

5. writelines(lines)

  • 向文件写入一个字符串列表。此方法不会自动添加行结束符,因此如果需要,必须自己在每行末尾加上\n
lines = ["First line", "Second line", "Third line"]
with open('output.txt', 'w') as file:
    # 如果需要,在每行末尾加上\n来实现换行。
    lines_with_newlines = [f"{line}\n" for line in lines]
    file.writelines(lines_with_newlines)

6. seek(offset, whence=0) 和 tell()

  • seek() 改变当前文件操作位置。offset表示相对于whence位置的偏移量:0表示从文件开头计算(默认),1表示从当前位置计算,2表示从文件末尾计算。
  • tell() 返回当前在文件中的位置。
# 读取文件,将第5个字节替换为'XXX'
with open('./data/test22.txt', 'rb+') as file:  # 使用二进制模式作为示例
    # 移动到第五个字节(索引从0开始)
    file.seek(5)
    # 报告当前位置
    current_position = file.tell()
    print(f"Current position: {current_position}")

    # 修改当前位置的内容,并回到起始位置查看更改。
    # 注意:在文本模式下修改可能会因编码问题导致错误。
    new_content = b'XXX'  # 替换为三个字节的内容
    old_content = file.read(len(new_content))
    if old_content != new_content:
        # 回退字节以覆盖刚才读取的内容。
        seek_back = file.seek(-len(new_content), 1)  # 1表示当前位置
        write_byte = file.write(new_content)
        seek_start = file.seek(0)
        updated_content = file.read().decode("utf-8")
        print(updated_content)

原文件:
在这里插入图片描述

执行后:
在这里插入图片描述

7. flush()

  • 刷新内部缓冲区,将数据立即写入磁盘而不是等待自动刷新发生。这对于长时间运行且需要即时保存结果的程序很有用。
# 这里perform_event_processing是假定存在的处理事件函数,
# 实际使用时应替换为具体逻辑代码块或函数调用。
import threading


def perform_event_processing():
    # 当前线程休眠3秒,模拟事件处理耗时
    threading.Event().wait(1000)
    print("Event processing started.")


# 假设我们正在记录一些重要事件,希望确保即使程序崩溃也能保存日志信息。
log_file_path = './data/test_log_example.log'
event_log = open(log_file_path, 'a')
try:
    event_log.write("Event started.\n")
    # 注释掉下面这行代码,以观察不同,在线程休眠期间,日志是否会被写入文件
    event_log.flush()
    perform_event_processing()
except Exception as e:
    event_log.write(f"Error occurred: {e}\n")
finally:
    event_log.close()

print("Event processing simulated.")

需求练习

示例文本文件

在Python中,文件操作主要涉及打开、读取、写入和关闭文件。
这是一门基础且重要的技能,因为它使得程序能够持久化数据,或者处理磁盘上的数据文件。
Python提供了一个内建的open函数用于文件的打开,以及文件对象提供的方法用于读取和写入。
使用open函数打开文件时,可以指定文件的路径和模式。模式指定了文件是用于读取、写入还是追加,以及文件是文本模式还是二进制模式。

初步实现

打开一个文本文件,将其中的’文件’字符替换为’文档’

with open('./data/test23.txt', 'r+') as file:
    text = file.read()
    replace_text = text.replace("文件", "文档")
    # 将当前操作位置移动到文件开头。这一步是必须的,因为在之前已经通过 .read() 方法将指针移动到了文件末尾。如果不重新定位到开始位置,接下来写入时会直接从末尾开始添加内容。
    file.seek(0)
    file.write(replace_text)
    # 防止替换后的文本比原始文本短,则新内容之后可能会保留旧数据残余部分。truncate 可以截断多余部分。
    file.truncate()

结果
在这里插入图片描述

注意

  • 这种方式在处理大型文本时可能不够高效,因为它一次性加载整个文本进内存。
  • 由于使用了’r+'模式,在不存在指定路径或者无法找到相应名称(test23.txt)时会抛出错误而非创建新文件。

改进实现

当处理大型文件时,一次性读取整个文件到内存确实可能导致效率低下甚至内存溢出。为了解决这个问题,可以采用分批处理的方法,逐行(或按一定大小的块)读取和写入文件。这样可以大大减少内存的使用。以下是一种改进方法,适用于逐行处理文本文件的场景:

分批处理替换文本

由于直接在原文件上进行逐行读写可能会复杂且易出错(特别是当替换后的文本长度与原文不同时),建议的方法是将修改后的内容写入一个临时文件,处理完成后再替换原文件。

import os

source_file_path = './data/test23.txt'
temp_file_path = './data/test23_temp.txt'

with open(source_file_path, 'r', encoding='utf-8') as read_file, \
     open(temp_file_path, 'w', encoding='utf-8') as write_file:
    for line in read_file:
        modified_line = line.replace("文件", "文档")
        write_file.write(modified_line)

# Replace the original file with the modified one
os.replace(temp_file_path, source_file_path)

解决方案解析

  1. 逐行读取:通过在with语句中同时打开源文件(用于读取)和临时文件(用于写入),可以逐行对源文件进行读取。这样就不需要一次性将整个文件内容加载到内存中。

  2. 逐行替换和写入:对于源文件的每一行,执行所需的替换操作,然后将结果写入临时文件。这个过程中,内存中仅需存储当前处理的行。

  3. 替换原文件:处理完成后,使用os.replace()方法将临时文件替换原文件。这个操作会自动删除原文件,并将临时文件重命名为原文件的名称。

注意事项

  • 这种方法适用于文本文件的逐行处理,可以有效减少内存消耗,特别是处理大文件时。
  • 完成替换操作后,原文件将被临时文件替代。确保在操作前做好相应的备份,以防数据丢失。
  • 如果处理过程中出现错误,可能需要手动清理临时文件或采取其他错误处理措施。
  • 对于更复杂的替换逻辑或大型二进制文件的处理,可能需要采用不同的策略。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1497880.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

模拟实现std::string类(包含完整、分文件程序)

std库中的string是一个类,对string的模拟实现,既可以复习类的特性,也可以加深对std::string的理解。 🌈一、搭建框架 ☀️1.新命名空间 本质上string是一个储存在库std里面的类,现在需要模拟实现一个string类&#…

MySQl基础入门④

上一遍知识内容 1.使用语句方式选择与查看数据库 打开我们navicat软件之后。 先不要点左边的连接内容,而是直接点击工具,再点击命令界面,也可以直接快捷键F6启动。 在我们的命令窗口输入以下命令: USE dataname;按回车。 这个语…

片上网络(NoC)技术的发展及其给高端FPGA带来的优势

片上网络(NoC)技术的发展及其给高端FPGA带来的优势 1. 概述 在摩尔定律的推动下,集成电路工艺取得了高速发展,单位面积上的晶体管数量不断增加。 片上系统(System-on-Chip,SoC)具有集成度高、功耗低、成本低等优势,已经成为大规模集成电路系统设计的主流方向,解决了…

RHEL9实现系统间复制文件

以下环境使用的是RHEL9学员练习环境 文件传送至远端 - sftp sftp是一个文件传输程序,类似于ftp目标可以指定为[user]host[:path]或URL格式为sftp://[user]host[:port][/path]sftp和ftp都是FTP协议的客户端工具,工作模式和使用方式均相同,但是…

Linux文件描述符剖析

文章目录 文件描述符文件描述符分配规则重定向软硬链接软链接(Symbolic Link):硬链接(Hard Link): 文件描述符 文件描述符(File Descriptor)是一个非负整数,用于标识打开…

【电路笔记】-NPN晶体管

NPN晶体管 文章目录 NPN晶体管1、概述2、双极NPN晶体管配置3、NPN晶体管中的α和β关系4、示例5、共发射极配置1、概述 NPN 晶体管是三端三层器件,可用作放大器或电子开关。 在前面的文章中,我们看到标准双极晶体管或 BJT 有两种基本形式。 NPN(负-正-负)配置和PNP(正-负…

腾讯云服务器和阿里云服务器哪家更优惠?2024价格对比

2024年阿里云服务器和腾讯云服务器价格战已经打响,阿里云服务器优惠61元一年起,腾讯云服务器61元一年,2核2G3M、2核4G、4核8G、4核16G、8核16G、16核32G、16核64G等配置价格对比,阿腾云atengyun.com整理阿里云和腾讯云服务器详细配…

好物周刊#44:现代终端工具

https://github.com/cunyu1943 村雨遥的好物周刊,记录每周看到的有价值的信息,主要针对计算机领域,每周五发布。 一、项目 1. Github-Hosts 通过修改 Hosts 解决国内 Github 经常抽风访问不到,每日更新。 2. 餐饮点餐商城 针对…

火柴排队(逆序对 + 离散化)

505. 火柴排队 原题链接 思路 如下是画图分析的一些过程 在这里贪心的思路是排序,然后两个数组都是从小到大那样对应的话最终的答案可达到最小 而我们只能交换相邻的火柴,故在这里先假设一个简化版本,即A有序,而只需要对B进行…

【学习笔记】数据结构与算法06 - 堆:上堆、下堆、Top-K问题以及代码实现

知识来源:https://www.hello-algo.com/chapter_heap/heap/#4 文章目录 2.5 堆2.5.1 堆(优先队列2.5.1.1 堆的常用操作 2.5.2 堆的存储与表示2.5.2.1 访问堆顶元素2.5.2.2 入堆时间复杂度 2.5.2.3 堆顶元素出堆时间复杂度 2.5.3 堆的常见应用2.5.4 建堆问…

WEB自动化测试----------Webdriver API 的使用

🔥 交流讨论:欢迎加入我们一起学习! 🔥 资源分享:耗时200小时精选的「软件测试」资料包 🔥 教程推荐:火遍全网的《软件测试》教程 📢欢迎点赞 👍 收藏 ⭐留言 &#x1…

PTA L2-015 互评成绩

学生互评作业的简单规则是这样定的:每个人的作业会被k个同学评审,得到k个成绩。系统需要去掉一个最高分和一个最低分,将剩下的分数取平均,就得到这个学生的最后成绩。本题就要求你编写这个互评系统的算分模块。 输入格式&#xf…

[项目设计] 从零实现的高并发内存池(五)

🌈 博客个人主页:Chris在Coding 🎥 本文所属专栏:[高并发内存池] ❤️ 前置学习专栏:[Linux学习] ⏰ 我们仍在旅途 ​ 目录 8 使用定长内存池脱离new 9. 释放对象时不传大小 10.性能优化 10.1…

使用Kali搭建钓鱼网站教程

一、前言 使用kali工具一分钟制作出和目标网站一模一样的钓鱼网站。目标用户使用钓鱼网站登录自己的账号,账号密码将被自动劫持。 二、钓鱼网站的制作过程 1.在虚拟机VMvare中登录kali linux 2.准备一个目标网址 3.在kail中搜索使用工具 4.在弹出的选项中选择第一…

AttributeError: ‘ChatGLMTokenizer‘ object has no attribute ‘sp_tokenizer‘

目录 问题描述 在使用ChatGLMlora微调的时候,报错“AttributeError: ChatGLMTokenizer object has no attribute sp_tokenizer“ ​编辑问题解决: 问题描述 在使用ChatGLMlora微调的时候,报错“AttributeError: ChatGLMTokenizer object h…

面试题之——事务失效的八大情况

事务失效的八大情况 一、非public修饰的方法 Transactional注解只能在在public修饰的方法下使用。 /*** 私有方法上的注解,不生效(因私有方法Spring扫描不到该方法,所以无法生成代理)*/ Transactional private boolean test() …

Flink实时数仓之用户埋点系统(一)

需求分析及框架选型 需求分析数据采集用户行为采集业务数据采集 行为日志分析用户行为日志页面日志启动日志APP在线日志 业务数据分析用户Insert数据用户Update数据 技术选型Nginx配置Flume配置MaxWellHadoopFlink架构图 需求分析 数据采集 用户行为采集 行为数据&#xff1…

【软件测试】上岗第一天,组长就要我做自动化测试?我该咋办?

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 如果你恰好刚刚进…

请说明Vue中的Error Boundaries

当我们开发基于Vue框架的应用时,我们经常会遇到各种错误处理的情况。Vue提供了一种非常强大且简单的方式来处理这些错误,那就是Error Boundaries(错误边界)。本文将从概念、用法和示例代码三个方面来详细介绍Vue中的Error Boundar…

数据结构—KMP 算法:

算法思想: KMP算法实现寻找主串中子串的位置时,主串指针地址不回退,在比对过程中串仅仅遍历一次,子串的回退可以是与当前主串可重新最多匹配的地址位置。 BF与KMP算法比对: KMP BF 主串不用回退 主串回退&#xf…