在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. github开源项目

    开源一小步,前端一大步   作为一名前端攻城狮,相信不少人已经养成了这样的习惯.当你进入一个网站,总会忍不住要打开控制台看下它是如何布局的,动画是如何实现的等.这也是前端开发者一个不错的的学习途径. ...

  2. HashTable类模板_C++

    好久没看数据结构了,今天终于要用到hash,整理一下写了个hash类模板 template<typename T> class DataType { public: T key; Data ...

  3. haskell学习笔记<1>--基本语法

    七月记录:整个七月就在玩,参加夏令营,去遨游.... 八月份需要开始复习,正等书的这个过程突然想起一直没有完成的学习-haskell,所以当前的目标是用haskell制作一个局域网通信的小工具,要求: ...

  4. javascript 闭包基础分享

    javascript 闭包基础分享 闭包向来给包括JavaScript程序员在内的程序员以神秘,高深的感觉,事实上,闭包的概念在函数式编程语言中算不上是难以理解的知识.如果对作用域,函数为独立的对象这 ...

  5. javaSocket与C通信

    前段时间写了个web端与C服务端之间的通信不过用的是短连接 非堵塞的方式,一直想使用长连接,使tomcat启动的时候就和C服务端进行通信,但是一直没找到方法希望je的朋友能给点思路.先来看我现在的具体 ...

  6. 设计模式:Prototype 原型模式 - 同学你抄过别人的作业么?-clone()方法的使用

    原型模式: 通过某个类的实例来创建对象 使用原型模式的好处: 好处是什么呢?当我们需要多次重复的创建一个类的示例的时候,我们可以使用new但是,new不仅仅耗费内存而且,如果new 某个类的构造方法中 ...

  7. php的curl封装类

    之前一直做爬虫相关的,每次自己去写一系列curl_setopt()函数太繁琐,我于是封装了如下curl请求类. <?php /** * @author freephp * @date 2015- ...

  8. “Will not add file alias 'samefile' ('SameFile' already exists in index)” when `git add/commit` operation

    从远程仓库pull下来的代码有两个类类名首字母小写出现如下情况 然后我想删了重新写一下(就是把这个类删了,代码复制到名字正确的类里面),然后commit的时候出现这个错误,后来删一个commit一下, ...

  9. mysql数据库 触发器简单实例

    触发器(trigger):监视某种情况,并触发某种操作. 触发器创建语法四要素:1.监视地点(table) 2.监视事件(insert/update/delete) 3.触发时间(after/befo ...

  10. Jquery源码分析与简单模拟实现

    前言 最近学习了一下jQuery源码,顺便总结一下,版本:v2.0.3 主要是通过简单模拟实现jQuery的封装/调用.选择器.类级别扩展等.加深对js/Jquery的理解. 正文 先来说问题: 1. ...