Properties类按顺序输出加载内容
Properties类按顺序输出加载内容
最近手写工厂的时候,遇到了加载配置文件时不按照properties文件中的数据的顺序来加载。
一、问题代码
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
public class PropertiesTest {
public static void main(String[] args) {
InputStream ips = null;
try {
ips = Properties.class.getResourceAsStream("/test.properities");
Properties props = new Properties();
props.load(ips);
for(String name:props.stringPropertyNames())
System.out.println(props.getProperty(name) + " "+name);
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(ips != null){
ips.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
配置文件
cat=1
dog=2
bird=3
mouse=4
pig=5
输出结果
二、原因分析
public class Properties extends Hashtable<Object,Object>
上面是Properties类的定义,可以看到它继承了Hashtable类
public synchronized void load(InputStream inStream) throws IOException {
load0(new LineReader(inStream));
}
load方法调用load0方法
private void load0 (LineReader lr) throws IOException {
char[] convtBuf = new char[1024];
int limit;
int keyLen;
int valueStart;
char c;
boolean hasSep;
boolean precedingBackslash;
while ((limit = lr.readLine()) >= 0) {
c = 0;
keyLen = 0;
valueStart = limit;
hasSep = false;
//System.out.println("line=<" + new String(lineBuf, 0, limit) + ">");
precedingBackslash = false;
while (keyLen < limit) {
c = lr.lineBuf[keyLen];
//need check if escaped.
if ((c == '=' || c == ':') && !precedingBackslash) {
valueStart = keyLen + 1;
hasSep = true;
break;
}
else if ((c == ' ' || c == '\t' || c == '\f') && !precedingBackslash) {
valueStart = keyLen + 1;
break;
}
if (c == '\\') {
precedingBackslash = !precedingBackslash;
} else {
precedingBackslash = false;
}
keyLen++;
}
while (valueStart < limit) {
c = lr.lineBuf[valueStart];
if (c != ' ' && c != '\t' && c != '\f') {
if (!hasSep && (c == '=' || c == ':')) {
hasSep = true;
} else {
break;
}
}
valueStart++;
}
String key = loadConvert(lr.lineBuf, 0, keyLen, convtBuf);
String value = loadConvert(lr.lineBuf, valueStart, limit - valueStart, convtBuf);
put(key, value);
}
}
load0方法可以看到最后取到key和value值后会调用父类Hashtable的put()
方法,把数据存入Hashtable,具体的Hashtable源码这里就不再贴出。简单来说Hashtable的put()
方法接收到值后会按照哈希值存储,而不是按照读取顺序存储。
接下来是读取时的源码,有兴趣的可以看一下:
public Set<String> stringPropertyNames() {
Hashtable<String, String> h = new Hashtable<>();
enumerateStringProperties(h);
return h.keySet();
}
enumerateStringProperties
方法:
private synchronized void enumerateStringProperties(Hashtable<String, String> h) {
if (defaults != null) {
defaults.enumerateStringProperties(h);
}
for (Enumeration<?> e = keys() ; e.hasMoreElements() ;) {
Object k = e.nextElement();
Object v = get(k);
if (k instanceof String && v instanceof String) {
h.put((String) k, (String) v);
}
}
}
Hashtable的keySet()
方法
public Set<K> keySet() {
if (keySet == null)
keySet = Collections.synchronizedSet(new KeySet(), this);
return keySet;
}
三、解决方法
写一个工具类继承Properties类,实现以下功能:
- 创建一个能够按照读取顺序来存储properities文件中的key值的集合框架
- 能够返回步骤1创建的集合
在这里我采用了LinkedList
来顺序存储key值(也可以采用别的集合类型),然后重写put方法,先把值存入自己建的LinkedList
中,再调用父类的方法。关于返回Key值的集合是新写了一个orderStringPropertyNames()
方法返回LinkedList
实现代码如下:
import java.util.LinkedList;
import java.util.Properties;
public class LinkedProperities extends Properties {
private LinkedList<String> linkedList = new LinkedList<String>();
@Override
public synchronized Object put(Object key, Object value) {
linkedList.add((String) key);
return super.put(key, value);
}
public LinkedList<String> orderStringPropertyNames() {
return linkedList;
}
}
四、结果测试
Properties类按顺序输出加载内容的更多相关文章
- Java 类中各成分加载顺序 和 内存中的存放位置
参加一个笔试,有一个关于类的静态代码块.构造代码块.构造函数的执行顺序的问题.不太清楚,网上百度了一下.在这里记录一下. 一.什么时候会加载类?使用到类中的内容时加载:有三种情况1.创建对象:new ...
- Java笔记(十二)……类中各部分加载顺序及存放位置问题
什么时候会加载类 使用到类中的内容时加载,三种情况: 创建对象:new StaticDemo(); 使用类中的静态成员:StaticCode.num = 9; StaticCode.getNum() ...
- struts2:struts.properties配置文件介绍及常量加载顺序
1. 背景 struts2框架中有两个核心配置文件,其中struts.xml文件主要负责管理应用中的action映射,以及该action包含的result定义等.除此之外,struts2框架还包括一个 ...
- java类的编译、加载和执行
一.java类的编译流程 这里主要讲的是从java文件到class文件 下图是java类编译的详细步骤: 1.词法分析:将java源代码的字符流转变为标记(Token)的集合,Token是编译过程中的 ...
- java类到底是如何加载并初始化的?
Java虚拟机如何把编译好的.class文件加载到虚拟机里面?加载之后如何初始化类?静态类变量和实例类变量的初始化过程是否相同,分别是如何初始化的呢?这篇文章就 是解决上面3个问题的. 若有不正之处, ...
- (转)java类到底是如何加载并初始化的?
Java虚拟机如何把编译好的.class文件加载到虚拟机里面?加载之后如何初始化类?静态类变量和实例类变量的初始化过程是否相同,分别是如何初始化的呢?这篇文章就 是解决上面3个问题的. 若有不正之处, ...
- Win8 Metro动态加载内容框架
制作背景 为了参加ImagineCup 2013 世界公民类比赛,我们设计制作了一个可动态扩展的幼教类App.这个App需要能动态加载内容,内容包括带动画可交互的电子书,动画,视频,游戏. 技术支持 ...
- js 利用 ajax 加载 js ,显示加载进度 ,严格按照js的顺序先后加载到页面
js 利用 ajax 加载 js ,显示加载进度 ,严格按照js的顺序先后加载到页面 , 做手机端开发时,发现一个问题,有些浏览器,在网速比较慢的情况下,js文件没有加载完,后续的调用已经开始调用了, ...
- Java虚拟机——类的结构与加载
1.为什么Java可以跨平台 因为有java虚拟机,跨平台是因为字节码即class文件具有平台无关性,java代码会经过java虚拟机转换为字节码 2.class文件的结构 class文件主要是以8位 ...
随机推荐
- java.sql.SQLException: Incorrect string value: '\xF0\x9F\x98\x8E' for column 'name' at row 1
我的错误案例: ,这个后台插不进去,就姓名那栏的中文编码问题. 遇到这个错误,应该是创建表的时候没有设置好编码,这个错误不用多想,我也试过在更改表那里设置编码,但还是不行,还是有残留 直接drop t ...
- 对于隐藏性质的非标准的动态 id 的下拉框,如何定位和选中
今天,在页面上碰到一个非 select 标签的下拉框,打算进行定位和模拟选中. <input aria-invalid="false" autocomplete=" ...
- c# 第39节 抽象类、抽象方法
本节内容: 1:抽象类的说明 2:抽象类的实例 1:抽象类的说明 抽象类定义:方法前有abstract就称为抽象类.抽象方法,抽象方法不提供任何实际实现. 注意点1: 抽象方法必须在抽象类中声明: 不 ...
- adb的端口号5037被占用的解决方法
1.在cmd中执行adb nodaemon server,查看adb的端口号是多少,一般情况下是5037(why?应该软件使用的端口号是固定的) 2.再执行netstat -ano | findstr ...
- CF1010D Mars rover
CF1010D Mars rover 洛谷评测传送门 题目描述 Natasha travels around Mars in the Mars rover. But suddenly it broke ...
- git 入门教程之 git bash 竟然不支持 tree 命令
开门见山 git bash 是 Windows 用户安装 git 时默认安装的命令行工具,不仅界面漂亮功能也不错,大多数情况下可以替代 Windows 原生的 cmd 命令行. 然而,git bash ...
- LeetCode 739 每日温度
1.直接遍历 暴力求解 class Solution { public: vector<int>dailyTemperatures(vector<int>& T) { ...
- OpenGL ES 入门
写在前面 记录一下 OpenGL ES Android 开发的入门教程.逻辑性可能不那么强,想到哪写到哪.也可能自己的一些理解有误. 参考资料: LearnOpenGL CN Android官方文档 ...
- 算法六Z自形变换
将一个给定字符串根据给定的行数,以从上往下.从左到右进行 Z 字形排列. 比如输入字符串为 "LEETCODEISHIRING" 行数为 3 时,排列如下: L C ...
- SEO-------- 了解
SEO(Search Engine Optimization) 译为:搜索引擎优化,是一种透过了解搜索引擎的运作规则来调整网站,以及提高目的的网站在有关搜索引擎内的排名方式. 目的:为了让用户更快的搜 ...