今天总结一篇工具箱文章。

  ini 类型文件通常作为程序的初始化文件。不同于我们常见的配置文件通篇 key-value 的键值对形式,ini 文件在键值对的基础之上还有分类节点,比如我们常见的 Mysql 数据库的初始化配置文件 my.cnf或my.ini,其内容格式通常是如下这样的:

[client]
port = 3306
socket = /data/3306/mysql.sock [mysqld]
user = mysql
port = 3306
socket = /data/3306/mysql.sock
basedir = /usr/local/mysql
datadir = /data/3306/data

  对于这种格式的文件的读取操作,Java中常用 Properties 类是不太好使的。当然,你也可以自己凭着高超的撸码水平去手写工具方法进行读写操作,但肯定还是比较费神的。实际上我们有第三方工具类库可供选择。此处博主分享的类库叫 org.dtools.javaini。整个工具包很轻便,能够支持基本的读写,格式校验等,官方教程很详细,花很少的时间就能上手。当然,结合项目的使用情况,自己还是需要自己进一步封装些方法以便更好的使用。前人种树,后人乘凉,博主也抛转引玉的写了几个:

package module.ini;

import com.alibaba.fastjson.JSONObject;
import org.dtools.ini.*;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.Set; /**
* @date: 2019/10/16 19:11
* @author: chen
* @desc: org.dtools.javaini-v1.1.00.jar 工具包读写ini 文件工具类
*/
public class IniUtil { // ini 文件抽象表示
private static IniFile iniFile = null;
// 要操作的文件实例
private static File file = null; // 操作 ini 文件的阅读器和书写器,通过它们来进行具体的读和写操作
private IniFileReader iniFileReader = null;
private IniFileWriter iniFileWriter = null; /**
* @param filePath 文件路径
* @param caseSensitive 是否区分大小写 默认false
* @param validator 格式校验器
*/
public IniUtil(String filePath, IniValidator validator, boolean caseSensitive) {
file = new File(filePath);
iniFile = new BasicIniFile(validator, caseSensitive);
try {
init();
} catch (IOException e) {
e.printStackTrace();
}
} public IniUtil(String filePath) {
this(filePath, new IniValidator(), false);
} public IniUtil(String filePath, IniValidator validator) {
this(filePath, validator, false);
} public IniUtil(String filePath, boolean caseSensitive) {
this(filePath, new IniValidator(), caseSensitive);
} /**
* 初始化 ini 文件的阅读器和书写器
*/
private void init() throws IOException {
iniFileReader = new IniFileReader(iniFile, file);
iniFileWriter = new IniFileWriter(iniFile, file);
iniFileReader.read();
} /**
* 读取 ini 文件转换数据为 Json对象
*/
public JSONObject getIniFileInfo() {
Iterator<IniSection> sectionIterator = iniFile.iterator();
JSONObject jsonObject = new JSONObject();
while (sectionIterator.hasNext()) {
IniSection section = sectionIterator.next();
Iterator<IniItem> itemIterator = section.iterator();
JSONObject child = new JSONObject();
while (itemIterator.hasNext()) {
IniItem item = itemIterator.next();
child.put(item.getName(), item.getValue());
}
jsonObject.put(section.getName(), child);
}
return jsonObject;
} /**
* 获取某个节点下的所有键值对
*/
public JSONObject getIniBySection(String sectionName) throws Exception {
IniSection section = getSection(sectionName);
Iterator<IniItem> iterator = section.iterator();
JSONObject jsonObject = new JSONObject();
while (iterator.hasNext()) {
IniItem item = iterator.next();
jsonObject.put(item.getName(), item.getValue());
}
return jsonObject;
} /**
* 获取某个节点下某个条目的值
*/
public Object getItemByName(String sectionName, String itemName) throws Exception {
JSONObject iniBySection = this.getIniBySection(sectionName);
return iniBySection.get(itemName);
} /**
* 新增或修改某节点条目
*/
public void addOrUpdateItem(String sectionName, String itemName, String itemValue) throws Exception {
IniSection section = getSection(sectionName);
IniItem iniItem = section.addItem(itemName);
if (iniItem == null)
iniItem = section.getItem(itemName);
iniItem.setValue(itemValue);
iniFileWriter.write();
} /**
* 新增或修改某节点条目 可添加注释
*/
public void addOrUpdateItem(String sectionName, String itemName, String itemValue,String comment) throws Exception {
IniSection section = getSection(sectionName);
IniItem iniItem = section.addItem(itemName);
if (iniItem == null)
iniItem = section.getItem(itemName);
iniItem.setValue(itemValue);
iniItem.setPreComment(comment); // 添加前置注释
iniFileWriter.write();
} /**
* 新增或修改某节点条目
*/
public void addOrUpdateItems(String sectionName, Map<String, Object> itemMap) throws Exception {
IniSection section = iniFile.getSection(sectionName);
Set<String> items = itemMap.keySet();
section.addItems(items.toArray(new String[0]));
iniFileWriter.write();
} /**
* 新增节点
*/
public void addSection(String sectionName) throws IOException {
if (iniFile.addSection(sectionName) == null)
return;
iniFileWriter.write();
} /**
* 删除 某节点
*/
public void removeSection(String sectionName) throws IOException {
if (iniFile.removeSection(sectionName) == null)
return;
iniFileWriter.write();
} /**
* 删除 某条目
*/
public void removeItem(String sectionName, String itemName) throws Exception {
IniSection section = getSection(sectionName);
section.removeItem(itemName);
iniFileWriter.write();
} private IniSection getSection(String sectionName) throws Exception {
if (!iniFile.hasSection(sectionName)) {
throw new Exception("The ini file【" + file.getName() + "】 has no section named " + sectionName);
}
return iniFile.getSection(sectionName);
} }

  作为一个比较简单的工具包,应对 ini 类型文件基本的增删改查足够了。如果你要深度使用,还有些问题需要你自己来解决——

    ① 工具包中对文件默认采用 ASCII 编码,所以对ASCII 码之外的字符比如中文字符就无法支持,如果读写过程中出现中文将会乱码;
    ② 对注释的支持也不足够。常见的注释为 #,但是作者却只给了以 ; 和 // 号开头的注释,,如果原文件有 # 类型的注释,读写操作后会被清理掉;

  由于类库中并没有提供设置编码或注释标注的方法,所以,比较好的办法就是自己下载源码,在源码上进行改动,然后自己打包到自己的项目中使用。以下是博主对代码的改动经验——

   首先,对于字符的问题,作者是在 IniFIleWriter 类中定义了一个表示字符的常量,去掉 final 修饰符,便于使用过程中动态修改编码:

                

  其次,对于注释,作者在 Commentable 接口中定义了表示注释开头的 ‘;’ 标识,由于是声明在接口中,默认就是static final 的,所以要改成动态设置的比较难办,改动会比较多,比较好的实践也是最简单粗暴的方式——直接改成通常的 # 注释符就可以了:

                

  最后,重新打成 jar 放入你的项目中或放入你的 maven 仓库。好了,工具方法,就长话短说了,祝使用愉快。

  如有什么问题或错漏,欢迎留言交流,不胜感激!

