编程的时候都要把一些可变的参数放到配置文件里面, 常见的配置文件就是xml, 键值对等. 但是我觉得xml有点大, 浪费; properties这种键值对有点简单了. 就仿照nginx的配置文件格式(不全一样)写了一个配置读取工具. 第一次发代码, 求指导.
首先是配置文件的格式
#注释格式
#system是一个配置段
system {
#子配置段config
config {
#一个配置项
url : localhost
#配置项的值是数组, 用[]包括, 逗号分隔
message : [not login, ok]
}
ok {
#配置项可以只有键(配置项名)而没有值
path1
}
user {
/user
}
whoami : wenjianwzz
}
#也可以不包括在配置段里面
where : cd
然后就是使用方法
public static void main(String args[]) {
//加载配置文件, 返回一个根配置段(文件中所有的)
Config config = Config.load(ResourceUtil.getResourcePath("new.conf"), "UTF-8");
//定位配置, @表示查找配置项, 如果不加@则是查找子配置段
System.out.println(config.locateValue("/system/@whoami"));
//可以用..上翻
System.out.println(config.locateValue("/system/../@where"));
//数组配置的某一值
System.out.println(config.locateValue("/system/config/@message[0]"));
//查找子孙配置段, 不用/打头表示从当前配置段定位, 这里因为本来就是根配置, 所以就一样了
config = config.locateConfig("system/config");
//从当前配置段定位
System.out.println(config.locateValue("@message[0]"));
// 上翻的作用
System.out.println(config.locateValue("../@whoami"));
}
这个用path定位的方式是受xpath启发, 觉得挺好用的
下面就是源码
package eu.jk.config;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import eu.jk.helper.ResourceUtil;
/**
* 配置段类
*
* @author wenjianwzz
*
*/
public final class Config {
/**
* 配置项
*/
private Map<String, ConfigItem> items = new HashMap<String, ConfigItem>();
/**
* 子配置段
*/
private Map<String, Config> subconfigs = new HashMap<String, Config>();
/**
* 父亲
*/
private Config parent = null;
/**
* 配置段名
*/
private String name = null;
/**
* 取得键对应的值,如果不存在对应的值, 返回NULL
*
* @param key
* @return String
* @see java.util.hashtable#get(Object)
*/
public String getValue(String key) {
return items.get(key).getValue();
}
/**
* 取得键对应的值,如果不存在对应的值, 返回NULL
*
* @param key
* @return String
* @see java.util.hashtable#get(Object)
*/
public String getValue(String key, int index) {
return items.get(key).getValue(index);
}
/**
* 查找配置项
* @param key
* @return
*/
public ConfigItem getConfigItem(String key) {
return items.get(key);
}
/**
* 是否包含指定键的配置项
* @param key
* @return
*/
public boolean contains(String key) {
return items.containsKey(key);
}
/**
* 获取所有的配置项名称
* @return
*/
public Collection<String> getItemsKeys() {
return items.keySet();
}
/**
* 获取配置段名
*/
public String getName() {
return name;
}
/**
* 获取所有子配置段的名称
* @return
*/
public Collection<String> getSubconfigKeys() {
return subconfigs.keySet();
}
/**
* 获取子配置段
* @param name
* @return
*/
public Config getSubconfig(String name) {
return subconfigs.get(name);
}
/**
* 是否包含指定名称的子配置段
* @param name
* @return
*/
public boolean containsSubconfig(String name) {
return subconfigs.containsKey(name);
}
/**
* 加载配置项
* @param id
* @return
*/
public ConfigItem locateItem(String id) {
return (ConfigItem) locate(id);
}
/**
* 加载配置值
* @param id
* @return
*/
public String locateValue(String id) {
Object object = locate(id);
if (object == null)
return null;
if (object instanceof ConfigItem)
return ((ConfigItem)object).getValue();
if (object instanceof String)
return (String) object;
return null;
}
/**
* 加载配置项
* @param id
* @return
*/
public Config locateConfig(String id) {
return (Config) locate(id);
}
/**
* 加载
* @param id
* @return
*/
protected Object locate(String id) {
if (id == null)
return null;
// 定位基点
Config base = this;
if (id.startsWith("/"))
while (base.getParent() != null)
base = base.getParent();
String[] fields = id.split("/");
for (String field : fields) {
field = field.trim();
if ("".equals(field))
continue;
if (field.startsWith("@")) {
if (field.matches("^@.+\\[[0-9]+\\]$")) {
String key = field.substring(1, field.indexOf('['));
String index = field.substring(field.indexOf('[') + 1, field.indexOf(']'));
if (!isDigit(index))
return null;
return base.getConfigItem(key).getValue(Integer.parseInt(index));
}
return base.getConfigItem(field.substring(1));
}
if ("..".equals(field))
base = base.getParent();
else
base = base.getSubconfig(field);
if (base == null)
return null;
}
return base;
}
/**
* 添加参数, 如果原来存在参数, 会接在后面成为一个数组
*
* @param key
* @param value
*/
protected void addParameters(String key, String value) {
ConfigItem item = items.get(key);
if (item == null)
items.put(key, new ConfigItem(key, value));
else
item.addValue(value);
}
protected void setConfigName(String configName) {
this.name = configName;
}
protected Config(String configName) {
this.name = configName;
}
/**
* 添加子配置段
* @param subconfig
*/
protected void addSubconfig(Config subconfig) {
subconfig.setConfigName(subconfig.getName().trim());
subconfigs.put(subconfig.getName(), subconfig);
}
protected void setParent(Config parent) {
this.parent = parent;
}
protected Config getParent() {
return parent;
}
/**
* 加载配置文件, 返回根配置段
* @param path 配置文件的路径
* @param encoding 文件编码, 如果为null则使用系统默认编码
* @return 根配置
*/
public static Config load(String path, String encoding) {
try {
return load(new FileInputStream(path), encoding, path);
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
}
}
/**
* 使用系统默认编码加载配置文件, 返回根配置
* @param path 配置文件的路径
* @return 根配置
*/
public static Config load(String path) {
return load(path, null);
}
/**
* 从流中加载配置, 使用系统默认编码
* @param input 输入流
* @param rootConfigName 根配置名
* @return
*/
public static Config load(InputStream input, String rootConfigName) {
return load(input, null, rootConfigName);
}
/**
* 从流中加载配置, 使用系统默认编码
* @param input 输入流
* @return 根配置
*/
public static Config load(InputStream input) {
return load(input, null, "anonymous");
}
/**
* 从流中加载配置, 使用指定编码
* @param input 输入流
* @param encoding 编码
* @param rootConfigName 根配置名
* @return 根配置
*/
public static Config load(InputStream input, String encoding, String rootConfigName) {
Config root = new Config(rootConfigName);
for (String line : readLines(input, encoding)) {
line = line.trim();
if (line.startsWith("#"))
continue;
if (line.length() == 0)
continue;
//SubConfig found
if (line.matches("^.+\\{$")) {
String name = new String(line.replace('{', '\b').trim());
Config sub = new Config(name);
root.addSubconfig(sub);
sub.setParent(root);
root = sub;
continue;
}
/*
* 往上翻一层
*/
if ("}".equals(line)) {
root = root.getParent();
continue;
}
/*
* 键值对的配置
*/
if (line.contains(":")) {
int index = line.indexOf(':');
String key = line.substring(0, index).trim();
String value = line.substring(index + 1).trim();
if (value.matches("^\\[.+\\]$")) {
value = value.substring(1, value.length()-1);
for (String sub : value.split(",")) {
sub = sub.trim();
if (sub.length() == 0)
continue;
root.addParameters(key, sub);
}
continue;
}
root.addParameters(key, value);
continue;
}
root.addParameters(line, null);
}
return root;
}
/**
* 判断一个字符串是不是数字
* @param str
* @return boolean
*/
private static boolean isDigit(String str) {
if (str == null)
return false;
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if (c < 48 || c > 57)
return false;
}
return true;
}
/**
* 从流中读取所有行
* @param path
* @param encoding
* @return
*/
private static List<String> readLines(InputStream input, String encoding) {
InputStreamReader fr;
List<String> list = new ArrayList<String>();
try {
if (encoding != null)
fr = new InputStreamReader(input, encoding);
else
fr = new InputStreamReader(input);
BufferedReader br = new BufferedReader(fr);
String line = br.readLine();
while (line != null) {
list.add(line);
line = br.readLine();
}
br.close();
fr.close();
} catch (Exception e) {
e.printStackTrace();
return null;
}
return list;
}
public static void main(String args[]) {
//加载配置文件, 返回一个根配置段(文件中所有的)
Config config = Config.load(ResourceUtil.getResourcePath("new.conf"), "UTF-8");
//定位配置, @表示查找配置项, 如果不加@则是查找子配置段
System.out.println(config.locateValue("/system/@whoami"));
//可以用..上翻
System.out.println(config.locateValue("/system/../@where"));
//数组配置的某一值
System.out.println(config.locateValue("/system/config/@message[0]"));
//查找子孙配置段, 不用/打头表示从当前配置段定位, 这里因为本来就是根配置, 所以就一样了
config = config.locateConfig("system/config");
//从当前配置段定位
System.out.println(config.locateValue("@message[0]"));
// 上翻的作用
System.out.println(config.locateValue("../@whoami"));
}
}
package eu.jk.config;
import java.util.ArrayList;
import java.util.List;
/**
* 配置项
* @author WZZ
*
*/
public final class ConfigItem {
String key;
List<String> values = new ArrayList<String>();
protected ConfigItem(String key) {
this.key = key;
}
protected ConfigItem(String key, String value) {
this.key = key;
values.add(value);
}
protected void addValue(String value) {
values.add(value);
}
public String getKey() {
return key;
}
public String getValue() {
if (values.size() <= 0)
return null;
return values.get(0);
}
public String getValue(int index) {
if (values.size() <= index || index < 0)
return null;
return values.get(index);
}
public int size() {
return values.size();
}
}
分享到:
相关推荐
在实际开发中,为了提高代码的可复用性和灵活性,我们还可以考虑将这两个工具类整合为一个,提供通用的配置文件读取接口,通过文件扩展名或配置文件内容自动识别是`.properties`还是`.yml`格式,并进行相应的读取...
系统开发的时候,都会涉及到一些配置文件的读取,为方便从配置文件中读取我们预先设置的值,我做了一个简单配置文件读取工具类。这个类主要基于apache开源项目commons-configuration,附件是该工具类完整代码,仅供...
以下是一个关于如何构建和使用配置文件读取工具类的详细说明。 1. **配置文件格式** 配置文件通常使用如INI、XML或JSON等易于解析的格式。在Java中,最常见的是使用.properties文件,因为它们简洁且易于处理。例如...
下面是一个简化的配置文件读取示例,它假设配置文件包含键值对,用等号分隔: ```cpp #include #include #include int main() { std::ifstream configFile("config.ini"); if (!configFile) { std::cerr !" ...
对于配置文件读取,封装意味着创建一个类,它负责打开文件、逐行读取、解析逗号分隔的值,并可能提供方法来获取或设置配置项。 6. **具体实现**:在`QueueTextFile`类中,可能会有一个构造函数接收文件路径作为参数...
JAR文件本质上是一个ZIP格式的压缩文件,包含了一个或多个类文件、资源文件、配置文件等。每个JAR文件有一个`META-INF`目录,其中包含`MANIFEST.MF`文件,这个文件存储了关于JAR的元信息,如主类、版本号等。此外,...
我上传的这个JAVA工具主要是用来读取配置文件。
压缩包中的"C#配置文件助手"可能包含了一个简单项目,演示了如何创建一个读取和写入配置文件的C#控制台应用。源代码可能包括以下几个关键部分: - `Program.cs`: 包含主方法,用于调用读写功能。 - `ConfigHelper...
`ResourceBundle`是Java提供的一种国际化的资源管理工具,也可以用来读取配置文件。它支持多种语言环境,适合处理多语言配置。不过,它默认只支持.properties格式: ```java ResourceBundle bundle = ...
本篇文章将详细探讨如何通过Python来读取并解析`.properties`配置文件。 首先,了解`.properties`文件的格式。这种文件通常用于存储配置信息,其中键值对以等号`=`分隔,每一行代表一个键值对,注释以`#`或`!`开始...
例如,我们可以创建一个QSettings对象,指定配置文件的路径: ```cpp int main(int argc, char *argv[]) { QApplication a(argc, argv); QSettings settings("test.ini", QSettings::IniFormat); // 创建...
本篇将详细介绍一个名为"C++读取配置文件工具"的实用程序,它可以帮助开发者快速、高效地处理配置文件,节约宝贵的开发时间。 这个工具的核心功能在于提供了一种简洁的方式来读取常见的配置文件格式,如INI、XML或...
当我们的应用程序被打包成JAR文件后,有时我们需要从JAR内部读取配置文件,例如application.properties或application.yml。本文将深入探讨如何在Spring框架中实现这一功能。 首先,理解Spring的资源配置。Spring...
Java INI配置文件读取是Java开发中常见的一项任务,主要涉及到对INI格式配置文件的解析、读取、以及可能的修改操作。INI文件是一种简单的文本格式,常用于存储应用程序的配置参数,其结构通常由多个节(Section)...
这篇博客“spring mvc 读取配置文件”将深入探讨如何在Spring MVC中读取和使用配置文件,以及相关工具的应用。 首先,Spring MVC中的配置文件通常是指XML配置文件,如`applicationContext.xml`或`servlet-context....
### C# .NET读取INI配置文件的知识点详解 #### 一、概述 在软件开发过程中,经常会遇到需要根据不同的环境或用户需求调整程序配置的情况。例如,更改数据库连接字符串、FTP登录凭证等。传统的做法是在代码中硬编码...
在web项目中读取yml配置文件的工具类.可以实现将 server : port : portnumber : 8081 转换为 key为"server.port.portnumber",值为"8081"的Map,String>集合
本文将深入讲解如何在Idea中读取YML配置文件,特别是针对刚接触Gradle的开发者。 首先,我们需要了解YML配置文件的结构。YAML文件以键值对的形式存储数据,使用缩进来表示层级关系。例如: ```yaml server: port:...
单例模式常用于管理共享资源,如配置文件的读取。本篇将详细介绍如何利用枚举(enum)来实现单例模式,并结合`Properties`类解析配置文件。 首先,我们来看一下传统的单例模式实现方式,如懒汉式和饿汉式,但这些...
在Linux系统中,读取配置文件是日常管理任务的一部分,特别是在使用像MySQL这样的数据库服务时。配置文件通常存储了服务的参数和设置,以便于管理和调整。本篇将详细讲解如何在Linux环境下处理类似“标题”中提到的...