教你正确使用Java Properties_惠州JAVA培训
作者:黄君发布时间:2020-11-10分类:热点问答浏览:1095
正确使用Java Properties
安静下来学一些常用开源项目,在翻struts2的时候看到读取properties配置文件是自己定义的reader来读取,因为之前上班的时候常常使用到properties的读写,对于jdk本身的properties在保存的时候会把注释忽略掉这点深恶痛绝,一直想重新写一个properties文件读写的工具类,但是大致翻了一下properties的代码和文档,发现properties的规则挺多,没有几天时间怕是难以完成就一直搁下了。这次看到struts2的代码就想拿来借鉴一下,于是就把properties的东西读了一遍,发觉很多东西是之前忽略甚至不知道的,于是记下和兄弟们共享,如有错欢迎指正,概念颇多,容易晕头,建议找头脑清醒的时候看。
JDK Properties核心在读取配置文件的
Java代码
private void load0 (LineReader lr) throws IOException
方法上。其中传入的参数LineReader类是Properties的内部类,用来读取一个逻辑行(这儿就不详细介绍了,它会读取一个逻辑行并且忽略掉逻辑行行首的所有空白字符和换行字符)。
load0方法的JDK文档总结如下,这也是后续的几个重要的概念的出处:
1.注释符为:'#'或者'!'。空白字符为:' ', '\t', '\f'。key/value分隔符为:'='或者':'。行分隔符为:'\r','\n','\r\n'。
2.自然行是使用行分隔符或者流的结尾来分割的行。逻辑行可能分割到多个自然行中,使用反斜杠'\'来连接多个自然行。
3.注释行是使用注释符作为首个非空白字符的自然行。
4.空白字符的自然行会被认为是空行而被忽略。
5.properties文件的key为从首个非空白字符开始直到(但不包括)首个非转义的'=', ':'或者非行结束符的空白字符为止。
6.key后面的第一个非空白字符如果是”=”或者”:”,那么这个字符后面所有空白字符都会被忽略掉。
7.可以使用转义序列表示key和value(当然此处的字符转义序列和unicode的转义有一些差别,jdk文档都有列出来)。
properties是一个包含了key、value对的文本文档,key,value的界定是正确读取properties的关键,那么key、value是如何界定的呢?上面第5点是对key的不完全界定但是并未涉及到value,这些,都只有从源码当中来寻找答案。
load0源码和注解如下:
Java代码
private void load0(LineReader lr) throws IOException {
char[] convtBuf = new char[1024];
//行的长度
int limit;
//key的长度
int keyLen;
//value的开始点
int valueStart;
//当前读取的字符
char c;
//是否是key/value的分隔符
boolean hasSep;
//前一个字符是否是反斜杠
boolean precedingBackslash;
//把通过LineReader读取来的逻辑行进行遍历,一个个char的进行处理。
while ((limit = lr.readLine()) >= 0) {
c = 0;
keyLen = 0;
valueStart = limit;
hasSep = false;
precedingBackslash = false;
//循环获取key的长度
while (keyLen < limit) {
c = lr.lineBuf[keyLen];
//当字符为key/value分隔符:'='或':'并且前一个字符不是反斜杠的时候,key长度读取结束,并且把hasSep设置为true,break。
if ((c == '=' || c == ':') && !precedingBackslash) {
valueStart = keyLen + 1;
hasSep = true;
break;
}
//当字符为空白字符' '或'\t'或'\f'并且前一个字符不是反斜杠的时候,key长度读取结束,break。
else if ((c == ' ' || c == '\t' || c == '\f') && !precedingBackslash) {
valueStart = keyLen + 1;
break;
}
//当连续存在奇数个反斜杠的时候, precedingBackslash为true。
if (c == '\\') {
precedingBackslash = !precedingBackslash;
} else {
precedingBackslash = false;
}
keyLen++;
}
//循环获取value开始的位置
while (valueStart < limit) {
c = lr.lineBuf[valueStart];
//如果字符不为所有的空白字符:' ', '\t', '\f'的时候
if (c != ' ' && c != '\t' && c != '\f') {
//如果前面不是key/value的分隔符,而是空白字符,而该字符是key/value分隔符
if (!hasSep && (c == '=' || c == ':')) {
hasSep = true;
} else {
//结束读取
break;
}
}
valueStart++;
}
//loadConvert是进行字符串转义的方法,就不用关心了。
String key = loadConvert(lr.lineBuf, 0, keyLen, convtBuf);
String value = loadConvert(lr.lineBuf, valueStart, limit - valueStart, convtBuf);
put(key, value);
}
}
通过如上的代码可以看出,key/value分割符'=', ':'与空白字符:' ', '\t', '\f'是区分key、value的关键:
key的界定为:逻辑行中,从首个非空白字符开始直到(但不包括)首个非转义的'=', ':'或者非行结束符的空白字符为止。(和前面第5点基本一致)
value的界定为:逻辑行中,非转义的key/value分隔符(此处不仅仅包括'=',':',还包括' ', '\t', '\f')后面的第一个非空白字符(非' ', '\t', '\f'字符)开始到逻辑行结束的所有字符。
另外key、value还有如下特征:
1.因为LineReader是读取的逻辑行,所以key、value中可以包含多个自然行。
2.在“循环获取key的长度”的代码中可以看到处理key/value分隔符的方式和处理空白字符的方式很相似(除了在发现处理的字符为key/value分隔符的时候会把 hasSep变量设置为true)。而这表明:
如果空白字符后续没有key/value分隔符(“=”或者“:”),那么该空白字符会被当作key/value分隔符,从分隔符后的第一个非空白字符起到逻辑行结束所有的字符都当作是value。也就是说:“key1 value1”,读取出来之后的key和value分别为”key1”, “value1”。
如果空白字符后续有key/value分隔符(“=”或者“:”),那么该空白字符会被忽略,key/value分隔符后的第一个非空白字符起到逻辑行结束所有的字符都当作是value。也就是说:”key1 :value1”,读取出来之后的key和value分别为”key1”和”value1”,而不是”key1”和”:value1”。
另外,在读xwork的com.opensymphony.xwork2.util.PropertiesReader类的时候发现,它的实现和JDK的Properties实现有出入,也就是说,如果JDK的Properties是规范的话,那么xwork的properties读取类是有bug的。测试类如下(注释掉的Assert才能通过junit):
Java代码
public class PropertiesTest {
@Test
public void testLoad() throws IOException {
File f = new File(getClass().getResource(".").getPath(), "test.properties");
InputStream in = null;
try {
//java properties
in = new FileInputStream(f);
Properties props = new Properties();
props.load(in);
String s1 = props.getProperty("key");
Assert.assertEquals("value#with", s1);
String s2 = props.getProperty("comments");
Assert.assertEquals("", s2);
} finally {
if (in != null)
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
try {
//xwork properties
in = new FileInputStream(f);
Reader reader = new InputStreamReader(in);
PropertiesReader pr = new PropertiesReader(reader);
while (pr.nextProperty()) {
String name = pr.getPropertyName();
String val = pr.getPropertyValue();
if ("key".equals(name)) {
Assert.assertEquals("value#with", val);
//Assert.assertEquals("valuecomments", val);
}
if ("comments".equals(name)) {
Assert.assertEquals("", val);
//Assert.assertEquals(null, val);
}
}
} finally {
if (in != null)
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
test.properties的内容如下:
Java代码
key=value\
#with
comments
好了,清楚properties的使用规则了,如果我们需要自己写一个实现在保存properties的时候注释不被忽略掉,而且按照原来的行数来保存的工具类的话,就会清晰很多了。本来想把这个工具写一下,但是写代码加调试实在太费时间,等到用的时候再来写吧。
相关推荐
- 转职Web前端开发要具备哪些技术?_惠州前端培训学校
- 转行Web前端开发要掌握哪些技术?_惠州前端培训学校
- 如何学习Web前端知识转型?_惠州前端培训学校
- Web前端工程师必须具备哪些JS技巧?_惠州前端培训学校
- Web前端开发|怎么封装几个Vue3中很有用的组合式API?_惠州前端培训学校
- Web前端开发如何使用JS中的arguments?_惠州前端培训学校
- Web前端开发如何在TypeScript中使用基本类型?_惠州前端培训学校
- 优秀Web前端开发工程师必须具备哪些技能?_惠州前端培训学校
- Web前端开发|GraphQL是什么?_惠州前端培训学校
- Web前端工程师要学会哪些技能?_惠州前端培训学校
- 热点问答排行
- 标签列表
-
- Java (3694)
- 北大青鸟 (3713)
- 软件开发 (3613)
- JAVA (3413)
- UI设计入门 (2093)
- 惠州北大青鸟 (4375)
- 惠州IT培训 (2558)
- UI设计培训 (2090)
- 惠州UI设计培训 (2095)
- 惠州UI设计培训学校 (2090)
- 惠州计算机软件培训 (6260)
- 惠州计算件软件开发 (6260)
- 惠州计算机软件基础 (6261)
- 惠州计算机JAVA培训 (3574)
- 惠州计算机Java软件开发 (3620)
- 惠州计算机JAVA软件开发 (4645)
- 惠州计算机JAVA软件开发学校 (3338)
- 惠州计算机Java软件开发培训 (3338)
- 北大青鸟IT计算机学校 (5048)
- 北大青鸟IT软件学校 (5062)
- 北大青鸟IT学校 (5059)
- 惠州计算机UI设计软件开发 (2088)
- UI设计基础教程 (2088)
- UI设计是什么 (2088)
- UI设计教程 (2088)
- 网站分类
-
- 计算机教程
- 计算机入门
- 职业学校
- 新闻动态
- 专业课程
- 热门技术
- SEO
- 培训教程
- windows
- linux教程
- 系统集成
- 网站开发
- Html5
- 办公软件
- 师资力量
- 热点问答
- 联系我们
- 计算机学校
- 惠州计算机学校
- 河源计算机学校
- 广州计算机学校
- 深圳计算机学校
- 湛江计算机学校
- 佛山计算机学校
- IT计算机培训信息
- 设计专业
- UI
- 影视特效
- 游戏动漫设计
- Photoshop
- AI设计
- 软件教程
- Java技术
- C语言/C++语言培训
- C#
- Python技术
- PHP
- 数据库
- SQL Server
- 网络教程
- 网络安全
- 网络营销
- 软件专业
- 大数据专业
- 前端开发专业
- 软件测试专业
- Python专业
- 软件实施
- 珠海计算机学校
- 初中生学什么好
- 计算机认证
- 文章归档
-
- 2024年11月 (14)
- 2024年10月 (32)
- 2024年9月 (29)
- 2024年8月 (68)
- 2024年7月 (59)
- 2024年6月 (43)
- 2024年5月 (48)
- 2024年4月 (80)
- 2024年3月 (65)
- 2024年2月 (54)
- 2024年1月 (25)
- 2023年12月 (12)
- 2023年11月 (73)
- 2023年10月 (134)
- 2023年9月 (34)
- 2023年8月 (3)
- 2023年7月 (3)
- 2023年6月 (12)
- 2023年5月 (30)
- 2023年4月 (72)
- 2023年3月 (11)
- 2023年2月 (34)
- 2023年1月 (37)
- 2022年12月 (78)
- 2022年11月 (359)
- 2022年6月 (1193)
- 2022年5月 (570)
- 2022年4月 (1567)
- 2022年3月 (982)
- 2022年2月 (54)
- 2022年1月 (182)
- 2021年9月 (308)
- 2021年8月 (1704)
- 2021年7月 (2423)
- 2021年6月 (1806)
- 2021年5月 (1569)
- 2021年4月 (1380)
- 2021年3月 (1255)
- 2021年2月 (709)
- 2021年1月 (1521)
- 2020年12月 (3626)
- 2020年11月 (1646)
- 2020年10月 (1046)
- 2020年9月 (592)
- 最近发表
-
- 清远信息:2024年广清杯清远南粤家政技能大赛举行决赛|||计算机培训机构
- 汕尾信息:陈良川带队到汕尾技师学院调研|||计算机职业技能培训班
- 东莞信息:凤岗凤岗镇组织召开社保参保缴费及劳动用工政策宣讲会|||计算机软件培训学校
- 阳江信息:2024年度注册城乡规划师职业资格考试的合格标准是怎样的?|||计算机软件培训学校
- 阳江信息:职业技能提升补贴对象有哪些?|||大学生计算机培训学校
- 清远信息:清远市首家社保服务合作网点在清城区举办启动仪式|||计算机职业技能培训班
- 汕头信息:招聘658名中高端人才!2024年汕头市引进中高端人才专场招聘会举行|||北大青鸟计算机培训中心
- 东莞信息:广东省社保智能经办现场会在东莞召开|||大学生计算机培训学校
- 东莞信息:东坑镇举办2024年重点群体系列招聘活动|||计算机职业技能培训班
- 东莞信息:万江万江街道成功举办第四届粤菜师傅烹饪技能竞赛|||广州计算机编程培训