您的位置:首页 > 编程语言 > Java开发

小说章节解析 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不方便从头重新读取,就把筛选后的文本存入了集合,不清楚就看代码 )进行匹配,方式与上述雷同。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: