在这里记录一下关于软件构造课程Lab3中关于正则表达式的应用。

  在实验内容中,要求用正则表达式来匹配读入文件的内容,从而取得构建图需要的相关信息。

  举个例子,读入的文件(GraphPoetTestFile.txt)内容如下:

  先说一下文件内容中的数据格式:

  ①一定有一行,第一个单词为"GraphType",后面是一个空格、一个'='、一个空格,加上一个"类型名"

  ②一定有一行,第一个单词为"GraphName",后面是一个空格、一个'='、一个空格,加上一个"图的名字"

  ③一定有一行,第一个单词为"VertexType"/"EdgeType",后面是一个空格、一个'='、一个空格,加上若干个"顶点类型",不同顶点类型之间用','和空格隔开

  ④一定有若干行,第一个单词为"Vertex",后面是一个空格,一个'='、一个空格、一个左尖括号'<',加上若干个"数据信息",最后用右尖括号'>'结束(中间可能仍有尖括号来界定属性信息)

  ⑤一定有若干行,第一个单词为"Edge",后面是一个空格,一个'='、一个空格、一个左尖括号'<',加上若干个"数据信息",信息项之间用','和空格隔开,最后用右尖括号'>'结束

  ⑥可能存在若干行,第一个单词为"HyperEdge",后面是一个空格,一个'='、一个空格、一个左尖括号'<',加上若干个"数据信息",信息项之间用','和空格隔开,包含一组大括号'{''}'来界定的属性信息,最后用右尖括号'>'结束

  下面说一下对于这个问题而言,我的解决思路:

  首先,分析读入文件的格式,每一行读入引号中的数据项个数可能不一致,有的行只包含一项,有的行却包含多项,因此没有一种完美的正则表达式能直接全部读取所有引号的数据项。同时,考虑到还有尖括号'<>'以及大括号'{}'来界定的情况,这种直接构建完整正则表达式进行匹配的方式似乎不存在或者说使用情况比较复杂。

  先说明两种基本的匹配字符串的方式,一种是最大化地进行匹配字符串,一种是最小化地进行匹配字符串。

  比如,对于一个字符串/Introduction = "I", "Am", "Steven", "Shen"/(这里用'/'来表示字符串界定符以避免产生歧义),最大化地进行匹配的话,我要得到的就是引号区间界定的整个字符串匹配,即/"I", "Am", "Steven", "Shen"/;最小化地进行匹配的话,我要得到的就是引号区间界定的一小部分字符串匹配,即/I/,再次重复进行匹配就会依次得到/Am/、/Steven/、/Shen/。这两种正则表达式在Java中的具体字符串表示格式就是max = "(\".+\")",min = "\"([^\"]+)\""。

  下面回到问题上来,我的解决思路有两种:

  第一种方式,通过max和min的使用,细致化地获取数据

  对每一行先进行这样的匹配String pattern1 = "(\\w+) = (\".+\")"; 即每行先是一个单词,一个空格,一个'=',一个空格,后加一个max型的匹配,得到'='后所有信息项。匹配上面的那个文件,第一行匹配结果就是/GraphType/、/"MovieGraph"/,第三行匹配结果就是/VertexType/、/"Movie", "Actor", "Director"/。此时,我们判断第一个读入的单词的内容,即可确定该如何处理'='后面的信息项。此时再对第二个获取的串(通过max匹配得到的串)进行最小化地匹配,第一行就得到了/MovieGraph/,第三行就得到了/Movie/、/Actor/、/Director/三个项。类似地,把界定范围改成尖括号内的内容,同样也可以获取Vertex以及Edge的信息。

  这种解决方式总的思路就是通过匹配每行第一个单词来确定如何处理这行数据'='后的数据项。然后通过最大化地匹配'='后的数据,进一步对其用最小化匹配进行划分,得到具体的数据项。

  第二种方式,通过max的使用,结合对字符串的操作达成目标

  类似于上面说的,得到每行第一个单词后,用最大化匹配来得到'='后的数据项,此时匹配的内容就是/"I", "Am", "Steven", "Shen"/,然后对这个字符串使用String的split方法(当然,split的参数列表实际上接收的就是一个正则表达式的字符串)。这里的split方法就是这样split(",\\s")。这样,/"I", "Am", "Steven", "Shen"/就变成了/"I"/、/"Am"/、/"Steven"/、/"Shen"/,他们存储在一个String数组中,这时还要数组中每个串求子串,从而去掉每个串两端的引号(")。即通过String的subString方法,得到/I/、/Am/、/Steven/、/Shen/。

  这种解决方式总的思路就是先获取要读取的数据块,在对数据块用String的操作来完成每个需要读取的数据项。这种方式相比于前面那种比较麻烦,原因在于求子串、分割过程比较繁琐,不如上面那种方法的用最小化匹配方便快捷。

  这两种方法的正则表达式匹配串并获取,都用到了group方法,这些内容在Java的String和正则表达式部分都有详细介绍,这里就不再赘述了。

  至于文件中可能存在的匹配不同界定符的情况,可以类似地考虑如何实现。主要思路就在上面,具体实现时可以通过每行数据项的个数等确定性信息来进行信息读取,使得处理更灵活。

  下面附上针对这种MovieGraph的处理代码。  

 package factory;

 import java.util.*;
import java.util.regex.*;
import java.io.*;
import vertex.*;
import edge.*;
import graph.*; public class MovieGraphFactory {
public static MovieGraph createGraph(String filePath) {
String GraphType = "";
String GraphName = "";
String VertexType = "";
List<String> VertexTypes = new ArrayList<>();
String EdgeType = "";
List<String> EdgeTypes = new ArrayList<>();
Set<String> fullVertexInfo = new HashSet<>();
Set<String> fullEdgeInfo = new HashSet<>();
Set<String> fullHyperEdgeInfo = new HashSet<>();
List<Vertex> vertexList = new ArrayList<>();
List<Edge> edgeList = new ArrayList<>();
List<Edge> hyperList = new ArrayList<>();
String pattern1 = "(\\w+) = (\".+\")";
String pattern2 = "(\\w+) = <(.+)>";
String pattern3 = ",? ?\"([^\"]+)\"";
Pattern p = Pattern.compile(pattern1);
Matcher parse1 = p.matcher("");
p = Pattern.compile(pattern2);
Matcher parse2 = p.matcher("");
MovieGraph graph = null;
try {
File file = new File(filePath);
InputStreamReader readin = new InputStreamReader(new FileInputStream(file));
BufferedReader bufReadin = new BufferedReader(readin);
String line;
int i = 1;
while((line = bufReadin.readLine()) != null) {
parse1.reset(line);
parse2.reset(line);
if(parse1.find()) {
if(parse1.groupCount() == 2) {
if(parse1.group(1).equals("GraphType")) {
GraphType = parse1.group(2);
if(!GraphType.equals("\"MovieGraph\"")) {
System.out.println("Error! the graph must be MovieGraph rather be " + GraphType);
bufReadin.close();
throw new RuntimeException();
}
}
if(parse1.group(1).equals("GraphName"))
GraphName = parse1.group(2);
if(parse1.group(1).equals("VertexType"))
VertexType = parse1.group(2);
if(parse1.group(1).equals("EdgeType"))
EdgeType = parse1.group(2);
}
} else if(parse2.find()) {
if(parse2.groupCount() == 2) {
if(parse2.group(1).equals("Vertex"))
fullVertexInfo.add(parse2.group(2));
if(parse2.group(1).equals("Edge"))
fullEdgeInfo.add(parse2.group(2));
if(parse2.group(1).equals("HyperEdge"))
fullHyperEdgeInfo.add(parse2.group(2));
}
}
}
p = Pattern.compile(pattern3);
Matcher parse3 = p.matcher(GraphType);
if(parse3.find())
GraphType = parse3.group(1);
parse3 = p.matcher(GraphName);
if(parse3.find())
GraphName = parse3.group(1);
parse3 = p.matcher(VertexType);
while(parse3.find()) {
VertexTypes.add(parse3.group(1));
}
parse3 = p.matcher(EdgeType);
while(parse3.find()) {
EdgeTypes.add(parse3.group(1));
} String label = "", type = "";
String[] fields = null; for(String temp : fullVertexInfo) {
i = 0;
Vertex point = null;
parse3 = p.matcher(temp);
if(parse3.find())
label = parse3.group(1);
if(parse3.find()) {
type = parse3.group(1);
}
switch(type) {
case "Actor" :
fields = new String[2];
break;
case "Director" :
fields = new String[2];
break;
case "Movie" :
fields = new String[3];
break;
default :
System.out.println("Error. The graph can't contain other vertex " + type);
bufReadin.close();
throw new RuntimeException();
}
while(parse3.find()) {
fields[i++] = parse3.group(1);
}
switch(type) {
case "Actor" :
point = ActorVertexFactory.createVertex(label, fields);
break;
case "Director" :
point = DirectorVertexFactory.createVertex(label, fields);
break;
case "Movie" :
point = MovieVertexFactory.createVertex(label, fields);
break;
default :
break;
}
vertexList.add(point);
} for(String temp : fullEdgeInfo) {
parse3 = p.matcher(temp);
Double weight = 0.0;
Vertex point1 = null, point2 = null;
Edge edge = null;
if(parse3.find())
label = parse3.group(1);
if(parse3.find())
type = parse3.group(1);
if(parse3.find())
weight = Double.parseDouble(parse3.group(1));
if(parse3.find())
for(Vertex start : vertexList) {
if(parse3.group(1).equals(start.getLabel())) {
point1 = start;
break;
}
}
if(parse3.find())
for(Vertex end : vertexList) {
if(parse3.group(1).equals(end.getLabel())) {
point2 = end;
break;
}
}
if(parse3.find())
if(!parse3.group(1).equals("No")) {
bufReadin.close();
throw new RuntimeException();
}
List<Vertex> arg = new ArrayList<>();
arg.add(point1); arg.add(point2);
switch(type) {
case "MovieActorRelation" :
edge = MovieActorRelationFactory.createEdge(label, arg, weight);
break;
case "MovieDirectorRelation" :
edge = MovieDirectorRelationFactory.createEdge(label, arg, -1.0);
break;
default :
System.out.println("Error, the graph can't contain other edge " + type);
bufReadin.close();
throw new RuntimeException();
}
edgeList.add(edge);
} for(String temp : fullHyperEdgeInfo) {
parse3 = p.matcher(temp);
Edge hyper = null;
if(parse3.find()) {
label = parse3.group(1);
}
if(parse3.find())
type = parse3.group(1);
List<Vertex> hyperVertices = new ArrayList<>();
while(parse3.find()) {
for(Vertex temppoint : vertexList) {
if(parse3.group(1).equals(temppoint.getLabel())) {
hyperVertices.add(temppoint);
break;
}
}
}
hyper = SameMovieHyperEdgeFactory.createEdge(label, hyperVertices, -1.0);
hyperList.add(hyper);
} graph = new MovieGraph(GraphName);
for(Vertex temp : vertexList) {
graph.addVertex(temp);
}
for(Edge temp : edgeList) {
graph.addEdge(temp);
}
for(Edge temp : hyperList) {
graph.addEdge(temp);
} System.out.println("***** vertexList's length : " + vertexList.size());
System.out.println("***** edgeList's length : " + edgeList.size());
System.out.println("***** hyperList's length : " + hyperList.size());
System.out.println("Vertex:" + fullVertexInfo.size()+ "\n" + fullVertexInfo + "\n" + "Edge:" + fullEdgeInfo.size() + "\n" + fullEdgeInfo + "\n" + "HyperEdge:" + fullHyperEdgeInfo.size() + "\n" + fullHyperEdgeInfo);
bufReadin.close();
} catch(Exception e) {
e.printStackTrace();
}
return graph;
}
}

MovieGraphFactory.java

  思路比较简单,事实证明可行。代码写得不高端...

  见证菜鸡成长...

  

最新文章

  1. Servlet-RequestDispatcher.forward方法
  2. div加边框
  3. DataTable/Array Linq查询,groupby
  4. NoSql存储日志数据之Spring+Logback+Hbase深度集成
  5. 注销CA登录
  6. Struts标签、Ognl表达式、el表达式、jstl标签库这四者之间的关系和各自作用
  7. shell编程的一些例子4
  8. 通过ip获取地理位置信息
  9. 课程作业02(关于Java的几点讨论)
  10. 如何连接别人电脑上的Oracle数据库--duende99
  11. async/await使用深入详解
  12. 阿里云各Linux发行版netcore兼容性评估报告---来自大石头的测试
  13. Spark入门到精通--(第七节)环境搭建(服务器搭建)
  14. Spark操作HBase报:org.apache.hadoop.hbase.client.RetriesExhaustedWithDetailsException异常解决方案
  15. HostPort和NodePort
  16. MVC中页面的传值方式总结
  17. msf辅助模块的应用
  18. 一张图让你学会Python
  19. Oracle直方图的详细解析(转)
  20. [POJ2625][UVA10288]Coupons

热门文章

  1. cmd添加管理员账号
  2. np.multiply
  3. 增加phpmyadmin导入文件上限
  4. 使用python爬取天气预报,[python入门案例]
  5. C#开发点滴记录
  6. 高级T-SQL进阶系列 (一)【上篇】:使用 CROSS JOIN 介绍高级T-SQL
  7. java判断字符串是否是数字
  8. Docker for windows修改默认镜像文件位置
  9. 计算机基础,Python - 回调函数,使用装饰器注册回调函数
  10. 对于使用javaweb技术制作简单管理系统的学习