若有不对的地方,也需要将正则表达式中的宏进

2019-08-17 作者:编程   |   浏览(95)

Java开发中使用POI库操作Excel,poiexcel

首先,我们要重点说明一下Excel的两中不同的格式,这个直接影响到我们在使用POI操作Excel的方式。一定要先明确你要操作的Excel所使用的版本,切记!  

用java开发编译器之:代码实现Thompson构造1,输入文本预处理

本节目的是Thompson构造实现的第一步,输入文本预处理.本节的代码可以在云课堂的附件中提取。

本节代码的目录结构如下:

图片 1

 

我们程序的目的,是希望将文本格式的正则表达式转换为链表式的NFA,即将文本:

D[0-9]

{D} return ICON

({D} | {D}*.{D} | {D} .{D}*)(e{D} )

转换为

图片 2

 

在转换前,我们需要对文本进行预处理,在上面的文本中,其实分成了两个不同的部分,第一部分称为宏定义即:

D[0-9]

 

就像C语言中的宏定义,在代码编译前要将宏进行替换,我们在转换前,也需要将正则表达式中的宏进行替换,也就是要将

{D} return ICON

({D} | {D}*.{D} | {D} .{D}*)(e{D} )

 

转换成:

{[0-9]} returnICON

([0-9] | [0-9]*.[0-9] | [0-9] .[0-9]*)(e[0-9] )

 

也就是把双括号D 换成[0-9]

宏定义的转换看似仅仅是简单的字符串替换,但它有一个难点是需要处理宏定义的间套情况,例如:

D[0-9]

A [a-z]

AD{D}|{A}

{AD}.{AD}

 

大家可以看到,宏定义AD 中,它自身的定义需要其他宏定义来组成(D和A),

替换了宏AD之后,还需要继续替换D 和A.也就是替换分成两部

1.由{AD}.{AD} 替换成( {D}|{A} ) . ( {D} | {A} )

2.由({D}|{A}) . ({D} | {A}) 替换成 ([0-9]|[a-z]).([0-9]|[a-z])

 

因此,在替换宏定义的时候,需要小心处理这种间套情况,间套甚至有可能会是很多层。

 

宏定义的组成方式如下:

 

名称 <一系列空格> 宏定义的内容 <一系列空格或换行>

 

因此,程序对宏定义的解析也根据上面的格式来入手, 宏定义的解析由类MacroHandler来处理:

图片 3

 

 

我们利用一个哈希表macroMap来存储所有宏定义,如果有两个宏的名字相同,那下一个宏将会覆盖上一个, 输入系统inputSystem,将从控制台获取宏定义的内容,然后调用newMacro函数对输入的内容进行解析(调出elipse).

图片 4

 

newMacro 函数通过解析从控制台读入的一行内容来构造宏定义,首先是先忽略掉空格和空行,直到遇到第一个有意义的字符才开始解析。从第一个字符开始,根据宏定义的格式,我们要构造的是宏定义的名称,将所有字符集合起来,直到遇到空格为止,所集合的字符构成的字符串就是宏定义的名称。

 

越过宏定义的名称后面的空格,遇到的有效内容就是宏定义的内容了,将他们收集起来,放入macroContent变量,然后以宏定义的名字为key, 放入到哈希表中。

 

当对正则表达式进行解析时,需要进行宏替换,也就是通过给定宏的名字,获取宏的内容,接口expandMacro 要实现的是获取宏的内容:

图片 5

 

 

正则表达式的文本替换:

在代码中,我们使用类RegularExpressionHandler来对正则表达式的输入进行替换,它的基本流程是,读入正则表达式文本,然后解析读入的内容,如果内容中有{}这一对符号时,程序确认需要进行宏替换,他将{}中的字符串提前出来作为宏定义的名字,通过上面提到的接口expandMacro获取宏定义的内容,用得到的内容进行替换,如果替换后还有宏定义,那么继续重复替换流程。该类的代码如下:

(调出eclipse)

图片 6

 

input是输入系统,用于获取正则表达式的输入,macroHandler是上面我们提到的宏定义处理器。该类将所有预处理后的正则表达式都存储在一个数组中,以备后面的程序使用。在一系列初始化完成后,调用processRegularExprs 开始执行正则表达式的预处理流程。

图片 7

 

