Java代码实现对properties文件有序的读写的示例

最近遇到一项需求,要求把properties文件中的内容读取出来供用户修改,修改完后需要再重新保存到properties文件中。很简单的需求吧,可问题是Properties是继承自HashTable的,直接通过keySet()、keys()或entrySet()方法对Properties中的元素进行遍历时取出来的内容顺序与properties文件中的顺序不一致,这是问题一;问题二是就算取出来的时候是有序的,保存到文件中时又是无序的了。

当然,解决这两个问题的方法有很多。我最终采用的方法是自定义一个PropertiesUtil类,该类继承自Properties。PropertiesUtil提供一个返回由key按照存入顺序组成的List的方法,getKeyList(),这样问题一就解决了。那如何保证getKeyList()方法返回的就是有序的key组成的集合呢?我查看了一下Properties方法的源码,发现其setProperty()方法实际上就是调用了父类HashTable的put()方法,其次Properties在从文件中加载内容时是按照文件顺序进行读取,然后调用父类HashTable的put()方法进行储存。所以问题的解决办法就是PropertiesUtil持有一个私有的可以有序存储key的集合,然后重写父类的put()方法,在方法体中照常通过super.put()进行属性的存储,同时将key添加到存储key的集合中。

Properties提供有save()方法和store()方法可以将当前对象的内容存放到指定的输出流中,但它们的底层逻辑都是一样的。通过调用keys()方法获取一个Enumeration,然后对该Enumeration进行遍历,依次将对应的key和value写入到输出流中,所以要保证写入是有序的,就要保证遍历keys()返回的Enumeration时取出的元素key是有序的。所以解决方法是重写keys()方法,保证遍历返回的Enumeration时得到的key是有序的。

下面就示范怎么按顺序读properties文件,以及还得按原来的顺序写properties文件。

package com.lxk.propertyFileTest; 

import java.util.*; 

/**
 * Created by lxk on 2017/5/2
 */
public class OrderedProperties extends Properties {
  private static final long serialVersionUID = -4627607243846121965L; 

  /**
   * 因为LinkedHashSet有序,所以,key在调用put()的时候,存放到这里也就有序。
   */
  private final LinkedHashSet<Object> keys = new LinkedHashSet<>(); 

  @Override
  public Enumeration<Object> keys() {
    return Collections.enumeration(keys);
  } 

  /**
   * 在put的时候,只是把key有序的存到{@link OrderedProperties#keys}
   * 取值的时候,根据有序的keys,可以有序的取出所有value
   * 依然调用父类的put方法,也就是key value 键值对还是存在hashTable里.
   * 只是现在多了个存key的属性{@link OrderedProperties#keys}
   */
  @Override
  public Object put(Object key, Object value) {
    keys.add(key);
    return super.put(key, value);
  } 

  /**
   * 因为复写了这个方法,在(方式一)的时候,才输出有序。
   * {@link MainOrder#printProp}
   */
  @Override
  public Set<String> stringPropertyNames() {
    Set<String> set = new LinkedHashSet<>();
    for (Object key : this.keys) {
      set.add((String) key);
    }
    return set;
  } 

  /**
   * 因为复写了这个方法,在(方式二)的时候,才输出有序。
   * {@link MainOrder#printProp}
   */
  @Override
  public Set<Object> keySet() {
    return keys;
  } 

  //这个就不设置有序了,因为涉及到HashTable内部类:EntrySet,不好复写。
  //public LinkedHashSet<Map.Entry<Object, Object>> entrySet() {
  //  LinkedHashSet<Map.Entry<Object, Object>> entrySet = new LinkedHashSet<>();
  //  for (Object key : keys) {
  //
  //  }
  //  return entrySet;
  //} 

  /**
   * 因为复写了这个方法,在(方式四)的时候,才输出有序。
   * {@link MainOrder#printProp}
   */
  @Override
  public Enumeration<?> propertyNames() {
    return Collections.enumeration(keys);
  }
}

上面是继承Java自带的类,我们做的主要是实现有序,其他的还是原来的样子就行。

看下整个的类继承关系:如下图:

下面是main方法的类。

package com.lxk.propertyFileTest; 

import java.io.*;
import java.util.Enumeration;
import java.util.Map;
import java.util.Properties;
import java.util.Set; 

/**
 * 读写properties文件测试(带顺序的读和写)
 * <p>
 * Created by lxk on 2017/5/2
 */
public class MainOrder {
  public static void main(String[] args) {
    Properties prop = readOrderedPropertiesFile();
    printProp(prop);
    writeOrderedPropertiesFile(prop);
  } 