ini 文件操作指南的更多相关文章

  1. C# ini文件操作【源码下载】

    介绍C#如何对ini文件进行读写操作,C#可以通过调用[kernel32.dll]文件中的 WritePrivateProfileString()和GetPrivateProfileString()函 ...

  2. C#读取ini文件的方法

    最近项目用到ini文件,读取ini文件,方法如下: using System; using System.Collections.Generic; using System.Linq; using S ...

  3. IIS不能下载ini文件

    1.打开IIS. 2.选择站点或者存放*.ini文件的目录,右键菜单中选择属性. 3.选择“HTTP头”选项卡. 4.点击“MINE类型”. 5.点击“新建”. 6.这是跳出一个对话框,在“扩展名”一 ...

  4. c# 利用动态库DllImport("kernel32")读写ini文件(提供Dmo下载)

    c# 利用动态库DllImport("kernel32")读写ini文件 自从读了设计模式,真的会改变一个程序员的习惯.我觉得嘛,经验也可以从一个人的习惯看得出来,看他的代码编写习 ...

  5. 伪静态重写模块rewrite.dll及httpd.ini文件参考下载

    伪静态重写模块rewrite.dll及httpd.ini文件参考下载 http://www.ledaokj.com/download/rewrite.rar 服务器端开启伪静态,可以查看以下文章< ...

  6. c#读取INI文件

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.I ...

  7. 创建Unicode格式的INI文件

    前段时间由于开发一个软件,需要调用别人的接口,虽然我的软件是Unicode编码,对方的模块也是Unicode编码,但是对方提供的接口却是Ansi接口,在非中文系统下,由于涉及到中文路径,导致Ansi和 ...

  8. 【vbs】vbs写ini文件

    这两天在折腾给一个项目打安装包,第一次接触软件打包,用的Advanced Installer(以下简称AI),应该说如果安装过程没有特殊动作(常规动作指释放文件.写注册表.建快捷方式等)的话,倒挺傻瓜 ...

  9. ini文件操作

    Config.ini 文件操作 [SYS] sysname=hy company=hyhy tel=2 using System; using System.Collections.Generic; ...

