在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. Leapin' Lizards

    Leapin' Lizards 题目大意: 在一个网格地图中有一些高度不同的石柱,一些石柱上站着一些蜥蜴,你的任务是让尽量多的蜥蜴逃到边界外. 每行每列中相邻石柱的距离为1,蜥蜴的跳跃距离是d,即蜥蜴 ...

  2. javascript拾遗

    javascript中,只有null和undefined不能拥有方法,其他任何类型都可以在其上定义方法:字符串既然不是对象,怎么会有属性呢?只有引用了字符串的属性,那么javascript就会将字符串 ...

  3. Changing the working directory of VIM

    Sometimes we want to open another file in the same folder with current editing file, what we can do ...

  4. jquery选择器之内容过滤选择器

    先写出DOM元素的HTML结构: <style type="text/css"> /*高亮显示*/ .highlight{ background-color: gray ...

  5. 如何安装ArchLinux

    如何安装ArchLinux   本文基于ArchLinux(https://www.archlinux.org/)Current Release: 2013.08.01的ISO写的安装教程! ISO下 ...

  6. TOGAF架构内容框架之架构制品(下)

    TOGAF架构内容框架之架构制品(下) 4.2.31 数据生命周期图(Data Lifecycle Diagram) 数据生命周期图是在业务流程的约束之下对业务数据在其整个生命周期(从概念阶段到最终退 ...

  7. .NET依托CLR进行的内存的管理

    看了http://www.cnblogs.com/liulun/p/3145351.html  不错,补习下相关技术.. 正文: .NET依托CLR进行的内存的管理 有了CLR 基本不需要担心.net ...

  8. vim 多行同时输入,且输入数值递增

    很有用的命令. 很给力的说. http://vim.wikia.com/wiki/Making_a_list_of_numbers 我在 html中需要增加新的标签的时候,就有用到过. 原来的html ...

  9. TCMalloc小记

    周末抽空看了一下tcmalloc,了解了个大概.下面记录一下. 一. 原理 tcmalloc就是一个内存分配器,管理堆内存,主要影响malloc和free,用于降低频繁分配.释放内存造成的性能损耗,并 ...

  10. Android ListView多布局讲解

    Listview优化是一个老生常谈的事情了,其优化的方面也有很多种,例如,布局重用.在getView()中减少逻辑计算.减少在页面滑动的时候加在图片,而是在页面停止滚动的时候再加在图片.而今天要介绍的 ...