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

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

解决方案

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

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

  1. import java.util.Collections;
  2. import java.util.Enumeration;
  3. import java.util.LinkedHashSet;
  4. import java.util.Properties;
  5. import java.util.Set;
  6.  
  7. /**
  8. * OrderedProperties
  9. * @author hanwl
  10. * @date 2018-11-13
  11. * @userd 使得Properties有序
  12. */
  13. public class OrderedProperties extends Properties {
  14.  
  15. private static final long serialVersionUID = 4710927773256743817L;
  16.  
  17. private final LinkedHashSet<Object> keys = new LinkedHashSet<Object>();
  18.  
  19. @Override
  20. public Enumeration<Object> keys() {
  21. return Collections.<Object> enumeration(keys);
  22. }
  23.  
  24. @Override
  25. public Object put(Object key, Object value) {
  26. keys.add(key);
  27. return super.put(key, value);
  28. }
  29.  
  30. @Override
  31. public Set<Object> keySet() {
  32. return keys;
  33. }
  34.  
  35. @Override
  36. public Set<String> stringPropertyNames() {
  37. Set<String> set = new LinkedHashSet<String>();
  38.  
  39. for (Object key : this.keys) {
  40. set.add((String) key);
  41. }
  42.  
  43. return set;
  44. }
  45. }

调用方法:

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

 

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. Camera Binning Mode

    Camera Binning Mode:像素合并模式,将相邻的像素单元电荷通过物理的方法叠加在一起作为一个像素输出信号: 水平方向Binning:  同列相邻行的电荷叠加 垂直方向Binning:   ...

  2. Spring注解定时器使用

    一.首先要配置我们的spring-service.xml 1.xmlns 多加下面的内容 xmlns:task="http://www.springframework.org/schema/ ...

  3. 文本分类实战(九)—— ELMO 预训练模型

    1 大纲概述 文本分类这个系列将会有十篇左右,包括基于word2vec预训练的文本分类,与及基于最新的预训练模型(ELMo,BERT等)的文本分类.总共有以下系列: word2vec预训练词向量 te ...

  4. Django-CRM项目学习(一)-admin组件

    开始今日份整理 1.admin组件使用 1.1 创建django项目以及开启APP01 略 1.2 创建类 使用django自带的sqlite3的小型文件型的数据库 注:使用sqlite3类型的数据库 ...

  5. 8-过滤器Filter和监听器Listener

    一.web监听器:监听特殊事件的发生1.监听实现步骤 a.写一个java类,实现特定的接口,重写相关方法 b.在web.xml中,牌配置 <listener> <listener-c ...

  6. ELK的安装

    首先得安装好Elasticsearch.Kibana和Logstash(这里全部使用rpm安装的是6.4.2版本,而且都是单机安装,暂时没有考虑分布式安装.) 服务器内存要求至少为4G,下图为运行起来 ...

  7. localStorage sessionStorage 增强版

    1. 保留了localStorage sessionStorage的(setItem getItem removeItem clear key)api,使用上几乎差不多 2. 增强了setItem方法 ...

  8. Linux内存管理 (16)内存规整

    专题:Linux内存管理专题 关键词:内存规整.页面迁移.pageblock.MIGRATE_TYPES. 内存碎片的产生:伙伴系统以页为单位进行管理,经过大量申请释放,造成大量离散且不连续的页面.这 ...

  9. Python—kmeans算法学习笔记

    一.   什么是聚类 聚类简单的说就是要把一个文档集合根据文档的相似性把文档分成若干类,但是究竟分成多少类,这个要取决于文档集合里文档自身的性质.下面这个图就是一个简单的例子,我们可以把不同的文档聚合 ...

  10. RuntimeError: An attempt has been made to start a new process before the current process has finished its bootstrapping phase. This probably means that you are not using fork to start your c

    Error Msg: Traceback (most recent call last): File "<string>", line 1, in <module ...