小说章节解析 language-Java
2014-05-10 10:07
417 查看
按照需求自己研究了一下能够解析小说中的章节的算法
package parse;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
public class ChapterParse {
/** 一级匹配表达式 */
private static String[] regexs = {
"第[零一二三四五六七八九十百千]{1,7}[章集回卷篇][::]?.*",
"第\\d{1,7}[章集回卷篇][::]?.*",
"[零一二三四五六七八九十百千]{1,7}.*",
"\\d{1,7}.*",
".* +第[零一二三四五六七八九十百千]{1,7}[章集回卷篇][::]?.*",
".* +第\\d{1,7}[章集回卷篇][::]?.*"
};
/** 二级匹配表达式 */
private static String[] regexs2 = {
"[零一二三四五六七八九十百千]{1,7}",
"[^,。“”…?;—-]{1,10}"
};
/**
* 解析章节
* @param txtFileName TXT文件名
* @return 章节列表
*/
public static List<String> parse(String txtFileName){
List<String> chapters = new ArrayList<String>();
try {
FileInputStream fis = new FileInputStream(txtFileName);
InputStreamReader isr = new InputStreamReader(fis,"UTF-8");
BufferedReader bufferReader = new BufferedReader(isr);
int lines = 240;//缓存到集合中的行数
int lineNum = 0;//记录已经尝试匹配的行数
boolean isFind = false;//标记是否找到章节
String regex = null;//找到的正则表达式
String oldLine = "";//读取的上一行文本 用于去除重复
//用于存储被筛选后的行文本
List<String> bufferLines = new ArrayList<String>();
while(bufferReader.ready()){
String txtLine = bufferReader.readLine().trim();
if(txtLine.length()>27&&txtLine.length()<72){
if(txtLine.matches(".*\\[.*\\]")){
txtLine = txtLine.substring(0, txtLine.lastIndexOf("["));
}
}
if(txtLine.length()>27||txtLine.equals("")||txtLine.replaceAll(" ", "").equals(oldLine.replaceAll(" ", ""))){
continue;
}
oldLine = txtLine;
//如果还没找到就继续找
if(isFind==false){
//如果读取的行数小于240行
if(lineNum<lines){
bufferLines.add(txtLine);
//用所有定义好的一级正则表达式尝试去匹配
for (int i = 0; i < regexs.length; i++) {
if(txtLine.matches(regexs[i])){
isFind = true;
regex = regexs[i];
chapters.add(txtLine);
break;
}
}
}else if(lineNum == lines){
//如果前面仍未找到采取二级匹配表达式
for (int i = 0; i < bufferLines.size(); i++) {
if(isFind){
if(bufferLines.get(i).matches(regex)){
chapters.add(bufferLines.get(i));
}
}else{
for (int j = 0; j < regexs2.length; j++) {
if(bufferLines.get(i).matches(regexs2[j])){
isFind = true;
regex = regexs2[j];
chapters.add(bufferLines.get(j));
break;
}
}
}
}
}
}else{
bufferLines = null;//释放
//如果已经找到能够识别的章节
//用识别出该章节的正则表达式进行匹配
if(txtLine.matches(regex)){
chapters.add(txtLine);
}
}
lineNum++;
}
bufferReader.close();
} catch (Exception e) {
System.err.println("出错:"+e.getMessage());
}
return chapters;
}
}
具体思路:逐行读取文本,用所有预定义的一级正则表达式尝试与每行文本(在匹配之前是经过筛选的)进行匹配。如果发现有个表达式匹配了一行文本,则认定此行为章节文本并添加到发现的章节集合中,此时将与该行进行匹配的表达式保存,标记已经找到合适的正则表达式,读取到下一行文本时,用已保存的表达式直接进行匹配,若匹配成功就添加至章节集合。如果遍历240-1行从一级表达式中没有任何的匹配记录,就使用二级表达式重新从这240-1行里(使用BufferedReader不方便从头重新读取,就把筛选后的文本存入了集合,不清楚就看代码 )进行匹配,方式与上述雷同。
package parse;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
public class ChapterParse {
/** 一级匹配表达式 */
private static String[] regexs = {
"第[零一二三四五六七八九十百千]{1,7}[章集回卷篇][::]?.*",
"第\\d{1,7}[章集回卷篇][::]?.*",
"[零一二三四五六七八九十百千]{1,7}.*",
"\\d{1,7}.*",
".* +第[零一二三四五六七八九十百千]{1,7}[章集回卷篇][::]?.*",
".* +第\\d{1,7}[章集回卷篇][::]?.*"
};
/** 二级匹配表达式 */
private static String[] regexs2 = {
"[零一二三四五六七八九十百千]{1,7}",
"[^,。“”…?;—-]{1,10}"
};
/**
* 解析章节
* @param txtFileName TXT文件名
* @return 章节列表
*/
public static List<String> parse(String txtFileName){
List<String> chapters = new ArrayList<String>();
try {
FileInputStream fis = new FileInputStream(txtFileName);
InputStreamReader isr = new InputStreamReader(fis,"UTF-8");
BufferedReader bufferReader = new BufferedReader(isr);
int lines = 240;//缓存到集合中的行数
int lineNum = 0;//记录已经尝试匹配的行数
boolean isFind = false;//标记是否找到章节
String regex = null;//找到的正则表达式
String oldLine = "";//读取的上一行文本 用于去除重复
//用于存储被筛选后的行文本
List<String> bufferLines = new ArrayList<String>();
while(bufferReader.ready()){
String txtLine = bufferReader.readLine().trim();
if(txtLine.length()>27&&txtLine.length()<72){
if(txtLine.matches(".*\\[.*\\]")){
txtLine = txtLine.substring(0, txtLine.lastIndexOf("["));
}
}
if(txtLine.length()>27||txtLine.equals("")||txtLine.replaceAll(" ", "").equals(oldLine.replaceAll(" ", ""))){
continue;
}
oldLine = txtLine;
//如果还没找到就继续找
if(isFind==false){
//如果读取的行数小于240行
if(lineNum<lines){
bufferLines.add(txtLine);
//用所有定义好的一级正则表达式尝试去匹配
for (int i = 0; i < regexs.length; i++) {
if(txtLine.matches(regexs[i])){
isFind = true;
regex = regexs[i];
chapters.add(txtLine);
break;
}
}
}else if(lineNum == lines){
//如果前面仍未找到采取二级匹配表达式
for (int i = 0; i < bufferLines.size(); i++) {
if(isFind){
if(bufferLines.get(i).matches(regex)){
chapters.add(bufferLines.get(i));
}
}else{
for (int j = 0; j < regexs2.length; j++) {
if(bufferLines.get(i).matches(regexs2[j])){
isFind = true;
regex = regexs2[j];
chapters.add(bufferLines.get(j));
break;
}
}
}
}
}
}else{
bufferLines = null;//释放
//如果已经找到能够识别的章节
//用识别出该章节的正则表达式进行匹配
if(txtLine.matches(regex)){
chapters.add(txtLine);
}
}
lineNum++;
}
bufferReader.close();
} catch (Exception e) {
System.err.println("出错:"+e.getMessage());
}
return chapters;
}
}
具体思路:逐行读取文本,用所有预定义的一级正则表达式尝试与每行文本(在匹配之前是经过筛选的)进行匹配。如果发现有个表达式匹配了一行文本,则认定此行为章节文本并添加到发现的章节集合中,此时将与该行进行匹配的表达式保存,标记已经找到合适的正则表达式,读取到下一行文本时,用已保存的表达式直接进行匹配,若匹配成功就添加至章节集合。如果遍历240-1行从一级表达式中没有任何的匹配记录,就使用二级表达式重新从这240-1行里(使用BufferedReader不方便从头重新读取,就把筛选后的文本存入了集合,不清楚就看代码 )进行匹配,方式与上述雷同。
相关文章推荐
- java堆栈信息打印
- java中的class对象
- spring框架整合使用定时任务框架java quartz的示例代码配置
- Java笔试题解析(一)
- windows eclipse运行mapreduce遇到权限问题该如何解决
- java 求First集和Follow集
- java策略设计模式
- 青蛙跳台阶解法 时间复杂度O(n) 空间复杂度O(1)
- Java中x+=y和x=x+y两种实现的区别
- java:打包
- Java中获取系统属性
- Myeclipse导入不了自己建的包
- java的url有中文参数导致乱码
- POJ-蚂蚁行军问题 1852
- Graphics
- java内存泄漏常见情况
- Java对象的强、软、弱和虚引用
- Java数组定义的方法
- Heritrix在eclipse中的配置过程(1.14.4版本)
- 修改eclipse背景颜色