  /**
   * 输出properties的key和value
   */
  public static void printProp(Properties properties) {
    System.out.println("---------(方式一)------------");
    for (String key : properties.stringPropertyNames()) {
      System.out.println(key + "=" + properties.getProperty(key));
    } 

    System.out.println("---------(方式二)------------");
    Set<Object> keys = properties.keySet();//返回属性key的集合
    for (Object key : keys) {
      System.out.println(key.toString() + "=" + properties.get(key));
    } 

    System.out.println("---------(方式三)------------");
    Set<Map.Entry<Object, Object>> entrySet = properties.entrySet();//返回的属性键值对实体
    for (Map.Entry<Object, Object> entry : entrySet) {
      System.out.println(entry.getKey() + "=" + entry.getValue());
    } 

    System.out.println("---------(方式四)------------");
    Enumeration<?> e = properties.propertyNames();
    while (e.hasMoreElements()) {
      String key = (String) e.nextElement();
      String value = properties.getProperty(key);
      System.out.println(key + "=" + value);
    }
  } 

  /**
   * 读Properties文件(有序)
   */
  private static Properties readOrderedPropertiesFile() {
    Properties properties = new OrderedProperties();
    InputStreamReader inputStreamReader = null;
    try {
      InputStream inputStream = new BufferedInputStream(new FileInputStream("D:testOrder.properties"));
      //prop.load(in);//直接这么写,如果properties文件中有汉子,则汉字会乱码。因为未设置编码格式。
      inputStreamReader = new InputStreamReader(inputStream, "utf-8");
      properties.load(inputStreamReader);
    } catch (Exception e) {
      System.out.println(e.getMessage());
    } finally {
      if (inputStreamReader != null) {
        try {
          inputStreamReader.close();
        } catch (IOException e) {
          System.out.println(e.getMessage());
        }
      }
    }
    return properties;
  } 

  /**
   * 写Properties文件(有序)
   */
  private static void writeOrderedPropertiesFile(Properties properties) {
    properties.setProperty("phone", "10086");
    OutputStreamWriter outputStreamWriter = null;
    try {
      //保存属性到b.properties文件
      FileOutputStream fileOutputStream = new FileOutputStream("order.properties", false);//true表示追加打开,false每次都是清空再重写
      //prop.store(oFile, "此参数是保存生成properties文件中第一行的注释说明文字");//这个会两个地方乱码
      //prop.store(new OutputStreamWriter(oFile, "utf-8"), "汉字乱码");//这个就是生成的properties文件中第一行的注释文字乱码
      outputStreamWriter = new OutputStreamWriter(fileOutputStream, "utf-8");
      properties.store(outputStreamWriter, "lll");
    } catch (Exception e) {
      System.out.println(e.getMessage());
    } finally {
      if (outputStreamWriter != null) {
        try {
          outputStreamWriter.close();
        } catch (IOException e) {
          System.out.println(e.getMessage());
        }
      }
    } 

  }
}

其实读和写,都和使用系统提供的类的差别不大,只是现在读到了我们自己写的子类里面去了。

其他的代码都是一样样的。

下面是读的文件的内容截图:

再然后是,实际代码运行的结果截图:

---------(方式一)------------
1=11
2=22
3=33
4=44
5=55
6=66
7=77
8=88
9=99
10=18
11汉字=测试汉字以防乱码产生
---------(方式二)------------
1=11
2=22
3=33
4=44
5=55
6=66
7=77
8=88
9=99
10=18
11汉字=测试汉字以防乱码产生
---------(方式三)------------
11汉字=测试汉字以防乱码产生
9=99
8=88
7=77
6=66
5=55
4=44
3=33
2=22
10=18
1=11
---------(方式四)------------
1=11
2=22
3=33
4=44
5=55
6=66
7=77
8=88
9=99
10=18
11汉字=测试汉字以防乱码产生 

额,太长了,就不截图了吧,就给把打印结果给展示一下得了。

可以看到,只有第三次是无序的,具体原因,我也在代码里面解释过了。

