Java Properties文件读写设计

凡是中文乱码问题,都是字符读写的编码格式不统一的问题。
一般情况下,便于统一字符编码格式,所有文件读写格式均设为utf-8模式,这些地方包括数据库字符存储格式,源代码文件编码格式,资源文件编码格式,前端页面编码格式,网络IO流字符编码格式等。
鉴于以上前提,本文着重关心的是properties资源文件的读写。下面所展示的封装类功能包括:
(1)读取资源文件中的值(处理了同一个资源文件中资源值相互引用的问题)
(2)写资源文件
(3)处理了properties文件中中文字符读取乱码问题。
关于问题(1),例如对于具有以下内容的properties文件:在test1的值中通过自定义的语法${key}来引用同一文件中的其他键值。在处理过程中,先读取字符串test1的值,再通过正则表达式匹配出key值,再按key值读取test的值,并拼凑到test1中,从而得到最终的test1的值。

test=test
test1=${test}

关于问题2,重点在于如果便捷地根据文件名获取到文件输入流,采用的方式是通过类ClassLoader根据编译后相对于classpath的路径名,获取到文件的URL,再转化为URI,由于File函数的构造函数中,提供了以文件URI为输入参数的构造器,所以便可以直接通过这种方式获得File对象,进而获得对应资源文件的输入流。
需要指出的是,在以下两种获得文件URL的方式中,区别仅在于是否通过ClassLoader,其中方式1适用于任何Java项目环境下;而方式2则仅适用于Java Application,而在Java Web应用环境下,获取不到文件URL值。

//方式1
URL url = PropsUtil.class.getClassLoader().getResource("setting/token.properties");
//方式2
URL url = PropsUtil.class..getResource("setting/token.properties");

对于问题3,方便起见,首先需将对应properties文件设置为utf-8编码格式(在IDEA环境下,由file->setting->editor->file encodings设置),否则以unicode编码的话,不仅不便于文档的统一,而且里面的中文字符会自动转成Unicode格式,极其不直观。
通常获得Properties对象的方式是,通过文件ClassLoader(方式1)获得文件输入流,在调用properties.load(imputstream)的方式完成初始化,然而这种方式下,由于不能够指定读取资源文件时的字符编码格式,在读取中文字符时便会出现乱码。
所以,更好的做法是,将该inputstream作为构造参数包装成Reader类,并在构造器的另一个参数中指明采用utf-8的方式,再通过properties.load(reader),完成初始化,便可解决中文字符读取乱码问题。
类源码如下:

/**
 * Created by Song on 2016/11/2.
 * mail:[email protected]
 * @since v0.0
 */
public final class PropsUtil {
    private static final Pattern PATTERN = Pattern.compile("\\$\\{([^\\}]+)\\}");

    /**
     * 加载资源文件
     * @param fileName 资源文件名
     * @return
     */
    public static Properties loadProps(String fileName){
        Properties pros = null;
        Reader reader = null;
        try{
            reader = new InputStreamReader(Thread.currentThread().getContextClassLoader().getResourceAsStream(fileName),"utf-8");
            if(null == reader){
                throw new FileNotFoundException(fileName+" file is not found");
            }
            pros = new Properties();
            pros.load(reader);
        }catch (IOException e){
            System.err.println("load peoperties file failed");
            e.printStackTrace();
        }finally {
            if(null != reader){
                try {
                    reader.close();
                }catch (IOException e){
                    System.err.println("close input stream failed");
                    e.printStackTrace();
                }
            }
        }
        return pros;
    }

    /**
     * 获取资源文件值
     * @param key 键名
     * @param prop 资源文件句柄
     * @return
     */
    public static String getProperty(String key,Properties prop) {
        String value = prop.getProperty(key);
        Matcher matcher = PATTERN.matcher(value);
        StringBuffer buffer = new StringBuffer();
        while (matcher.find()) {
            String matcherKey = matcher.group(1);
            String matchervalue = prop.getProperty(matcherKey);
            if (matchervalue != null) {
                matcher.appendReplacement(buffer, matchervalue);
            }
        }
        matcher.appendTail(buffer);
        return buffer.toString();
    }

    /**
     * 写资源文件
     * 问题很奇怪,重新加载资源文件并读键值,可得到最新的值,然而直接打开文件,却读不到新值
     * @param key
     * @param value
     * @param fileName
     * @return
     * @throws Exception
     */
    public static boolean setProperty(String key,String value,String fileName) throws Exception{
        URL url = PropsUtil.class.getClassLoader().getResource("setting/token.properties");
        Properties properties = new Properties();
        properties.setProperty(key, value);
        properties.store(new FileOutputStream(new File(url.toURI())),"");
        return true;
    }
}

猜你喜欢

转载自blog.csdn.net/u013248535/article/details/53164488