preProcessExpr将输入的正则表达式逐字符读入,一旦遇到左括号{ 时,便准备开始进行宏替换,但如果左括号 { 是在双引号中,例如[“{}”] , 那么就将括号{当做普通字符处理,不进行替换,如果不是在双引号中,就进行宏替换。

 

它先将处于{ 和 } 中的字符串抽出来,作为宏定义的名字,抽取的过程通过接口extractMacroNameFromInput实现,拿到宏的名字后,调用expandMacro来进行替换操作。

图片 8

 

expandMacro 从macroHandler中获取宏定义的内容,由于宏定义可能会间套,因此获取内容后,还需要判断,宏定义中是否间套了其他宏定义,macroContent.indexOf(“{“} 就是用于判断宏定义是否间套,如果有间套,那么将{}中的内容抽取出来,再进行宏定义替换,替换完后再次检验是否还有间套,一直这么进行直到宏定义再无间套为止。

 

在判断宏定义时做了一些检查,如果遇到括号{, 但没有遇到对应的},那表明输入出错,同时将出错信息打印出来。

 

这节,我们只对代码进行了简单的介绍,下一节,我将以运行调试的方式,进一步给大家展现代码的流程,让大家能更好的理解代码。

 

本节目的是Thompson构造实现的第一步,输入文本预处理.本节的代码可以在云课...

Java 8 新特性:Lambda 表达式 ——诺诺"涂鸦"记忆

Struts2 数据展现

Struts2 数据展现

一、OGNL

什么是GONL?

Object Graph Navigation Language,是一门功能强大的表达式语言,类似于EL。
Struts2默认采用OGNL表达式访问Action的数据,通过ValueStack用封装后的OGNL来访问Action。
OGNL是独立的开源组件,Struts2对其进行了改造及封装,要想了解Struts2中OGNL的运行原理,需参考ValueStack。

Struts2显示标签

Struts2中,OGNL表达式要结合Struts2标签来访问数据,即OGNL表达式要写在Struts2标签内,因此我们先来介绍第一个Struts2的标签——显示标签。

该标签的作用是根据OGNL表达式访问Action,并将取出的数据替换标签本身。

2个常用的OGNL表达式和6个不常用的GONL表达式

OGNL表达式一共有8种使用方法,其中前2种是经常要用到的方式,后6种了解即可
1、访问基本属性
语法:
解释:这种方式的作用是将Action中的基本属性直接显示到标签的位置,属性名指的是Action中的属性。
举例:

2、访问实体对象
语法:
解释:这种方式的作用是将Action中的实体对象属性显示到标签的位置,对象名指的是Action中的实体对象,属性名指的是实体对象中的属性。
举例“

可以看出,这两种访问Action的方式实际上与EL表达式用法完全一致,是最常用的,也是最容易掌握的2种方式。

3、访问Action中的数组或集合的某元素,其中属性指的是Action中的数组或集合属性,index指的是数组或集合的下标。

4、访问Action中的Map类型的属性值,其中属性指的是Action中的Map类型属性,KEY指的是Map属性的key,通过key输出对应值。

5、在访问Action数据后,可以对OGNL表达式返回的结果直接进行计算,并将计算结果输出于标签位置。

6、访问Action数据后,可以直接调用OGNL表达式返回值的方法,并将最终的结果输出于标签位置。

7、不访问Action的数据,而是直接使用OGNL表达式创建一个临时的集合,并返回输出于标签位置。

8、不访问Action的数据,而是直接使用OGNL表达式创建一个临时的Map,并返回输出于标签位置

二、ValueStack

什么是ValueStack(值栈)?

ValueStack是Struts2中,Action向页面传递数据的媒介,ValueStack封装了Action的数据,并允许JSP通过OGNL来对其进行访问。
Struts2使用了ValueStack对OGNL组件进行了封装,其封装的实际上是改造后的OGNL,我们并不需要关注改造的过程,只需要掌握改造后的OGNL在ValueStack中的运行原理即可。
ValueStack中封装了OGNL解析引擎,用于解析传入的OGNL表达式,其目的就是在页面上以标签 字符串的方式访问Java对象,从而降低了页面代码的开发难度,提升了页面代码的维护效率。

图片 9

 

OGNL引擎可以访问2种类型的对象,一种是栈类型,另一种是Map类型。

1、栈

默认情况下,OGNL表达式访问栈,访问的规则是从栈顶向下依次以栈的每一级元素作为root对象来取值,直到取到值则返回,如果没有取到任何数据则返回null。
root对象就是JavaBean,只是在ValueStack中按照这种方式称呼而已。OGNL访问root对象,其写法是直接从root对象的属性写起,比如以某Action为root对象,访问Action中的user属性,那么OGNL表达式可以写为user.xxx

2、Map

如果OGNL表达式以“#”开头,那么OGNL引擎会访问Map类型的对象,此时OGNL表达式的写法为#key,返回的值为该key在Map中对应的值,这种对象通常我们称之为context对象。
context对象用于封装程序的上下文数据,包含request、session、page、application等。实际上,context对象封装的是完整的数据,也包含了action的数据。

访问ValueStack

ValueStack的原理是比较抽象的,对于其结构的理解也不够直观。对于这种情况,Struts2提供了一个调试标签,可以用于观察ValueStack的结构。

迭代集合

我们可以使用Struts2的迭代标签结合着OGNL,来迭代Action中的集合属性,迭代集合标签的语法如下:

users是OGNL表达式,自顶向下访问ValueStack栈中root对象的users属性,这里会从栈顶的Action对象取到该集合属性(List users)值 。

在迭代的过程中,ValueStack的栈顶会发生变化,循环变量User会被压入栈顶,此时Action被压到栈的第二位,即栈顶由原来的Action变为循环变量User。在循环时栈顶即为循环变量。

总结经验

ValueStack结构看似复杂,但是需要我们重点关注的无非是栈顶的变化,而此变化也仅仅是在循环时发生,因此记住这唯一的变化情况即可,即

1、默认情况下栈顶为Action。
2、循环过程中,栈顶为循环变量。
3、循环结束后,栈顶变回Action。

三、UI标签

UI标签的作用

UI标签有很多种用法,其核心功能是生成表单框体以及给框体赋默认值,因此常用于修改的功能,但不局限于修改。
为了方便大家理解,我们将UI标签分为:
1、简单的UI标签
2、复杂的UI标签

简单的UI标签

1、用于生成HTML的表单元素,其中theme用于指定主题,simple是简约主题,在生成时不会带有样式和表格。
2、该标记用于生成一个summit按钮。
3、首先它会生成一个文本框,其次它会根据OGNL表达式访问ValueStack取值,并将取到的结果设置为文本框的默认值。
4、密码框的作用完全与文本框一致,不同的是它生成了一个密码框。
5、文本域的作用完全与文本框一致,不同的是它生成了一个文本域。
6、生成一个checkbox,其次它会根据OGNL表达式访问valueStack取值,这里取的值要求是一个布尔类型,然后会根据返回的结果,来设置checkbox是否勾选,显然如果返回值为true则勾选,否则不勾选。
复杂的UI标签

一、单选框
listKey="cityCode" listValue="cityName"/>
1、根据OGNL表达式(cities)访问ValueStack,访问的属性应为集合(List),并根据返回结果生成一组单选框。集合中有几个值,就生成几个radio。期间,会根据listKey指定的实体(City)属性来生成radio的value值,根据listValue指定的实体(City)属性来生成radio的显示值label。
2、根据OGNL表达式(favoriteCity)访问ValueStack,并将返回的结果与radio的value值比较,哪个radio的value值返回结果一致,则该radio默认选中。

单选框使用总结

2种使用方式在第一步初始化选项时有所区别
第一种是初始化为一个固定的值
第二种方式初始化的是动态的值
而对于设置单选框的默认选中,2者完全一致

二、多选框

list="#{'01':'北京', '02':'上海', '03':'广州', '04':'深圳' }"/>
1、根据OGNL表达式创建的Map(#{'01':'北京', '02':'上海', '03':'广州', '04':'深圳' })生成一组多选框,Map中有几个键值对,就生成几个checkbox。其中Map的key用于生成checkbox的value值,Map的value用于生成checkbox 的label值。
2、根据OGNL表达式(travelCities)访问ValueStack,访问的属性为集合(List),并将返回的结果与checkbox的value值比较,哪个checkbox的value值在返回结果的集合中,则该checkbox 默认选中。
listKey="cityCode" listValue="cityName"/>
1、根据OGNL表达式(cities)访问ValueStack,访问的属性应为集合(List),并根据返回结果生成一组多选框。集合中有几个值,就生成几个checkbox。期间,会根据listKey指定的实体(City)属性来生成checkbox的value值,根据listValue指定的实体(City)属性来生成checkbox的显示值。
2、根据OGNL表达式(travelCities)访问ValueStack,访问的属性为集合(List),并将返回的结果与checkbox的value值比较,哪个checkbox的value值在返回结果的集合中,则该checkbox 默认选中。

三、下拉框

list="#{'01':'北京', '02':'上海', '03':'广州', '04':'深圳' }"/>

1、根据OGNL表达式创建的Map(#{'01':'北京', '02':'上海', '03':'广州', '04':'深圳' })生成一组多选框,Map中有几个键值对,就生成几个checkbox。其中Map的key用于生成checkbox的value值,Map的value用于生成checkbox 的label显示值。
2、根据OGNL表达式(home)访问ValueStack,访问的属性为集合(List),并将返回的结果与checkbox的value值比较,哪个checkbox的value值在返回结果的集合中,则该checkbox默认选中。

listKey="cityCode" listValue="cityName"/>
1、根据OGNL表达式(cities)访问ValueStack,访问的属性应为集合(List),并根据返回结果生成一组下拉选。集合中有几个值,就生成几个option。期间,会根据listKey指定的实体(City)属性来生成option的value值,根据listValue指定的实体(City)属性来生成option的显示值。
2、根据OGNL表达式(home)访问ValueStack,并将返回的结果与option的value值比较,哪个option的value值与返回结果一致,则该option默认选中。

 

数据展现 Struts2 数据展现 一、OGNL 什么是GONL? Object Graph Navigation Language,是一门功能强大的表达式语言,类似于EL。 Struts2默认采用...

1,Excel的两种格式区别

a),*.xls文件是使用Microsoft Excel 2003或之前版本保存的电子表格,使用的存储格式为BIFF (Binary Interchange File Format),一种特殊的二进制格式文件。 b)*.xlsx文件是使用Microsoft Office 2007 或后续版本保存的电子表格,使用的存储格式为OOXML(Office Open XML),一种压缩过的格式(通过十六进制编辑器UltraEdit可以看到其文件头为#504B0304)   关于*.xls与*.xlsx的更多区别可参考(*_翻_墙_):   #说明:-03为2003版本或之前,07 为2007版本或后续  

Lambda 表达式

 

(注:此文乃个人查找资料然后学习总结的,若有不对的地方,请大家指出,非常感谢!另外,知识都有串联,如果某一处看不懂,就先接着往下看,之后再回头看不明白的地方就会恍然大悟了。)

 

2,使用POI新建Excel

  a),新建工作簿:

//-03
Workbook wb = new HSSFWorkbook();
FileOutputStream fileOut = new FileOutputStream("workbook.xls");
wb.write(fileOut);
fileOut.close();
//07 
Workbook wb = new XSSFWorkbook();
FileOutputStream fileOut = new FileOutputStream("workbook.xlsx");
wb.write(fileOut);
fileOut.close();

 

  b),新建表

Workbook wb = new HSSFWorkbook(); // or new XSSFWorkbook();
Sheet sheet1 = wb.createSheet("new sheet");
Sheet sheet2 = wb.createSheet("second sheet");

//WorkbookUtil类可以检查你的表名是否合法
String safeName = WorkbookUtil.createSafeSheetName("[O'Brien's sales*?]"); 
Sheet sheet3 = wb.createSheet(safeName);

FileOutputStream fileOut = new FileOutputStream("workbook.xls");
wb.write(fileOut);
fileOut.close();

 

  c),新建单元格

Workbook wb = new HSSFWorkbook();
//Workbook wb = new XSSFWorkbook();
CreationHelper createHelper = wb.getCreationHelper();
Sheet sheet = wb.createSheet("new sheet");

//在表格第一行新建一行(注意其索引从0开始)
Row row = sheet.createRow((short)0);
//在第一行的第一列新建单元格,并设置其内容为1(注意其索引从0开始)
Cell cell = row.createCell(0);
cell.setCellValue(1);

//另一种更简洁的创建方式
row.createCell(1).setCellValue(1.2);
row.createCell(2).setCellValue(
createHelper.createRichTextString("This is a string"));
row.createCell(3).setCellValue(true);

//将表格输出到文件
FileOutputStream fileOut = new FileOutputStream("workbook.xls");
wb.write(fileOut);
fileOut.close();

 

一.为什么Java需要Lambda表达式?

 

如果忽视注解(Annotations)、泛型(Generics)等特性,自Java语言诞生时起,它的变化并不大。Java一直都致力维护其对象至上的特征,在使用过JavaScript之类的函数式语言之后,Java如何强调其面向对象的本质,以及源码层的数据类型如何严格变得更加清晰可感。其实,函数对Java而言并不重要,在Java的世界里,函数无法独立存在。

 

然而,在函数式编程语言中,函数是一等公民,它们可以独立存在,你可以将其赋值给一个变量,或将他们当做参数传给其他函数。JavaScript是最典型的函数式编程语言。函数式语言提供了一种强大的功能——闭包,相比于传统的编程方法有很多优势,闭包是一个可调用的对象,它记录了一些信息,这些信息来自于创建它的作用域。Java现在提供的最接近闭包的概念便是Lambda表达式,虽然闭包与Lambda表达式之间存在显著差别,但至少Lambda表达式是闭包很好的替代者。

 

Lambda表达式为Java添加了缺失的函数式编程特点,使我们能将函数当做一等公民看待。尽管不完全正确,我们很快就会见识到Lambda与闭包的不同之处,但是又无限地接近闭包。在支持一类函数的语言中,Lambda表达式的类型将是函数。但是,在Java中,Lambda表达式是对象,他们必须依附于一类特别的对象类型——函数式接口(functional interface)。

 

本文由小鱼儿玄机30码发布于编程,转载请注明出处:若有不对的地方,也需要将正则表达式中的宏进

关键词: 小鱼儿玄机30码