还有,就是生成的文件的截图:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • java中读写Properties属性文件公用方法详解

    前言 大家都知道Java中有个比较重要的类Properties(Java.util.Properties),主要用于读取Java的配置文件,各种语言都有自己所支持的配置文件,配置文件中很多变量是经常改变的,这样做也是为了方便用户,让用户能够脱离程序本身去修改相关的变量设置.像Python支持的配置文件是.ini文件,同样,它也有自己读取配置文件的类ConfigParse,方便程序员或用户通过该类的方法来修改.ini配置文件.在Java中,其配置文件常为.properties文件,格式为文本文件,

  • Java 读写Properties配置文件详解

    Java 读写Properties配置文件 1.Properties类与Properties配置文件 Properties类继承自Hashtable类并且实现了Map接口,也是使用一种键值对的形式来保存属性集.不过Properties有特殊的地方,就是它的键和值都是字符串类型. 2.Properties中的主要方法 (1)load(InputStream inStream) 这个方法可以从.properties属性文件对应的文件输入流中,加载属性列表到Properties类对象.如下面的代码:

  • Java代码实现对properties文件有序的读写的示例

    最近遇到一项需求,要求把properties文件中的内容读取出来供用户修改,修改完后需要再重新保存到properties文件中.很简单的需求吧,可问题是Properties是继承自HashTable的,直接通过keySet().keys()或entrySet()方法对Properties中的元素进行遍历时取出来的内容顺序与properties文件中的顺序不一致,这是问题一:问题二是就算取出来的时候是有序的,保存到文件中时又是无序的了. 当然,解决这两个问题的方法有很多.我最终采用的方法是自定义一

  • java实现对excel文件的处理合并单元格的操作

    一.依赖引入 <dependency> <groupId>net.sourceforge.jexcelapi</groupId> <artifactId>jxl</artifactId> <version>2.6.12</version> </dependency> 二.表格操作 1.读取xls文件 测试文件为: 代码: public void test() throws IOException, BiffEx

  • 详解Java项目中读取properties文件

    下面1-4的内容是网上收集的相关知识,总结来说,就是如下几个知识点: 1.最常用读取properties文件的方法InputStream in = getClass().getResourceAsStream("资源Name");这种方式要求properties文件和当前类在同一文件夹下面.如果在不同的包中,必须使用: InputStream ins = this.getClass().getResourceAsStream("/cn/zhao/properties/test

  • Python实现对PPT文件进行截图操作的方法

    本文实例讲述了Python实现对PPT文件进行截图操作的方法.分享给大家供大家参考.具体分析如下: 下面的代码可以为powerpoint文件ppt进行截图,可以指定要截取的幻灯片页面,需要本机安装了powerpoint,可以指定截图的大小分辨率 import os import comtypes.client def export_presentation(path_to_ppt, path_to_folder): if not (os.path.isfile(path_to_ppt) and

  • python实现对csv文件的列的内容读取

    以下代码测试在python2.7 mac上运行成功 import csv with open('/Users/wangzhao/Downloads/test.csv', 'U') as csvfile: reader = csv.DictReader(csvfile) column = [row['Employee Name'] for row in reader] print column import csv with open('/Users/wangzhao/Downloads/test

  • java如何实时动态获取properties文件的内容

    目录 java 实时动态获取properties文件的内容 动态读取的代码 Java 读取配置文件 Properties VS ResourceBundle 1. 常用API 2. Properties 解析属性文件 3. ResourceBundle 解析属性文件 4. 属性文件 5. 实战推荐 java 实时动态获取properties文件的内容 用"ClassLoader.getResourceAsStream"读取properties文件时会发现修改了.properties后,

  • Python实现对excel文件列表值进行统计的方法

    本文实例讲述了Python实现对excel文件列表值进行统计的方法.分享给大家供大家参考.具体如下: #!/usr/bin/env python #coding=gbk #此PY用来统计一个execl文件中的特定一列的值的分类 import win32com.client filename=raw_input("请输入要统计文件的详细地址:") flag=0 #用于判断文件 名如果不带'日'就为 0 if '\xc8\xd5' in filename:flag=1 print 50*'

  • java使用POI读取properties文件并写到Excel的方法

    本文实例讲述了java使用POI读取properties文件并写到Excel的方法.分享给大家供大家参考.具体实现方法如下: package com.hubberspot.code; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import

  • Spring用代码来读取properties文件实例解析

    有些时候,我们需要以Spring代码直接读取properties配置文件,那么我们要如何操作呢?下面我们来看看具体内容. 我们都知道,Spring可以@Value的方式读取properties中的值,只需要在配置文件中配置 org.springframework.beans.factory.config.PropertyPlaceholderConfigurer <bean id="propertyConfigurer" class="org.springframewo

  • java代码实现C盘文件统计工具

    概述 工作电脑用了3年多了,100G的C盘也快吃不消了,每次打开看到C盘红了,总要用清理工具清理一下子. 不知道怎么最近清理工具清理了也没有什么效果,把temp下面的文件删除,没什么大作用. 总是有一种冲动要去处理掉,已经影响工作了.乘着星期天写个工具,分析一下C盘的文件,看看那些是最近才增加的,能不能手动删除掉. 版本介绍 Maven-3.3.9 JDK1.8 目录结构 com └─sedaier └─calcdir ├─service │ │ IDirSizeCalc.java │ │ │

随机推荐