前几天,公司项目中有一个需求是读取配置文件的,而且最好能够保证加载到内存中的顺序能够和配置文件中的顺序一致,但是,如果使用 jdk 中提供的 Properties 类的话,读取配置文件后,加载到内存中的顺序是随机的,不能保证和原文件的顺序一致,因此,jdk 提供的 Properties 是不行的。

由于有这样的需求,而 Java 的 Properties 类又不能实现,因此只能想别的办法。我曾经想过,在把配置文件加载到内存后,对其进行排序,但这个方案会有很多限制,而且也有问题。配置文件中的信息会有很多,如果对其进行再排序的话,首先会影响系统的性能,其次,对程序的执行效率来讲,也会有一定的影响。最后,经过一番查证之后,同事找到了一篇类似的文章。

解决方案

从文章中了解到,Java 的 Properties 加载属性文件后是无法保证输出的顺序与文件中一致的,因为 Properties 是继承自 Hashtable 的, key/value 都是直接存在 Hashtable 中的,而 Hashtable 是不保证进出顺序的。

文章中已经给提供了代码,思路是继承自 Properties,覆盖原来的 put/keys,keySet,stringPropertyNames 即可,其中用一个 LinkedHashSet 来保存它的所有 key。完整代码如下:

import java.util.Collections;
import java.util.Enumeration;
import java.util.LinkedHashSet;
import java.util.Properties;
import java.util.Set; /**
* OrderedProperties
* @author hanwl
* @date 2018-11-13
* @userd 使得Properties有序
*/
public class OrderedProperties extends Properties { private static final long serialVersionUID = 4710927773256743817L; private final LinkedHashSet<Object> keys = new LinkedHashSet<Object>(); @Override
public Enumeration<Object> keys() {
return Collections.<Object> enumeration(keys);
} @Override
public Object put(Object key, Object value) {
keys.add(key);
return super.put(key, value);
} @Override
public Set<Object> keySet() {
return keys;
} @Override
public Set<String> stringPropertyNames() {
Set<String> set = new LinkedHashSet<String>(); for (Object key : this.keys) {
set.add((String) key);
} return set;
}
}

调用方法:

