欢迎来到代码驿站!

JAVA代码

当前位置:首页 > 软件编程 > JAVA代码

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

时间:2023-01-07 09:28:33|栏目:JAVA代码|点击:

最近遇到一项需求,要求把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汉字=测试汉字以防乱码产生 

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

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

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

上一篇:java读取其他服务接口返回的json数据示例代码

栏    目:JAVA代码

下一篇:Java深入数据结构理解掌握抽象类与接口

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

本文地址:http://www.codeinn.net/misctech/223154.html

推荐教程

广告投放 | 联系我们 | 版权申明

重要申明:本站所有的文章、图片、评论等,均由网友发表或上传并维护或收集自网络,属个人行为,与本站立场无关。

如果侵犯了您的权利,请与我们联系,我们将在24小时内进行处理、任何非本站因素导致的法律后果,本站均不负任何责任。

联系QQ:914707363 | 邮箱:codeinn#126.com(#换成@)

Copyright © 2020 代码驿站 版权所有