首先感谢下这位博主的分享,本文是在这篇博文的基础上加上了自己的逻辑,原文请点击这里←
------------------------------------------------------------------------------------------------------------------------------
下面来说下具体的实现步骤(前端使用的是layui):
HTML端:
<div class="layui-form-item">
<label class="layui-form-label">小说附件<span style="color: red;">*</span></label>
<div class="layui-upload-list">
<button type="button" class="layui-btn" id="upload" >上传文件</button>
<label class="set-item-label" id="txtName"></label>
</div>
</div>
<div class="layui-form-item text-right">
<button class="layui-btn layui-btn-primary" type="button" ew-event="closeChapter">取消</button>
<button class="layui-btn" lay-filter="btnSubmit" id="btnSubmit" lay-submit>保存</button>
</div>
JS端 上传txt文件:
// 上传txt文件
var uploadInst = upload.render({
elem: '#upload', //绑定元素
url: '/book_content/upload/', //上传接口
accept:'file',
before: function(obj){
//预读本地文件示例,不支持ie8
obj.preview(function(index, file, result){
document.getElementById('txtName').innerHTML = file.name;
});
},
done: function(res){
$("#txtPath").val(res.pictureName);
//如果上传失败
if(res.code > 0){
return layer.msg('上传失败');
}
//上传完毕回调
},
error: function(){
return layer.msg('上传失败');
}
});
JS端 导入txt文件:
// 导入txt文件
form.on('submit(btnSubmit)', function (data) {
var ajax = new $ax("/book_content/importTxt", function (data) {
layer.alert("导入成功!");
// 传给上个页面,刷新table用
admin.putTempData('formOk', true);
// 关掉对话框
admin.closeThisDialog();
}, function (data) {
layer.alert("导入失败!" + data.responseJSON.message);
});
ajax.set(data.field);
ajax.set("contBid",contBid); // 小说ID
ajax.set("regX",$('#regX').val()); // 输入的章节标题格式
ajax.set("txtPath",$('#txtPath').val()); // 上传后的章节txt路径
ajax.start();
});
下面重点来了:
Java 导入工具类:
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ImportTxtUtil {
int idx;
Connection conn = null;
PreparedStatement pstmt = null;
PreparedStatement pstmt1 = null;
public Map<String,String> readTxtFile(String contBid,String contdb, String regX, String txtPath, String source) {
//存放内容的map对象
Map<String,String> filemaps = new HashMap<String,String>();
try {
// 本地环境路径
String str1 = "C:\\Users\\Administrator\\AppData\\Local\\Temp\\";
// 设定文件编码格式
String encoding = "UTF-8";
File file = new File(str1 + txtPath);
// 启动数据库
dbConnection();
int count = 1;//定义章节顺序变量
if (file.isFile() && file.exists()) { // 判断文件是否存在
InputStreamReader read = new InputStreamReader(
new FileInputStream(file),encoding);// 考虑到编码格式
BufferedReader bufferedReader = new BufferedReader(read);
String lineTxt = null;
String content = "";
while ((lineTxt = bufferedReader.readLine()) != null) {//按行读取
if(!"".equals(lineTxt) ){
String reds = lineTxt.split("\\\\+")[0];//对行的内容进行分析处理后再放入map里。
/* 正则表达式处理标题名称 */
Pattern p = null;
Matcher mReds = null;
switch(regX){ // 根据正则表达式匹配章节标题
case "第N章":
p = Pattern.compile("第[\\u4e00-\\u9fa5\\u767e\\u5343\\u96f6]{1,10}章");
mReds = p.matcher(reds);
break;
case "第n章":
p = Pattern.compile("第-?[0-9]\\d*章");
mReds = p.matcher(reds);
break;
case "正文 第N章":
p = Pattern.compile("正文 第[\\u4e00-\\u9fa5\\u767e\\u5343\\u96f6]{1,10}章");
mReds = p.matcher(reds);
break;
case "正文 第n章":
p = Pattern.compile("正文 第-?[0-9]\\d*章");
mReds = p.matcher(reds);
break;
case "第n卷":
p = Pattern.compile("第-?[0-9]\\d*卷");
mReds = p.matcher(reds);
break;
case "第N卷":
p = Pattern.compile("第[\\u4e00-\\u9fa5\\u767e\\u5343\\u96f6]{1,10}卷");
mReds = p.matcher(reds);
break;
case "卷N":
p = Pattern.compile("卷-?[0-9]\\d*");
mReds = p.matcher(reds);
break;
case "卷n":
p = Pattern.compile("卷-?[0-9]\\d*");
mReds = p.matcher(reds);
break;
case "第N幕":
p = Pattern.compile("第[\\u4e00-\\u9fa5\\u767e\\u5343\\u96f6]{1,10}幕");
mReds = p.matcher(reds);
break;
}
if( mReds.find() ){ // 部分匹配,如果匹配成功说明本行是标题,进行标题行处理逻辑
// 1> 先将上次循环存入的章节内容信息存入数据库操作
if(filemaps.size() > 0){ // 如果filemaps不为空,则将map中的值提交到数据库
System.out.println(filemaps.get("cont_chapter"));
insertCustInfo(filemaps); // 数据库存入操作
Thread.sleep(10);
filemaps.clear(); // 清空filemaps
content = ""; // 初始化content
}
filemaps.put("cont_chapter",reds); // put 标题内容
filemaps.put("cont_index",count++ +""); // put 章节顺序值
filemaps.put("cont_bid",contBid); // put 小说ID
filemaps.put("contdb",contdb); // put 章节所属分表内容
filemaps.put("source",source); // put 章节内容来源
}else{ // 未被正则匹配到的,说明是章节内容,进行章节处理逻辑
if(StringUtils.isNullOrEmpty(content)){ // 校验 content 是否是章节内容的第一行
content = reds.replaceAll(" ","") + "\n\t"; // 后缀加入"\n\t",是为了给移动端添加章节段落换行等样式
}else{
content = content + (reds.replaceAll(" ","") + "\n\t"); // 后缀加入 "\n\t",是为了给移动端添加章节段落换行等样式
}
filemaps.put("cont_content", content);//放入map
}
}
}
// 数据读取完之后,对 filemaps 进行校验,如果不为空则提交到数据库。
if(filemaps.size() > 0){
System.out.println(filemaps.get("cont_chapter"));
insertCustInfo(filemaps);
}
read.close();//关闭InputStreamReader
bufferedReader.close();//关闭BufferedReader
} else {
System.out.println("找不到指定的文件");
}
} catch (Exception e) {
System.out.println("读取文件内容出错");
e.printStackTrace();
}
return filemaps;
}
// 插入到数据库中
public void insertCustInfo(Map<String,String> filemaps) {
try {
// 生成UUID
String contId = UUID.randomUUID().toString().replaceAll("-", "");
StringBuffer sqlBf = new StringBuffer();
sqlBf.setLength(0);
sqlBf.append("INSERT INTO txt_db (cont_id, cont_bid, cont_oid,cont_chapter,cont_content,cont_index,cont_source) \n");
sqlBf.append(" VALUES(? ");
sqlBf.append(" , ? ");
sqlBf.append(" , ? ");
sqlBf.append(" , ? ");
sqlBf.append(" , ? ");
sqlBf.append(" , ? ");
sqlBf.append(" , ?) ");
pstmt = conn.prepareStatement(sqlBf.toString());
idx = 1;
pstmt.clearParameters();
pstmt.setString(idx++, contId);
pstmt.setString(idx++, filemaps.get("cont_bid"));
pstmt.setString(idx++, filemaps.get("cont_bid"));
pstmt.setString(idx++, filemaps.get("cont_chapter"));
pstmt.setString(idx++, filemaps.get("cont_content"));
pstmt.setString(idx++, filemaps.get("cont_index"));
pstmt.setString(idx++, filemaps.get("source"));
pstmt.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (pstmt != null) {
try {
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
// 连接数据库
public Connection dbConnection() {
try {
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/testDB";
String user = "root";
String password = "root";
conn = DriverManager.getConnection(url, user, password);
System.out.println("Connection 开启!");
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
// 关闭数据库
public void dbDisConnection() {
if (conn != null) {
try {
conn.close();
System.out.println("Connection 关闭!");
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
结合网上的资料自己整理的一套关于导入小说Txt文件并按照 章节名+章节段落 存储到数据库的功能,希望能帮助有需求的朋友。