public class demo {
Properties prop = new OrderedProperties();
File appDir = GlobalVars.getLocalAppDataDir();
File dir = new File(appDir, "userHistory/");
if (!dir.exists()) {
dir.mkdirs();
}
try {
OutputStreamWriter oStreamWriter = new OutputStreamWriter(new FileOutputStream(dir+"\\user.properties",true), "utf-8");
//FileOutputStream fileOutputstream = new FileOutputStream(dir+"\\user.properties", false);
prop.setProperty("serverUrl", serverUrlTextField.getText());
prop.setProperty("userName", userNameTextField.getText());
prop.setProperty("password", passwordField.getText());
prop.store(oStreamWriter, null);
oStreamWriter.close(); } catch (Exception e) {
e.printStackTrace();
} Properties prop = new OrderedProperties();
File appDir = GlobalVars.getLocalAppDataDir();
File dir = new File(appDir, "userHistory/");
if(new File(dir+"\\user.properties").exists()){
try {
InputStreamReader iStreamReader = new InputStreamReader(new FileInputStream(dir+"\\user.properties"),"utf-8");
prop.load(iStreamReader);
Iterator<String> it = prop.stringPropertyNames().iterator();
while (it.hasNext()) {
String key = it.next();
String value = prop.getProperty(key);
System.out.println(key+":"+value);
}
iStreamReader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
    /**
* 返回程序本地数据存储目录
* C:\Users\Administrator\AppData\Local\Founder\PublisherClient
* C:\Users\Administrator\AppData\Local\Founder\PrinterClient
* C:\Users\Administrator\AppData\Local\Founder\TypeSettingClient
* @return
*/
public static File getLocalAppDataDir() {
String appDataPath;
if (Util.isMac()) {
appDataPath = System.getProperty("user.home") + "/Library/";
}
else if (NativeUtil.libraryLoaded()) {
appDataPath = NativeUtil.getLocalAppDataFolder();
}
else {
appDataPath = System.getProperty("user.home");
} File founderDir = new File(appDataPath, Util.isWindows() || Util.isMac() ? "Founder" : ".Founder");
File appDir = new File(founderDir, CLIENT_TYPE.getClientName());
appDir.mkdirs(); return appDir;
}
结束
 
  这种特定的需求,以前倒是没怎么接触过,不给通过这次的经历,发现了一点,自己的积累还是很少,不多说了,继续努力吧。
 
参考:

 

Java Properties 类读配置文件保持顺序的更多相关文章

  1. java properties类读取配置文件

    1.JAVA Properties类,在java.util包里,具体类是java.util.properties.Properties类继承自Hashtable类并且实现了Map接口,也是使用一种键值 ...

  2. java工具类-读配置文件

    ///读配置文件 import java.io.InputStream;import java.util.HashMap;import java.util.Map;import java.util.M ...

  3. Java 数据类型:集合接口Map:HashTable;HashMap;IdentityHashMap;LinkedHashMap;Properties类读取配置文件;SortedMap接口和TreeMap实现类:【线程安全的ConcurrentHashMap】

    Map集合java.util.Map Map用于保存具有映射关系的数据,因此Map集合里保存着两个值,一个是用于保存Map里的key,另外一组值用于保存Map里的value.key和value都可以是 ...

  4. 基于Java Properties类设置本地配置文件

    一.Java Properties类介绍 Java中有个比较重要的类Properties(Java.util.Properties),主要用于读取Java的配置文件,各种语言都有自己所支持的配置文件, ...

  5. 读配置文件能够保持顺序的 Java Properties 类

    序 前几天,公司项目中有一个需求是读取配置文件的.并且最好可以保证载入到内存中的顺序可以和配置文件里的顺序一致,可是.假设使用 jdk 中提供的 Properties 类的话,读取配置文件后.载入到内 ...

  6. 使用java.util.Properties类读写配置文件

    J2SE 1.5 以前的版本要求直接使用 XML 解析器来装载配置文件并存储设置,虽说也并非难事,相比 java.util.Properties却要做额外的解析工作.而java.util.Proper ...

  7. day1 java基础回顾- Properties类与配置文件

    Properties配置文件说明 Properties类对应.properties文件.文件内容是键值对,键值对之间使用"="或空格隔开.开头是"#"的表示注释 ...

  8. 【JAVA Properties类概述】

    一.概述. 之前说过,该对象是和IO流相结合的技术,所以和IO流结合在一起来讲比较合适. public class Propertiesextends Hashtable<Object,Obje ...

  9. Java Properties类源码分析

    一.Properties类介绍 java.util.Properties继承自java.util.Hashtable,从jdk1.1版本开始,Properties的实现基本上就没有什么大的变动.从ht ...

随机推荐

  1. js 学习之路6: if...else...条件语句的使用

    1.1 if (...) { ... } else { ... } <!DOCTYPE html> <html> <meta http-equiv="Conte ...

  2. VMware14虚拟机下安装Centos6.5

    一.下载VMware14,CentOS6.5光盘映像文件. https://pan.baidu.com/s/1WaTBnYuNC5dLYM_Ra2bjBQ 二.安装过程 1.打开VMware虚拟机 — ...

  3. 面向对象_item项目

    详细见老师博客:http://www.cnblogs.com/Eva-J/articles/7351812.html#_label9 __getitem__\__setitem__\__delitem ...

  4. PHP程序员从小白到高手,掌握这些技能少走弯路

    PHP程序员从小白到高手,掌握这些技能少走弯路 PHP究竟是不是最好的语言,一直以来是程序员最大的“争议”,但毋庸置疑的是,PHP绝对是最有前途和力量的变成语言,也是你入门最值得学习的语言. 作为老牌 ...

  5. ubuntu系统下mysql重置密码和修改密码操作

    一.忘记密码后想重置密码 在介绍修改密码之前,先介绍一个文件/etc/mysql/debian.cnf.其主要内容如下图: 里面有一个debian-sys-maint用户,这个用户只有Debian或U ...

  6. day22-多并发编程基础(三)

    今天学习了并发编程中的最后一部分,协程,也是python中区别于java,c等语言中很大不同的一部分 1.协程产生的背景 2.协程的概念 3.yield模拟协程 4.协程中主要的俩个模块 5.协程的应 ...

  7. CentOS 6.5 minimal 安装配置VMware tools

    1.登录到系统,切换到root账户 2.配置网络 minimal版本默认不启动网络,所以要自己配置. 配置过程很简单,编辑配置文件 vi /etc/sysconfig/network-script/i ...

  8. day22---面向对象基础初识

    面向过程编程: 核心是过程两个字,指的是解决问题的步骤,即先干什么再干什么,基于面向过程设计的程序就好比在设计一条流水线,是一种机械的思维方式. 优点:复杂问题流程化, 缺点:程序的可扩展性差 面向对 ...

  9. 使用Jasypt对SpringBoot配置文件加密(转)

    文章转自   https://www.jianshu.com/p/323ec96c46d2 引入jasypt <dependency> <groupId>com.github. ...

  10. 初学Python——协程

    进程.线程和协程区分 我们通常所说的协程Coroutine其实是corporate routine的缩写,直接翻译为协同的例程,一般我们都简称为协程. 在linux系统中,线程就是轻量级的进程,而我们 ...