在Java早期的开发中,常用*.properties文件存储一些配置信息。其文件中的信息主要是以key=value的方式进行存储,在早期受到广泛的应用。而后随着xml使用的广泛,其位置渐渐被取代,不过,目前仍有一些框架如log4J在使用它。最近在弄自己的小玩意儿的时候也用到了它,顺便加深了一下了解,在此分享。

Java在对*.properties文件进行操作的时候,实际上是通过IO对文档进行逐行的扫描,然后将文中非注释的部分存放在一个properties对象中。Properties 实际上是继承了hashtable,实现了Map接口。可以这样理解,它是进行了进一步封装的HashMap。存放到properties中后,可以对properties进行一系列的操作,此时的数据保存在内存中。最后,当需要保存数据的时候,是将properties中所有的键值重新写入到文件中去。 对properties文件的操作,jdk提供了一系列的API。一下是一个工具类,实现了对properties文件的增删查改的功能。

 package com.sean.file.properties;

 import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
/**
* Java 操作Properties的工具类
* 实现功能:
* 1、Properties文件的增删查改功能
* 2、解决读写中文乱码问题
* @author Sean
*
*/
public class PropertiesUtil { /**
* Properties地址值,不需要加根标记"/"
*/
private String src = "";
private InputStreamReader inputStream = null;
private OutputStreamWriter outputStream = null;
private String encode="utf-8";
public Properties properties ; /**
* 默认构造函数
*/
public PropertiesUtil() {
} /**
* 构造函数
*
* @param src 传入Properties地址值,不需要加根标记"/"
*/
public PropertiesUtil(String src) {
this.src = src;
} /**
* 构造函数,提供设置编码模式
* @param src 传入Properties地址值,不需要加根标记"/"
* @param encode 传入对应的编码模式,默认是utf-8
*/
public PropertiesUtil(String src, String encode) {
this(src);
this.encode = encode;
} /**
* 加载properties文件
* @author Sean
* @date 2015-6-5
* @return 返回读取到的properties对象
*/
public Properties load(){
if(src.trim().equals("")){
throw new RuntimeException("The path of Properties File is need");
}
try {
inputStream=new InputStreamReader(ClassLoader.getSystemResourceAsStream(src),encode);
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
}
properties=new Properties();
try {
properties.load(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
return properties;
} /**
* 将配置写入到文件
* @author Sean
* @date 2015-6-5
* @throws Exception
*/
public void write2File() throws Exception{
//获取文件输出流
outputStream=new OutputStreamWriter(new FileOutputStream(new File(ClassLoader.getSystemResource(src).toURI())),encode);
properties.store(outputStream, null);
close();
} /**
* 通过关键字获取值
* @author Sean
* @date 2015-6-5
* @param key 需要获取的关键字
* @return 返回对应的字符串,如果无,返回null
*/
public String getValueByKey(String key){
properties=load();
String val =properties.getProperty(key.trim());
close();
return val; } /**
* 通过关键字获取值
* @author Sean
* @date 2015-6-5
* @param key 需要获取的关键字
* @param defaultValue 若找不到对应的关键字时返回的值
* @return 返回找到的字符串
*/
public String getValueByKey(String key ,String defaultValue){
properties=load();
String val =properties.getProperty(key.trim(),defaultValue.trim());
close();
return val;
} /**
* 关闭输入输出流
* @author Sean
* @date 2015-6-5
*/
public void close(){
try {
if(inputStream!=null){inputStream.close();}
if(outputStream!=null){outputStream.close();}
} catch (IOException e) {
e.printStackTrace();
}
} /**
* 获取Properties所有的值
* @author Sean
* @date 2015-6-5
* @return 返回Properties的键值对
*/
public Map<String,String> getAllProperties(){
properties=load();
Map<String,String> map=new HashMap<String,String>();
//获取所有的键值
Enumeration enumeration=properties.propertyNames();
while(enumeration.hasMoreElements()){
String key=(String) enumeration.nextElement();
String value=getValueByKey(key);
map.put(key, value);
}
close();
return map;
} /**
* 往Properties写入新的键值
* @author Sean
* @date 2015-6-5
* @param key 对应的键
* @param value 对应的值
*/
public void addProperties(String key,String value){
properties=load();
properties.put(key, value);
try {
write2File();
} catch (Exception e) {
e.printStackTrace();
}
} /**
* 添加Map中所有的值
* @author Sean
* @date 2015-6-5
* @param map 对应的键值对集合
*/
public void addAllProperties(Map<String,String> map){
properties=load();
properties.putAll(map);
try {
write2File();
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("write fail");
}
} /**
* 更新配置文件
* @author Sean
* 2015-6-5
* @param key 需要更新的键值
* @param value 对应的值
*/
public void update(String key,String value){
properties=load();
if(!properties.containsKey(key)){
throw new RuntimeException("not such key");
}
properties.setProperty(key, value);
try {
write2File();
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("write fail");
}
} /**
* 删除某一键值对
* @author Sean
* 2015-6-5
* @param key 对应的键值
*/
public void deleteKey(String key){
properties=load();
if(!properties.containsKey(key)){
throw new RuntimeException("not such key");
}
properties.remove(key);
try {
write2File();
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("write fail");
}
} /**
* 设置path值
* @author Sean
* @date 2015-6-5
* @param src 对应文件值
*/
public void setSrc(String src) {
this.src = src;
}
}

基本上,常用的对properties的操作采用这个工具类都能完成。值得注意的是,因为程序在对properties进行扫描的时候,忽略了注释的内容,而当重新写内容入文字的时候,程序也只会将properties中的值写入,这样会注释丢失的情况。这种情况,网上有人的解决方案是自己新建一个继承了properties的类,然后将程序读取到的信息包括注释放入到LinkedHashMap中,这样就可以保存注释了。

不过,同样的功能,通过Apache 上的开源项目commons-configuration也能实现。commons-configuration 主要是实现对如xml, properties等配置文件操作的API。通过它,同样能实现对properties的操作,同时,在操作的时候,也可以保存文件中的注释。

在使用commons-configuration进行properties的文件操作的时候,不仅需要导入commons-configuration.jar 包,还需要导入另外几个依赖包才能实现。

以下是本能采用commons-configuration提供的api进行properties操作的一个Demo

package com.sean;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.URISyntaxException; import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration; public class PropertiesUtil {
private String src="";
private PropertiesConfiguration pcf=null;
private String encode="utf-8";
/**
* 默认构造函数
*/
public PropertiesUtil(){};
/**
* 传参构造函数
* @param src 传入对应文件地址
*/
public PropertiesUtil(String src){
this.src=src;
try {
pcf=new PropertiesConfiguration(src);
} catch (ConfigurationException e) {
e.printStackTrace();
}
pcf.setEncoding(encode);
} /**
* 获取特定key的值
* @param key 对应的键值
* @return 返回对应value值,找不到返回null;
*/
public String getValue(String key){
String s=pcf.getString(key);
return s;
}
/**
* 更新对应的值
* @param key 对应的关键字
* @param value 对应的值
*/
public void updateValue(String key,String value) {
if(!pcf.containsKey(key)){
throw new RuntimeException("not such key");
}
try {
pcf.save(new FileOutputStream(new File(ClassLoader.getSystemResource(src).toURI())),"utf-8");
} catch (ConfigurationException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (URISyntaxException e) {
e.printStackTrace();
}
} /**
* 添加键值对
* @param key 关键字
* @param value 值
*/
public void addValue(String key,String value){
pcf.addProperty(key, value);
try {
pcf.save(new FileOutputStream(new File(ClassLoader.getSystemResource(src).toURI())),"utf-8");
} catch (ConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (URISyntaxException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 删除关键字
* @param key 关键字
*/
public void delValue(String key){
pcf.clearProperty(key);
try {
pcf.save(new FileOutputStream(new File(ClassLoader.getSystemResource(src).toURI())),"utf-8");
} catch (ConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (URISyntaxException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} }

可以看出,commons-configuration提供的api操作起来简单多了。可是,因为commons-configuration是国外的开源项目,所以其对中文的支持存在一些问题。尽管API中提供了设置字符编码的功能,但是还是没有能够非常好的解决中文的问题。相对而言,原生的API实现起来比较的简单。

最后做下总结,关于对properties 的操作,jdk和commons-configuration都提供了较好的支持,关于使用原生还是框架,应该根据具体条件而定。不过我们在不重复造轮的情况下,还是应该保持对原理的探讨

关于Java配置文件properties的学习的更多相关文章

  1. Java配置文件Properties的读取、写入与更新操作

    /** * 实现对Java配置文件Properties的读取.写入与更新操作 */ package test; import java.io.BufferedInputStream; import j ...

  2. 对Java配置文件Properties的读取、写入与更新操作

    http://breezylee.iteye.com/blog/1340868 对Java配置文件Properties的读取.写入与更新操作 博客分类: javase properties  对Jav ...

  3. 实现对Java配置文件Properties的读取、写入与更新操作

    /** * 实现对Java配置文件Properties的读取.写入与更新操作 */ package test; import java.io.BufferedInputStream; import j ...

  4. java.util.Properties类 学习笔记

    学习目标:   1.认识properties文件,理解其含义,会正确创建properties文件. 2.会使用java.util.Properties类来操作properties文件. 3.掌握相对路 ...

  5. java配置文件properties,yml,一般文件

    JAVA编写配置文件的几种方式: JAVA配置文件,一般都放在resource目录下,无论是下面提到的properties.yml还是普通的txt等文件. 在打成jar包之后,只需要jar包程序就可运 ...

  6. 读取java配置文件properties

    java项目里很多参数都是写在配置文件properties上,如果需要读取的话,可以使用jdk里提供的Properties类进行处理. 具体写法如下: public class PropertiesC ...

  7. java 读写properties

    网速不好:先贴上资料: Java配置文件Properties的读取.写入与更新操作 [Spring] - Property注入 http://www.360doc.com/content/14/073 ...

  8. freemarker遍历java.util.Properties

    java.util.Properties类 学习笔记 http://trans.blog.51cto.com/503170/110227/ FreeMarker代码 <#list systemP ...

  9. java读取properties配置文件总结

    java读取properties配置文件总结 在日常项目开发和学习中,我们不免会经常用到.propeties配置文件,例如数据库c3p0连接池的配置等.而我们经常读取配置文件的方法有以下两种: (1) ...

随机推荐

  1. IOS使用不同父类的 view 进行约束

    最终效果图如下: 很多限制条件都已经应用到了视图中,我们在解释一下: ·在我们的视图控制器的主视图中有两个灰色的视图.两个视图距视图控制器的视图左 边和右边都有一个标准的空白距离.视图的顶部距顶部的视 ...

  2. 探讨 : Host在IIS上的WCF Service的执行方式

    一个WCF请求由两个线程来完成 运行在IIS上的WCF service, 你可能会注意到一个比较有趣的现象. 当WCF service接收到一个请求时, 这个请求实际上会有两个线程在执行这个请求. 一 ...

  3. linux下面配置安装nodejs+npm

    linux下 多亏这一篇文章= =我就卡死在文章所说的这个点里 附大牛链接:http://blog.sitearth.com/nodejs%E4%B8%8A%E4%BD%BF%E7%94%A8mong ...

  4. CSS案例

    1.美团网效果 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> ...

  5. SSH使用技巧

    SSH使用技巧 SSH免输入密码 原理是依赖证书去认证,从而免除密码输入. 通过ssh-keygen生成一对公私钥,是否使用passphrase可以根据个人喜好.(其实使用证书就是为了方便而已,我是不 ...

  6. Python -- machine learning, neural network -- PyBrain 机器学习 神经网络

    I am using pybrain on my Linuxmint 13 x86_64 PC. As what it is described: PyBrain is a modular Machi ...

  7. Deploying OpenFire for IM (instant message) service (TCP/IP service) with database MySQL , client Spark on linux部署OpenFire IM 消息中间件服务

    Are you a hacker? How to build another QQ/Wechat/whatsapp/skype/imessage? Let's go through this!!!! ...

  8. ERROR 1130: Host xxx is not allowed to connect to this MySQL server

    在使用MySQL-Front连接mysql的时候发生的这个错误 ERROR 1130: Host xxx is not allowed to connect to this MySQL server ...

  9. 用友CDM系统“货位间商品移库单(一步)”表体增加“货位可用数量”字段,根据表头的选择的货位自动带出数值

    系统控制台——业务单据定制——货位间商品移库单(一步) 明细字段——增加“可销数量”字段. 然后修改明细字段的“商品编号”自定义查询方案. 增加自定义资料检索方案hwyksp SQL: select ...

  10. 在android里用ExpandableListView实现二层和三层列表

    转载自http://www.cnblogs.com/nuliniaoboke/archive/2012/11/13/2767957.html 二层列表是直接用androidAPI中的Expandabl ...