- 浏览: 300121 次
- 性别:
- 来自: 山西
博客专栏
-
天天编程
浏览量:21490
最新评论
-
变脸小伙:
运用到了场景中,希望接力
StringBuffer源码理解 -
fangsj:
IE9 安全设置 把这个禁用掉了
spring mvc 文件上传+本地预览+一次提交 -
xu-ch:
今天面试,遇到这题,求出了相似度,面试官问我算法原理是什么,悲 ...
计算字符串相似度算法——Levenshtein -
flywangfei:
你是创新工场的么?
计算字符串相似度算法——Levenshtein -
scwuwei:
六点起床比较好
《4点起床-最养生和高效的时间管理》读书笔记
Properties用来读配置文件的对象,用的很多。
使用方法
// 新建一个对象 Properties pro = new Properties(); // 加载字节流 pro.load(new FileInputStream("abc.txt")); // 取值 System.out.println(pro.getProperty("key")); // 修改 pro.setProperty("key", "value");
0.几个问题
1.a=b=c 会被拆分成什么样? 答:key="a",value="b=c" 2.字符中有 = 该怎么办? 答:办法一:\= 办法二:\u003D 3.a<空格><空格>d = 2<空格>44 可以作为一个正常的配置么? 答:不能,空格会作为key的结束 4.a=2<空格>34<空格>5 最后的值value为多少? 答: "2 34 5" 5.在配置文件中最后的空格会被去掉吗? 答:不会被去掉,程序中只会去掉前面和等号左右的空格。 6.想在配置文件里换行改怎么办 答:在回车前输入一个\ 7.pro.load(new FileInputStream("abc.txt")); 这样打开abc.txt的文件流关闭没有? 答:流未关闭,需要手动关闭,不建议这样写。但是虚拟机在回收这个对象的时候会关闭流。
1.构造方法
类继承了hashTable类
public class Properties extends Hashtable<Object,Object>
本身是一个Map ,这个对象主要用来储存key-value的键值对,所以可以使用另一个Properties来初始化自己。
protected Properties defaults; public Properties() { this(null); } public Properties(Properties defaults) { this.defaults = defaults; }
2.使用的第一步,load()。
先简单的说一下load的执行过程:
1.读一行。
2.找到key 和 value 。
3.存入map中<String,String>
//下面是Properties类中方法 public synchronized void load(InputStream inStream) throws IOException { //将输出流转成LineReader,LineReader是Properties的内部类,功能是可以一行一行的读数据。 load0(new LineReader(inStream)); } //私有 private void load0 (LineReader lr) throws IOException { //由于key和value中会有转义字符串,所以用这个数组来存储key或者value的转义后的数据。 char[] convtBuf = new char[1024]; int limit;//一行字符数(除一行前面空格,到末尾的回车符) int keyLen;//key值长度 int valueStart;//value起始 char c;//在循环遍历时暂存一个字符,临时使用,命名也很不规范。 boolean hasSep;//是否有分割符 = 或者: boolean precedingBackslash; //当前读取是否为转义字符 /*循环读取每一行,每一行分析出key和value。limit为每一行字符数长度(除前面空格),-1表示流读完了 */ while ((limit = lr.readLine()) >= 0) { c = 0; keyLen = 0; valueStart = limit; hasSep = false; //下面的system是原作者写的,不认真。 //System.out.println("line=<" + new String(lineBuf, 0, limit) + ">"); //字面上是反斜杠的意思,表示碰到了转义的反斜杠"\"。 precedingBackslash = false; /*这个循环主要找出key结束的地方,也简单的找了一个value大概开始部分。*/ while (keyLen < limit) { //这个lineBuf是LineReader里的一个字符数组,存了一行字符。 c = lr.lineBuf[keyLen]; //找到分隔符 if ((c == '=' || c == ':') && !precedingBackslash) { //value的起始点 valueStart = keyLen + 1; //找到key和value的分隔符 hasSep = true; //找到key结束的位置,跳出循环 break; /*同样空格\t \f 也是key结束的地方*/ } else if ((c == ' ' || c == '\t' || c == '\f') && !precedingBackslash) { valueStart = keyLen + 1; break; } //如果是反斜杠,则跳过下一个字符 if (c == '\\') { //连续两个反斜杠的话又变为false了。 precedingBackslash = !precedingBackslash; } else { //未碰到变为false。 precedingBackslash = false; } //这个就是key的长度。 keyLen++; } /*计算value的开始点*/ while (valueStart < limit) { c = lr.lineBuf[valueStart]; /*这个if是为了去掉value前的空格字符*/ if (c != ' ' && c != '\t' && c != '\f') { /*这个if是为了在key值中因为空格跳出,然后空格后接着是“="或":"的情况下*/ if (!hasSep && (c == '=' || c == ':')) { //有了分割key和value的标识 hasSep = true; } else { //结束value开始的检查 break; } } valueStart++; } //取key和value。 String key = loadConvert(lr.lineBuf, 0, keyLen, convtBuf); String value = loadConvert(lr.lineBuf, valueStart, limit - valueStart, convtBuf); //这个类继承了HashTable put(key, value); } }
紧接着,我们看一下怎么取出key和value,并且将其内部的转义符都去掉。
/* 加载转化, * in 传入的字符数组 * off 要取值开始的地方 * len 要取的长度 * convtbuf 输出的字符数组 */ private String loadConvert (char[] in, int off, int len, char[] convtBuf) { //如果数组的长度小于要取长度 if (convtBuf.length < len) { int newLen = len * 2; //如果传入的len为负的,性能就非常差了,少个判断! if (newLen < 0) { newLen = Integer.MAX_VALUE; } convtBuf = new char[newLen]; } char aChar; char[] out = convtBuf; //换个名字 int outLen = 0; //输出的长度 int end = off + len;//要取字符结束的地方 //循环从要取字符开始到结束。 while (off < end) { aChar = in[off++]; //如果是转义字符 if (aChar == '\\') { aChar = in[off++]; //如果是unicode if(aChar == 'u') { //读4位,4位表示unicode的编码集. int value=0; //下面的步骤可以理解成Integer.paseInt("7EA2",16) for (int i=0; i<4; i++) { aChar = in[off++]; switch (aChar) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': value = (value << 4) + aChar - '0'; break; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': value = (value << 4) + 10 + aChar - 'a'; break; case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': value = (value << 4) + 10 + aChar - 'A'; break; default: //抛出的这个异常不需要捕获。 throw new IllegalArgumentException( "Malformed \\uxxxx encoding."); } } //写入输出的数组 out[outLen++] = (char)value; } else { //这样就其它转义字符处理了 if (aChar == 't') aChar = '\t'; else if (aChar == 'r') aChar = '\r'; else if (aChar == 'n') aChar = '\n'; else if (aChar == 'f') aChar = '\f'; //这一步非常关键,它直接忽略转义符号\ ,举例:\= 会存为 = , \\ 会存为\ , \?会存为 ?,\<空格> 会存 为 <空格> out[outLen++] = aChar; } } else { //无转义 out[outLen++] = (char)aChar; } } return new String (out, 0, outLen); }
它是怎么读取一行数据的?下面需要看一下Properties的内部类LineReader
3.Properties的内部类LineReader
3.1首先是无任何继承
class LineReader {}
3.2构造方法
字符流和字节流通吃。
public LineReader(InputStream inStream) { this.inStream = inStream; inByteBuf = new byte[8192]; } public LineReader(Reader reader) { this.reader = reader; inCharBuf = new char[8192]; }
3.3 readLine方法
简单的看一下吧,这个不是重点
文字介绍:读取每一个字符,空白的跳过,碰到一行第一个字符检查是否为#或者!,继续循环直到碰到\r 或者\n ,然后结束进入一个新一行的循环。末尾的空格不去掉。
int readLine() throws IOException { int len = 0; //数组长度 //另外一些变量 ... while (true) { //从字节流中读取 8192个字节,或者从字符流中读取8192个字符 if (inOff >= inLimit) { inLimit = (inStream==null)?reader.read(inCharBuf) :inStream.read(inByteBuf); //如果流读到末尾 if (inLimit <= 0) { //流的长度是0,或者是注释,直接返回-1,结束。 if (len == 0 || isCommentLine) { return -1; } return len; } } //取出一个字符 ... //碰到\\r的情况,意思是\\r\n 或者 \\r \\n都不会进行换行,同样\\r \\r\n \\n 也不加入字符数组中。 if (skipLF) { skipLF = false; if (c == '\n') { continue; } } //跳过空白 if (skipWhiteSpace) { if (c == ' ' || c == '\t' || c == '\f') { continue; } //如果没有开始,并且字符时\r \n 的,同样跳过。 if (!appendedLineBegin && (c == '\r' || c == '\n')) { continue; } //如果不是上述情况,则代表已经不是空格字符了。 skipWhiteSpace = false; appendedLineBegin = false; } //如果是新的一行 if (isNewLine) { isNewLine = false; //如果是注释 if (c == '#' || c == '!') { isCommentLine = true; continue; } } //检查字符是不是换行 if (c != '\n' && c != '\r') {//不是换行 lineBuf[len++] = c; //下面是检查是否越界了 ... //同样处理转义字符 ... } else {// 这里是找到了换行的字符了 //注释或者空行 if (isCommentLine || len == 0) { isCommentLine = false; isNewLine = true; skipWhiteSpace = true; len = 0; continue; } //如果当前字符超过了读取到的字符数。 if (inOff >= inLimit) { inLimit = (inStream==null) ?reader.read(inCharBuf) :inStream.read(inByteBuf); inOff = 0; if (inLimit <= 0) { return len; } } //下面还有回车前碰到转义符的情况 ... } } }
4.取值和修改
在load里面使用put存储了数据,这里取值很简单。
public String getProperty(String key) { Object oval = super.get(key); String sval = (oval instanceof String) ? (String)oval : null; return ((sval == null) && (defaults != null)) ? defaults.getProperty(key) : sval; } public String getProperty(String key) { Object oval = super.get(key); String sval = (oval instanceof String) ? (String)oval : null; return ((sval == null) && (defaults != null)) ? defaults.getProperty(key) : sval; }
5.方法中也包含着将数据存成文本的功能。
在存储xml的时候,用到了 java.util.XMLUtils 来解析xml。
storeToXML() loadFromXML()
6.读取时候去除绝对路径
props.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("config.properties"));
7.结束
发表评论
-
fastcgi中的多线程使用
2012-04-06 22:38 136980.背景 在项目中加入了 ... -
crc循环校验原理和实现
2012-03-29 23:33 192781.CRC简介 CRC(cyclical redundanc ... -
TreeMap源码理解
2012-01-31 10:44 01.首先看构造方法 public TreeMap() { ... -
HashMap源码理解
2012-01-30 21:33 1840看看HashMap对应的源码。 1.类、接口关系 ... -
StringUtils源码理解(下)
2012-01-16 15:46 2198本文介绍StringUtils的剩下的两个方法 1. ... -
StringUtils源码理解(中)有点意思的方法
2012-01-12 00:17 3632这次不按照前面的介绍了,方法都大同小异,下面就介绍几个有意思一 ... -
StringUtils源码理解(上)
2012-01-11 23:08 4740StringUtils 源码,使用的是commons-lang ... -
字符流(一)Reader和Writer源码理解
2011-11-27 20:32 14551.Reader 1.1 继承关系 public ... -
字符流(二)BufferedReader和BufferedWriter源码理解
2011-11-27 20:33 47841.BufferedReader 1.1 继承关系 ... -
DataInputStream和DataOutputStream源码理解
2011-11-17 00:02 43721.FilterInputStream简介 列出主要的内 ... -
InputStream,OutputStream源码理解
2011-11-09 22:50 33651.理解字节流和字符流 按流的形式分: 字节流和字符流。 ... -
File源码理解
2011-11-07 23:55 43261.构造函数 最基本的构 ... -
Thread源码理解
2011-10-23 14:36 43061.首先看一下Runnable接口 ... -
泛型简单回顾
2011-09-06 23:36 1283泛型的简介 1.java引入泛型的好处是安全简单。 2. ... -
LinkedList源码理解
2011-08-31 00:26 1405LinkedList源码 0.首先这个类中的两个变量 ... -
Vector源码理解
2011-08-29 23:44 1504Vector类 1.系统的变量 //记录元素的数组 pr ... -
ArrayList源码理解
2011-08-15 21:02 1691构造方法: ... -
Arrays源码理解
2011-08-15 20:34 13321.equals public static boo ... -
StringBuffer源码理解
2011-06-22 19:39 5645StringBuffer 存储和操作字符串 它所继承实现的类 ...
相关推荐
一、源码特点 ssm 体检预约管理系统是一套完善的信息系统,结合springMVC框架完成本系统,对理解JSP java编程开发语言有帮助系统采用SSM框架(MVC模式开发),系统具有完整的源代码和数据库, 系统主要采用B/S模式...
一、源码特点 ssm 设备采购管理系统是一套完善的信息系统,结合springMVC框架完成本系统,对理解JSP java编程开发语言有帮助系统采用SSM框架(MVC模式开发),系统具有完整的源代码和数据库, 系统主要采用B/S模式...
一、源码特点 ssm 房屋销售管理系统是一套完善的信息系统,结合springMVC框架完成本系统,对理解JSP java编程开发语言有帮助系统采用SSM框架(MVC模式开发),系统具有完整的源代码和数据库, 系统主要采用B/S模式...
一、源码特点 idea 开发 SSM 网上选课管理系统是一套完善的信息管理系统,结合SSM框架和bootstrap完成本系统,对理解JSP java编程开发语言有帮助系统采用SSM框架(MVC模式开发),系统具有完 整的源代码和数据库,...
它包含了完整的源码、部署说明、演示视频以及源码介绍,帮助开发者快速搭建和理解智慧社区系统。 项目主要功能包括: 社区公告发布与查看:管理员可以发布社区公告,居民可以查看公告信息。 报修管理:居民可以...
项目标题:基于SSM框架的JavaScript全栈简易案例源码集 ...此案例不仅为初学者提供了一个易于理解的全栈开发框架,同时也为有经验的开发者提供了一个轻量级的代码参考模板,以便快速启动类似项目开发工作。
一、源码特点 ssm 科研奖励申报管理系统是一套完善的信息系统,结合springMVC框架完成本系统,对理解JSP java编程开发语言有帮助系统采用SSM框架(MVC模式开发),系统具有完整的源代码和数据 库,系统主要采用B/S...
一、源码特点 SSM 图书借阅管理系统是一套完善的信息管理系统,结合SSM框架和bootstrap完成本系统,对理解JSP java编程开发语言有帮助系统采用SSM框架(MVC模式开发),系统具有完整的源代码 和数据库,系统主要...
一、源码特点 idea 开发 SSM 学员信息管理系统是一套完善的信息管理系统,结合SSM框架和bootstrap完成本系统,对理解JSP java编程开发语言有帮助系统采用SSM框架(MVC模式开发),系统具有完 整的源代码和数据库,...
一、源码特点 idea 开发 SSM 小区物业管理系统是一套完善的信息管理系统,结合SSM框架和bootstrap完成本系统,对理解JSP java编程开发语言有帮助系统采用SSM框架(MVC模式开发),系统具有完 整的源代码和数据库,...
一、源码特点 idea 开发 SSM 人才引进管理系统是一套完善的信息管理系统,结合SSM框架和bootstrap完成本系统,对理解JSP java编程开发语言有帮助系统采用SSM框架(MVC模式开发),系统具有完整的源代码和数据库,...
一、源码特点 idea 开发 SSM 工厂效能管理系统是一套完善的信息管理系统,结合SSM框架和bootstrap完成本系统,对理解JSP java编程开发语言有帮助系统采用SSM框架(MVC模式开发),系统具有完整的源代码和数据库,...
一、源码特点 idea ssm 失物招领管理系统是一套完善的完整信息管理系统,结合SSM框架完成本系统SpringMVC spring mybatis ,对理解JSP java编程开发语言有帮助系统采用SSM框架(MVC模式开发) ,系统具有完整的源...
一、源码特点 idea 开发 SSM 校园兼职招聘平台是一套完善的信息管理系统,结合SSM框架和bootstrap完成本系统,对理解JSP java编程开发语言有帮助系统采用SSM框架(MVC模式开发),系统具有完 整的源代码和数据库,...
一、源码特点 ssm 网上订餐管理系统是一套完善的信息系统,结合springMVC框架完成本系统,对理解JSP java编程开发语言有帮助系统采用SSM框架(MVC模式开发),系统具有完整的源代码和数据库, 系统主要采用B/S模式...
项目标题:企业级SSM框架CRM系统...项目描述:该项目是基于SSM(Spring, SpringMVC, MyBatis)框架的企业级CRM(客户关系管理)系统源码,适合新手学习SSM框架的应用与实践,深入理解企业级系统的开发流程与架构设计。
本项目是基于Scala语言开发的Apache Spark学习与实践源码,共包含53个文件。其中,Scala源代码文件21个,文本文件7个,XML文件5个,Markdown文档5个,JSON配置文件3个,Avro Schema文件2个,CSV数据文件2个,...
项目名称:传智健康管理系统 项目概述:该项目是基于SSM(Spring、SpringMVC、MyBatis)框架开发的个人...简而言之,传智健康管理系统源码是一个集成了多种技术,适合深入理解和实践SSM框架应用开发的优质学习项目。
本资源提供了一整套基于Java语言和SSH(Spring, Struts2, Hibernate)框架开发的实验室设备管理系统设计源码。项目包含62个Java源文件、8个PNG图像文件、2个XML配置文件、2个properties配置文件、2个文本文件、2个...
基于Dubbox重新开发的简单监控系统源码+数据库,基于dubbo-monitor-simple改进而成,可以理解为其演化版本。该系统用数据库记录日志的方式替代了dubbo-monitor-simple写文件的方式 配置介绍 第一步:创建数据库 首先...