python原生处理properties文件

这个工具类使用 Python 的 configparser 模块操作 .properties 文件,核心是将 .properties 格式适配为 configparser 支持的 .ini 格式。

核心代码解释

1. 类初始化与配置解析
class Properties:def __init__(self, file_path: str, encoding: str = 'utf-8'):self.file_path = file_pathself.encoding = encodingself.config = configparser.ConfigParser(allow_no_value=True,           # 允许无值的键delimiters=('=',),             # 使用等号作为分隔符comment_prefixes=('#', '!'),   # 支持 # 和 ! 开头的注释inline_comment_prefixes=('#', '!')  # 支持行内注释)self.config.optionxform = str  # 保留键的大小写self._section = 'DEFAULT'      # 默认使用 DEFAULT 部分self.read()  # 读取文件内容
  • configparser.ConfigParser 是核心解析器
  • optionxform = str 防止键名被转为小写
  • 添加 [DEFAULT] 部分适配 .properties 格式
2. 读取文件
def read(self) -> None:try:with open(self.file_path, 'r', encoding=self.encoding) as f:# 添加 [DEFAULT] 部分使 configparser 能解析config_content = f"[{self._section}]\n" + f.read()self.config.read_string(config_content)except FileNotFoundError:# 文件不存在时创建空配置self.config[self._section] = {}
  • 读取文件内容并在前面添加 [DEFAULT] 部分
  • read_string 方法从字符串解析配置
3. 保存文件
def save(self) -> None:with open(self.file_path, 'w', encoding=self.encoding) as f:# 写入时跳过 [DEFAULT] 部分,保持 .properties 格式for key, value in self.config.items(self._section):if value is None:f.write(f"{key}\n")else:f.write(f"{key}={value}\n")
  • 保存时去掉 [DEFAULT] 部分,恢复 .properties 格式
  • 处理无值的键(如 key= 或单独的 key

新增功能实现

1. 遍历所有键值对
def items(self) -> List[Tuple[str, str]]:"""获取所有键值对的列表"""return list(self.config.items(self._section))def keys(self) -> List[str]:"""获取所有键的列表"""return list(self.config.options(self._section))def values(self) -> List[str]:"""获取所有值的列表"""return [value for _, value in self.config.items(self._section)]
2. 清空文件内容
def clear(self) -> None:"""清空 properties 文件的所有内容"""self.config[self._section] = {}self.save()

完整代码

以下是添加了遍历和清空功能的完整代码:

import configparser
from typing import Dict, Optional, Union, List, Tupleclass Properties:"""处理 .properties 文件的工具类,使用 configparser 实现"""def __init__(self, file_path: str, encoding: str = 'utf-8'):"""初始化 Properties 工具类Args:file_path: properties 文件路径encoding: 文件编码,默认为 utf-8"""self.file_path = file_pathself.encoding = encodingself.config = configparser.ConfigParser(allow_no_value=True,delimiters=('=',),comment_prefixes=('#', '!'),inline_comment_prefixes=('#', '!'))self.config.optionxform = str  # 保留键的大小写self._section = 'DEFAULT'  # 默认使用 DEFAULT 部分self.read()def read(self) -> None:"""读取 properties 文件内容"""try:with open(self.file_path, 'r', encoding=self.encoding) as f:# 添加默认 section 以兼容 .properties 格式config_content = f"[{self._section}]\n" + f.read()self.config.read_string(config_content)except FileNotFoundError:# 文件不存在,创建空配置self.config[self._section] = {}def get(self, key: str, default: Optional[str] = None) -> Optional[str]:"""获取指定键的值Args:key: 键名default: 键不存在时的默认值Returns:键对应的值,或默认值"""return self.config.get(self._section, key, fallback=default)def set(self, key: str, value: str) -> None:"""设置或修改键值对Args:key: 键名value: 值"""self.config.set(self._section, key, value)def remove(self, key: str) -> None:"""删除指定键Args:key: 键名"""self.config.remove_option(self._section, key)def set_batch(self, items: Union[Dict[str, str], List[Tuple[str, str]]]) -> None:"""批量设置键值对Args:items: 字典或元组列表形式的键值对"""if isinstance(items, dict):for key, value in items.items():self.set(key, value)elif isinstance(items, list):for key, value in items:self.set(key, value)def save(self) -> None:"""保存当前配置到文件"""with open(self.file_path, 'w', encoding=self.encoding) as f:# 写入时跳过 section 头,保持 .properties 格式for key, value in self.config.items(self._section):if value is None:f.write(f"{key}\n")else:f.write(f"{key}={value}\n")def items(self) -> List[Tuple[str, str]]:"""获取所有键值对的列表"""return list(self.config.items(self._section))def keys(self) -> List[str]:"""获取所有键的列表"""return list(self.config.options(self._section))def values(self) -> List[str]:"""获取所有值的列表"""return [value for _, value in self.config.items(self._section)]def clear(self) -> None:"""清空 properties 文件的所有内容"""self.config[self._section] = {}self.save()def __getitem__(self, key: str) -> str:"""通过 [] 语法获取值"""return self.get(key)def __setitem__(self, key: str, value: str) -> None:"""通过 [] 语法设置值"""self.set(key, value)def __contains__(self, key: str) -> bool:"""检查键是否存在"""return self.config.has_option(self._section, key)def __str__(self) -> str:"""返回所有键值对的字符串表示"""return '\n'.join([f"{k}={v}" for k, v in self.config.items(self._section)])

使用示例

以下是如何使用新增功能的示例:

# 初始化并读取文件
props = Properties('config.properties')# 遍历所有键值对
for key, value in props.items():print(f"{key} = {value}")# 获取所有键
all_keys = props.keys()
print("所有键:", all_keys)# 获取所有值
all_values = props.values()
print("所有值:", all_values)# 清空文件
props.clear()
print("文件已清空")# 添加新键值对
props['new_key'] = 'new_value'
props.save()

工作原理总结

这个工具类通过以下方式实现 .properties 文件操作:

  1. 格式适配

    • 读取时在文件内容前添加 [DEFAULT] 部分,使其符合 .ini 格式
    • 保存时去掉 [DEFAULT] 部分,恢复 .properties 格式
  2. 核心操作

    • configparser 负责解析和生成配置
    • optionxform = str 保持键的原始大小写
    • allow_no_value=True 支持无值的键
  3. 新增功能

    • items()/keys()/values() 方法提供遍历功能
    • clear() 方法清空所有配置并保存

这样就可以方便地操作 .properties 文件,无需了解底层实现细节。

DEFAULT 部分是 Python configparser 模块的一个特殊概念,源于 .ini 配置文件格式的设计。让我详细解释它的作用、必要性以及历史渊源:

1. DEFAULT 部分的作用

.ini 格式中,[DEFAULT] 是一个特殊的全局 section,它的作用是:

  • 为所有其他 section 提供默认值
  • 定义所有 section 都能继承的公共配置

例如:

[DEFAULT]
host = localhost
port = 3306[database]
name = mydb
user = root[test]
name = testdb

这里:

  • [database] 实际继承了 host=localhostport=3306
  • [test] 同样继承了 hostport,但覆盖了 name

2. 为什么在 .properties 文件中需要 DEFAULT?

.properties 文件本身没有 [section] 的概念,它是扁平的键值对结构。但 configparser 模块必须有一个 section 才能工作,因此我们:

  • 读取时:人为添加 [DEFAULT] 部分,让 configparser 能解析
  • 保存时:去掉 [DEFAULT] 部分,保持 .properties 格式

这是一种适配技巧,让 configparser 能处理 .properties 文件。

3. 历史渊源

.ini 格式的起源
  • .ini(Initialization)格式最早出现在 Windows 3.1 系统中,用于存储程序配置
  • 它使用 [section] 分组,支持层级化配置
  • [DEFAULT] 作为特殊 section,提供全局默认值
.properties 格式的起源
  • .properties 是 Java 语言的标准配置格式
  • 它是简单的 key=value 结构,没有 section 概念
  • 通常通过 java.util.Properties 类加载
Python 的 configparser
  • Python 的 configparser 模块最初设计用于解析 .ini 格式
  • 为了兼容 .properties,我们需要通过 [DEFAULT] 做适配

4. 必须使用 DEFAULT 吗?

是的,在使用 configparser 时必须有一个 section:

  • 如果不指定 [DEFAULT]configparser 会抛出 MissingSectionHeaderError
  • 其他替代方案(如自定义解析器)会更复杂,失去使用标准库的优势

可以将 [DEFAULT] 视为 .properties 文件的隐式容器,它只是让 configparser 正常工作的必要手段。

5. 实际影响

使用 [DEFAULT].properties 文件没有副作用:

  • 读取和保存时自动处理 [DEFAULT],文件本身不会改变
  • 所有键值对仍按原始格式存储
  • 工具类的 API(如 get()set())对用户保持透明,无需关心底层实现

总结

DEFAULT 部分是 configparser 模块的特性,用于适配 .ini 格式:

  • 在处理 .properties 文件时,它是必要的适配层
  • 不会影响文件内容,只是内存中的解析结构
  • 让我们能用标准库处理 .properties,避免手写解析器的复杂性

理解这一点后,你可以专注于使用工具类的 API,而无需担心 [DEFAULT] 的底层细节。

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

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

相关文章

【java 安全】 IO流

前言 IO是指 Input/Output,即输入和输出。以内存为中心: Input指从外部读入数据到内存,例如把文件从磁盘读取到内存,从网络读取数据到内存等等。Output指把数据从内存输出到外部,例如把数据从内存写入到文件&#xff0…

音视频同步技术初剖析:原理、实现与FFmpeg分析

音视频同步的基本原理 音视频同步主要依靠以下几个关键点:时间戳机制: 在封装格式(如MP4)中,音频帧和视频帧都带有时间戳(PTS, Presentation Time Stamp)这些时间戳表示该帧应该在什么时间被呈现同步策略: 音频为主时钟&#xff1…

掌控网页的魔法之书:JavaScript DOM的奇幻之旅

掌控网页的魔法之书:JavaScript DOM的奇幻之旅 在网页开发的世界里,JavaScript就像一位魔法师,而DOM(文档对象模型)则是它的魔法之书。没有DOM,JavaScript就像失去了咒语的巫师,无法操控网页的元…

【C语言】深入理解柔性数组:特点、使用与优势分析

C语言学习 柔性数组 友情链接:C语言专栏 文章目录C语言学习前言:柔性数组一、柔性数组的特点二、柔性数组的使用三、柔性数组的优势总结附录上文链接专栏前言: 在有结构体和动态内存分配的知识后,今天咱们来说说柔性数组吧&…

RV126平台NFS网络启动终极复盘报告

1. 初始目标与环境目标: 将RV1126开发板的启动方式,由从eMMC内部存储挂载根文件系统(rootfs),切换为通过网络挂载位于NFS服务器上的根文件系统。动机: 提升开发调试效率,实现代码修改后仅需重启即可验证,免…

一台显示器上如何快速切换两台电脑主机?

我注意到很多人会遇到一个常见的情况:他们有两台电脑,一台旧的用来处理基本的办公任务,另一台新的用来玩游戏。新手通常会用 DP端口连接第一台电脑的显示器,用 HDMI 连接第二台电脑。当他们想在两台电脑之间切换时,经常…

抗辐照与国产替代:ASM1042在卫星光纤放大器(EDFA)中的应用探索

摘要:本文以国科安芯推出的ASM1042芯片为例,通过分析ASM1042的抗辐照性能、高速数据传输能力、可靠性以及国产化优势,结合EDFA系统的需求特点,深入探讨了其在商业卫星光纤放大器(EDFA)项目中的应用潜力。AS…

鸿蒙ArkUI:声明式开发,高效构建全场景体验

目录 导言:开启鸿蒙应用开发的新范式 ArkUI框架概览 - 鸿蒙UI的灵魂 深入核心 - 声明式UI开发范式 命令式 vs 声明式:范式革命 ArkUI如何实现声明式? 创建内置组件 创建自定义组件 自定义组件的基本结构 ArkUI框架的核心特性与优势 …

数据查找 二叉查找树

查找一般分为有序查找和无序查找,这边在讲有序查找例二分查找二分查找就是在有序数组中,通过mid(lowhigh)/2来判定中间值,将中间值与待查找的值进行比较,如果待查找的值大于中间值,那么就将范围缩小,查找右…

几款开源的安全监控与防御工具分享

安全监控与防御工具概述 在现代网络安全架构中,合理选择和部署一系列的安全监控、检测、响应工具至关重要。下面我们将介绍一些常见的安全工具,包括 Elkeid、Wazuh、Caldera、ELK、Snort、Suricata、OpenHFW、OSSEC、GScan 和 Sysom,并详细介绍它们的下载链接、用处、使用方…

Elasticsearch:ES|QL 改进的时间线

作者:来自 Elastic Toms Mura 让我们回顾一下 ES|QL 的历史和它的改进。 更多阅读,Elasticsearch:ES|QL 查询展示。 Elasticsearch 配备了众多新功能,帮助你为自己的用例构建最佳搜索方案。查看我们的示例笔记本了解更多内容&…

Linux | Bash 子字符串提取

注:本文为 “ Bash 子字符串提取” 相关合辑。 英文引文,机翻未校。 如有内容异常,请看原文。 How to Extract Bash Substring? [5 methods] 如何提取 Bash 子字符串?[5 种方法] 2024-04-28 00:00:00 In Bash, a substring is…

Vue2 前端开发 - vue-quill-editor 富文本编辑器(编辑器基础案例、编辑器配置参数解读、编辑器事件)

一、vue-quill-editor 1、vue-quill-editor 概述vue-quill-editor 是一个基于 Quill 富文本编辑器的 Vue 组件vue-quill-editor 在 Vue 2 项目中可以很方便地集成与使用2、vue-quill-editor 安装 执行如下指令,安装 vue-quill-editor npm install vue-quill-editor …

断网情况下,网线直连 Windows 笔记本 和Ubuntu 服务器

在断网情况下,通过网线直连 Windows 笔记本 和 Ubuntu 服务器,并使用 VSCode 访问服务器及 Docker 容器 的步骤如下:1. 物理连接(网线直连) 1.1 使用网线连接 用 网线(Cat5e 或更高) 连接 Windo…

消息队列总结

为什么需要消息队列? 随着互联网快速发展,业务规模不断扩张,技术架构从单体演进到微服务,服务间调用复杂、流量激增。为了解耦服务、合理利用资源、缓冲流量高峰,「消息队列」应运而生,常用于异步处理、服务…

C#引用转换核心原理:类型视角切换

🔍 C#引用转换核心原理:类型视角切换 引用类型由内存指针和类型标记组成(如图1)。引用转换不改变内存地址,仅改变编译器识别对象的“视角”: B myVar1 new B(); // 实际B类型对象 A myVar2 (A)myV…

重要发布丨MaxKB V2正式发布,助力用户快速构建企业级智能体

2025年7月18日,MaxKB V2版本正式发布。MaxKB是一个强大易用的企业级智能体平台,致力于解决企业AI落地所面临的技术门槛高、部署成本高、迭代周期长等问题,让企业用户落地AI更简单。 秉承“开箱即用,伴随成长”的设计理念&#xff…

大语言模型任务分解与汇总:从认知瓶颈到系统化解决方案

一、缘起:为什么大模型需要"分而治之" 1.1 从一个真实场景说起 设想这样一个场景:你要求GPT-4帮你完成一份包含市场调研、竞品分析、财务预测和战略规划的商业计划书。即使是最先进的大模型,面对这样的复杂任务也会"力不从心&…

Spring核心注解@RequestMapping详解

RequestMapping 是 Spring Framework 中一个核心注解,用于在 Spring MVC(或 Spring WebFlux)中将 HTTP 请求映射到特定的处理器(Controller 中的方法)或处理器类。它告诉 Spring 框架:当一个匹配特定条件的…

OSPF路由协议的协商过程

OSPF的知识点非常多,协议过程也是一个不大不小的知识点,今天就简单的说一下,OSPF是如何进行协商的。OSPF(Open Shortest Path First)协议是一种用于路由选择的动态链路状态协议,是大型网络普遍使用的动态路…