随机推荐

  1. 【Offer】[9] 【用两个栈实现队列】

    题目描述 思路分析 Java代码 代码链接 题目描述 用两个栈实现队列 思路分析 栈--> 先进后出 队列--> 先进先出 进队列操作,选择栈s1进栈,关键在与实现出队列操作,要考虑到队列 ...

  2. hdu 1007 Quoit Design 题解

    原题地址 题目大意 查询平面内最近点对的距离,输出距离的一半. 暴力做法 枚举每一个点对的距离直接判断,时间复杂度是 $ O(n^2) $,对于这题来说会超时. 那么我们考虑去优化这一个过程,我们在求 ...

  3. CF785D Anton and School – 2

  4. CNCF 宣布成立应用交付领域小组,正式开启云原生应用时代

    作者|赵钰莹 作为云原生领域的顶级开源社区, Cloud Native Computing Foundation (云原生基金会,以下简称 CNCF)近日宣布成立 Application Delive ...

  5. .Net基础篇_学习笔记_第六天_For循环语法

    For循环:专门处理已知循环次数的循环.  小技巧:连续敲击两下TAB键循环体自动搭建完成. For循环语法: for(表达式1;表达式2;表达式3){ 循环体;}表达式1一般为声明循环变量,记录循环 ...

  6. 【学习笔记】python3核心技术与实践--开篇词

    python的应用和流行程度: Python 可以运用在数据处理.Web 开发.人工智能等多个领域,它的语言简洁.开发效率高.可移植性强,并且可以和其他编程语言(比如 C++)轻松无缝衔接.现如今,不 ...

  7. Thinkphp5.0 仿百度糯米 开发多商家 电商平台(完整版)

    目录第1章 课程简介第2章 需求分析第3章 快速掌握thinkphp5第4章 任性的TP5模块第5章 生活服务分类管理模块第6章 百度地图应用封装第7章 打造属于TP5自己的发送邮件服务第8章 商户模 ...

  8. 使用gcc不同选项来编译查看中间生成文件

    gcc编译C程序的总体流程如下图 用到的命令如下: .c---> .i gcc -E hello.c .c--->.s gcc -S hello.c .c--->.o gcc -c ...

  9. 004:CSS三大重点之二:浮动(拖标、不占位置、转行内块)

    目录 1:拖标.不占位.转行内块 2:首先浮动的盒子需要和标准流的父级搭配使用,其次 特别的注意浮动可以使元素显示模式体现为行内块特性. 3:清除浮动 前言 CSS的定位机制有3种:普通流(标准流). ...

  10. C++基础之关联容器

    关联容器 关联容器和顺序容器的本质区别:关联容器是通过键存取和读取元素.顺序容器通过元素在容器中的位置顺序存储和访问元素.因此,关联容器不提供front.push_front.pop_front.ba ...