完成文本处理以及文本文件读取工具类的改造

This commit is contained in:
彭宇琦 2021-02-02 08:03:15 +08:00
parent 29c14a3abc
commit c4adc67170
3 changed files with 221 additions and 470 deletions

View File

@ -0,0 +1,146 @@
package com.auxiliary.tool.data;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Optional;
/**
* <p>
* <b>文件名</b>DisposeText.java
* </p>
* <p>
* <b>用途</b>用于对文件中的文本进行处理以简化日常工作中对文本的内容的测试
* </p>
* <p>
* <b>编码时间</b>2019年7月4日 07:08
* </p>
* <p>
* <b>修改时间</b>2019年7月11日 09:12
* </p>
*
* @author 彭宇琦
* @version Ver1.0
* @since JDK 1.8
*/
public class DisposeText {
/**
* 用于将两个词语集合进行比较并返回待测集合不在目标集合中的元素
*
* @param testList 待测试集合
* @param targetList 目标集合
* @return 待测集合不在目标集合中的元素
* @throws IllegalDataException 未指定集合时抛出的异常
*/
public static List<String> compareFileWord(List<String> testList, List<String> targetList) {
// 判断是否传入集合
Optional.ofNullable(testList).filter(list -> !list.isEmpty())
.orElseThrow(() -> new IllegalDataException("未指定待测试集合:" + testList));
Optional.ofNullable(targetList).filter(list -> !list.isEmpty())
.orElseThrow(() -> new IllegalDataException("未指定目标集合:" + targetList));
List<String> compareWordList = new ArrayList<>();
testList.stream()
// 过滤为null的数据
.filter(str -> str != null)
// 过滤不在targetList中的数据
.filter(str -> !targetList.contains(str))
// 过滤掉已存在于compareWordList中的数据
.filter(str -> !compareWordList.contains(str)).forEach(compareWordList::add);
return compareWordList;
}
/**
* 该方法用于对文本进行去重保留不重复的字符
*
* @param textFile 存储文本的文件
* @return 去重后的文本
* @throws IOException
*/
public static String textDelDuplication(String text) {
// 存储文件中的文本
StringBuilder newText = new StringBuilder();
// 获取并按字符对字符串进行返回
Optional.ofNullable(text).orElse("").chars()
// 将字符转换为字符串
.mapToObj(ch -> String.valueOf(((char) ch)))
// 过滤掉已在newText中的数据并进行存储
.filter(str -> newText.indexOf(str) < 0).forEach(newText::append);
return newText.toString();
}
/**
* 用于对文本按照切分符多次切分返回最终的切分结果
* <p>
* <b>注意</b>切分符必须使用正则表达式的写法例如按照.进行切分则必须传入\\.
* </p>
* @param text 需要切分的内容
* @param regexs 切分符号组
* @return 最终切分后的结果
*/
public static List<String> splitText(String text, String... regexs) {
List<String> wordList = new ArrayList<>();
// 若text存在且不为空则执行切分
Optional.ofNullable(text).filter(str -> !str.isEmpty()).ifPresent(str -> {
wordList.add(str);
//遍历切分符号集合
Arrays.stream(Optional.ofNullable(regexs).orElseThrow(() -> new IllegalDataException("未指定切分方式")))
.forEach(regex -> {
ArrayList<String> tempWordList = new ArrayList<>();
//遍历wordList中的所有内容并对内容一一按照当前的切分符号进行切分
wordList.stream().map(word -> word.split(regex))
//将且分后得到的数组转换为集合后并存储
.map(Arrays::asList).forEach(tempWordList::addAll);
//清空wordList集合并存储临时结合中的所有元素
wordList.clear();
wordList.addAll(tempWordList);
});
});
return wordList;
}
/**
* 该方法用于对文本中单词进行去重输出不重复单词
*
* @param testFile 待测文件
* @return 去重后的单词数组
*/
public static List<String> wordDelDuplication(List<String> textList) {
List<String> wordList = new ArrayList<>();
Optional.ofNullable(textList).filter(list -> !list.isEmpty()).ifPresent(list -> {
list.stream().filter(text -> !wordList.contains(text)).forEach(wordList::add);
});
return wordList;
}
/**
* 用于统计每个内容在集合中出现的次数
*
* @param wordList 需要统计的集合
* @return 统计结果
*/
public static LinkedHashMap<String, Integer> statistics(List<String> wordList) {
LinkedHashMap<String, Integer> result = new LinkedHashMap<>(16);
// 存储不重复的单词并存储其在文中出现的次数
Optional.ofNullable(wordList).filter(list -> !list.isEmpty()).ifPresent(list -> {
list.forEach(element -> {
// 判断map是否已经存在该词语若存在则将key对应的value加上1
if (result.containsKey(element)) {
result.put(element, result.get(element) + 1);
} else {
result.put(element, 1);
}
});
});
return result;
}
}

View File

@ -1,429 +0,0 @@
package com.auxiliary.tool.file;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Optional;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import com.opencsv.CSVReader;
/**
* <p>
* <b>文件名</b>DisposeText.java
* </p>
* <p>
* <b>用途</b>用于对文件中的文本进行处理以简化日常工作中对文本的内容的测试
* </p>
* <p>
* <b>编码时间</b>2019年7月4日 07:08
* </p>
* <p>
* <b>修改时间</b>2019年7月11日 09:12
* </p>
*
* @author 彭宇琦
* @version Ver1.0
* @since JDK 1.8
*/
public class DisposeText {
/**
* 段落或者表格列标记
*/
private static final String LINE = "\n";
/**
* 该方法用于对两文本中文本的单词进行比较
*
* @param testFile 待测试文件
* @param targetFile 目标文件
* @return 返回待测文件中不在目标文件中的单词
* @throws IOException
*/
public static ArrayList<String> compareFileWord(File testFile, File targetFile) throws IOException {
// 存储不在目标文件中的词语
ArrayList<String> words = new ArrayList<>();
// 定义存储切分词语的容器并存储其不重复的单词
LinkedHashMap<String, Integer> testTextMap = saveWord(split(readFile(testFile), LINE));
LinkedHashMap<String, Integer> targeTextMap = saveWord(split(readFile(targetFile), LINE));
// 对比结果
// 定义存储不在目标文件的词语
for (String targeWord : targeTextMap.keySet()) {
// 用于判断待测单词是否存在于目标单词表中存在则为true
boolean b = true;
for (String testWord : testTextMap.keySet()) {
// 判断待测单词是否与遍历到的目标单词一致一致则将b设置为true并结束遍历
if (testWord.trim().equals(targeWord.trim())) {
b = false;
break;
}
b = true;
}
// 判断b的值为false时则存储至words中
if (b) {
words.add(targeWord);
}
}
return words;
}
/**
* 该方法用于对文本进行去重保留不重复的字符
*
* @param textFile 存储文本的文件
* @return 去重后的文本
* @throws IOException
*/
public static String textDelDuplication(File textFile) throws IOException {
// 存储文件中的文本
StringBuilder text = new StringBuilder(readFile(textFile));
// 用于存储去重后的字符
String newText = "";
// 存储当前字符在本文本中出现的次数使用map存储
LinkedHashMap<String, Integer> saveChar = new LinkedHashMap<String, Integer>(16);
// 循环读取字符串中的每一个字符
for (int i = 0; i < text.length(); i++) {
// 获取当前读取的字符
String temp = text.substring(i, i + 1);
// 判断该字符是否存在于map中不存在则将该字符存储至map并拼接至newText中若存在则将map中的元素+1
if (!saveChar.containsKey(temp)) {
saveChar.put(temp, 1);
newText += temp;
} else {
saveChar.put(temp, saveChar.get(temp) + 1);
}
}
return newText;
}
/**
* 该方法用于对两文件中的文本按照指定的方式进行切分后输出待测文本与目标文本不同的地方
*
* @param testFile 待测文件
* @param targeFile 目标文件
* @return 待测文件与目标文件不相同的地方
* @throws IOException
*/
public static List<String[]> compareFileText(File testFile, File targeFile, String... regexs) throws IOException {
// 读取并按照规则切割文本并存储被切割的文本
// 由于返回为Collection故需要强转为ArrayList
ArrayList<String> testTexts = (ArrayList<String>) split(readFile(testFile), regexs);
ArrayList<String> targeTexts = (ArrayList<String>) split(readFile(targeFile), regexs);
// 用于存储对比后的文本容器元素的字符串数组存储待测文本和目标文本
ArrayList<String[]> result = new ArrayList<>();
// 注意此处用到一个对比由于在切分后后可能会由于目标或者待测文件多出一部分信息多两一个文本中按规则切分不出那么多的信息后则读取长的可能会出现空指针故需要按照短的那部分进行读取
// 存储最短的文本true表示targeTexts文本最短false表示testTexts最短
boolean compareText = testTexts.size() > targeTexts.size();
// 存储切分后容器元素最少的容器长度作为循环终点
int minLength = compareText ? targeTexts.size() : testTexts.size();
// 循环对两个容器中的元素进行逐个对比
for (int i = 0; i < minLength; i++) {
// 判断两个字符串是否相同相同则存储至容器中
// 由于切分的文档可能有空格的干扰故进行去空格处理后再对比
if (!testTexts.get(i).trim().equals(targeTexts.get(i).trim())) {
result.add(new String[] { testTexts.get(i), targeTexts.get(i) });
}
}
// 存储剩余
// 若两容器里的元素量相同则条件语句里的循环将不执行故亦可使用该方法
// 循环按照最短的元素继续存储至result容器中
for (int i = minLength; i < (compareText ? testTexts.size() : targeTexts.size()); i++) {
// 判断容器元素最少的容器存储多元素容器中的元素至result容器并将另外一个设为空串
if (compareText) {
result.add(new String[] { testTexts.get(i), "" });
} else {
result.add(new String[] { "", targeTexts.get(i) });
}
}
// 返回结果
return result;
}
/**
* 该方法用于对文本中单词进行去重输出不重复单词
*
* @param testFile 待测文件
* @return 去重后的单词数组
* @throws IOException
*/
public static String[] wordDelDuplication(File testFile) throws IOException {
// 读取切分并存储文本不重复的单词
LinkedHashMap<String, Integer> result = saveWord(split(readFile(testFile), LINE));
// 将不重复的单词转换成字符串数组并返回该数组
return result.keySet().toArray(new String[] {});
}
/**
* 该方法用于读取文件并自动判断文件的格式以选择相应的读取方式<br>
* <ul>
* <li>docdocxtxt格式以文本形式原文读取段落使用段落标记进行拼接</li>
* <li>xlsxlsxcsv格式以表格形式读取数据后按照标记拼接至字符串中读取</li>
* </ul>
*
* @param f 封装的文件对象
* @return 文本中的内容
* @throws UnsupportedFileException 文件格式或读取有误时抛出的异常
*/
public static String readFile(File f) {
// 用于存储读取文件中的内容
String text = "";
// 用于存储文件的后缀名以判断文件的格式
String[] fileName = f.getName().split("\\.");
String suffix = fileName[fileName.length - 1];
try {
switch (suffix) {
case "doc":
case "docx":
text = readWord(f);
break;
case "xls":
case "xlsx":
text = readExcel(f);
break;
case "txt":
text = readTxt(f);
break;
case "csv":
text = readCsv(f);
break;
default:
throw new UnsupportedFileException("无法解析“" + suffix + "”文件格式");
}
} catch (IOException e) {
throw new UnsupportedFileException("无法解析文件:" + f.getAbsolutePath());
}
return text;
}
/**
* 该方法用于读取并处理csv文件
*
* @param f 待读取的文件
* @return 读取的文本
* @throws IOException
*/
private static String readCsv(File f) throws IOException {
// 定义CSV文件对象
CSVReader csv = new CSVReader(new FileReader(f));
// 存储转换的字符串
String text = "";
// 用于临时转换的字符串数组
String[] texts;
// 循环读取所有的信息
while ((texts = csv.readNext()) != null) {
// 循环读取行内的信息
for (String temp : texts) {
text += (temp + LINE);
}
}
csv.close();
return text;
}
/**
* 该方法用于读取并处理txt文件
*
* @param file 待读取的文件
* @return 读取的文本
* @throws IOException
*/
private static String readTxt(File file) {
file = Optional.ofNullable(file).filter(File::isFile)
.orElseThrow(() -> new UnsupportedFileException("未传入文件路径或文件路径有误"));
try (BufferedReader br = new BufferedReader(new FileReader(file))) {
// 用于存储读取到的
String text = "";
// 定义临时读取文件时得到的字符串
String temp = "";
// 循环读取文件中所有的文本
// 循环按行读取文本
while ((temp = br.readLine()) != null) {
// 拼接字符串
text += (temp + LINE);
}
return text;
} catch (IOException e) {
throw new UnsupportedFileException("文件路径有误,无法读取");
}
}
/**
* 该方法用于读取并处理excel文件根据后缀名选择不同的读取方式
*
* @param f 待读取的文件
* @return 读取的文本
* @throws IOException
*/
private static String readExcel(File f) throws IOException {
String xlsx = "xlsx";
// 读取文件流
FileInputStream fip = new FileInputStream(f);
// 用于读取excel
Workbook excel = null;
// 根据文件名的后缀对其判断文件的格式并按照相应的格式构造对象
if (f.getName().indexOf(xlsx) > -1) {
// 通过XSSFWorkbook对表格文件进行操作
excel = new XSSFWorkbook(fip);
} else {
// 通过XSSFWorkbook对表格文件进行操作
excel = new HSSFWorkbook(fip);
}
// 关闭流
fip.close();
// 用于存储文本
String text = "";
// 读取excel中的内容
// 读取方式为将列与行的内容一同写在一列文本中不考虑分列
Sheet sheet = excel.getSheetAt(0);
for (int i = 0; i < sheet.getLastRowNum(); i++) {
Row row = sheet.getRow(i);
// 若获取不到行则说明该行无数据直接继续循环
if (row == null) {
continue;
}
for (int j = 0; j < row.getLastCellNum(); j++) {
try {
Cell cell = row.getCell(j);
text += (cell.toString() + LINE);
} catch (NullPointerException e) {
// 当读取到的列表为空时则会抛出空指针的异常此时不对该行进行存储
}
}
}
excel.close();
return text;
}
/**
* 该方法用于读取并处理word文件根据后缀名选择不同的读取方式
*
* @param f 待读取的文件
* @return 读取的文本
* @throws IOException
*/
private static String readWord(File f) throws IOException {
String docx = "docx";
// 用于存储读取到的文本
String text = "";
// 读取文件流
FileInputStream fip = new FileInputStream(f);
// 由于读取doc与docx的类不继承自同一个类所以无法直接写在一起只能通过判断语句隔开
if (f.getName().indexOf(docx) > -1) {
XWPFDocument word = new XWPFDocument(fip);
// 07版本相较麻烦需要分段读取
for (XWPFParagraph pa : word.getParagraphs()) {
text += (pa.getText() + LINE);
}
word.close();
} else {
HWPFDocument word = new HWPFDocument(fip);
// 由于03版的word可通过getText()方法直接返回文本内容故可直接写
StringBuilder temp = word.getText();
while (true) {
int i = -1;
// 判断是否存在/r若存在/r则替换成/n
if ((i = temp.indexOf("\r")) > -1) {
temp.replace(i, i + 1, "\n");
continue;
}
// 若未搜索到/r则结束循环
break;
}
// 存储替换后的文本
text = temp.toString();
word.close();
}
fip.close();
return text;
}
/**
* 该方法用于按照规则对字符串进行切分规则可定义多个
*
* @param regex 切分字符串的规则
* @return 切分的结果
*/
private static Collection<String> split(String text, String... regexs) {
// 用于存储切分后的信息
Collection<String> c = new ArrayList<String>();
c.add(text);
// 循环逐个读取切分的规则信息
for (String regex : regexs) {
Collection<String> temp = new ArrayList<String>();
c.forEach(element -> {
temp.addAll(Arrays.asList(element.split(regex)));
});
c = temp;
}
return c;
}
/**
* 该方法用于存储关键词出现的次数
*
* @param words 需要写入word中的数据
* @return 返回map
*/
private static LinkedHashMap<String, Integer> saveWord(Collection<String> words) {
LinkedHashMap<String, Integer> result = new LinkedHashMap<>(16);
// 存储不重复的单词并存储其在文中出现的次数
words.forEach(element -> {
// 判断map是否已经存在该词语若存在则将key对应的value加上1
if (result.containsKey(element)) {
result.put(element, result.get(element) + 1);
} else {
result.put(element, 1);
}
});
return result;
}
}

View File

@ -73,25 +73,21 @@ public class TextFileReadUtil {
/**
* 用于以行元素单位合并csv文件中所有的元素内容并以字符串的形式返回
* @param file 待读取文件对象
* @param isLine 是否插入换行符
* @return 合并后的文本
*/
public static String mergeAllRowDataToCsv(File file) {
StringBuilder text = new StringBuilder();
mergeRowDataToCsv(file).forEach(text::append);
return text.toString();
public static String mergeAllRowDataToCsv(File file, boolean isLine) {
return megerText(mergeRowDataToCsv(file), isLine);
}
/**
* 用于以列元素单位合并csv文件中所有的元素内容并以字符串的形式返回
* @param file 待读取文件对象
* @param isLine 是否插入换行符
* @return 合并后的文本
*/
public static String mergeAllColumnDataToCsv(File file) {
StringBuilder text = new StringBuilder();
mergeColumnDataToCsv(file).forEach(text::append);
return text.toString();
public static String mergeAllColumnDataToCsv(File file, boolean isLine) {
return megerText(mergeColumnDataToCsv(file), isLine);
}
/**
@ -135,34 +131,32 @@ public class TextFileReadUtil {
/**
* 用于以行元素单位合并excel文件中所有的元素内容并以字符串的形式返回
* @param file 待读取文件对象
* @param sheetName 读取的sheet名称
* @param isLine 是否插入换行符
* @return 合并后的文本
*/
public static String mergeAllRowDataToExcel(File file, String sheetName) {
StringBuilder text = new StringBuilder();
mergeRowDataToExcel(file, sheetName).forEach(text::append);
return text.toString();
public static String mergeAllRowDataToExcel(File file, String sheetName, boolean isLine) {
return megerText(mergeRowDataToExcel(file, sheetName), isLine);
}
/**
* 用于以列元素单位合并excel文件中所有的元素内容并以字符串的形式返回
* @param file 待读取文件对象
* @param sheetName 读取的sheet名称
* @param isLine 是否插入换行符
* @return 合并后的文本
*/
public static String mergeAllColumnDataToExcel(File file, String sheetName) {
StringBuilder text = new StringBuilder();
mergeColumnDataToExcel(file, sheetName).forEach(text::append);
return text.toString();
public static String mergeAllColumnDataToExcel(File file, String sheetName, boolean isLine) {
return megerText(mergeColumnDataToExcel(file, sheetName), isLine);
}
/**
* 用于合并旧版word2003版本word文档中每段的内容以字符串的形式返回
* 用于读取旧版word2003版本word文档中每段的内容将段落内容以集合的形式返回
* @param file 待读取文件对象
* @return 并后的文本
* @return 读取的段落集
*/
public static String megerTextToOldWord (File file) {
StringBuilder megerText = new StringBuilder();
public static List<String> oldWordToLineList(File file) {
List<String> lineTextList = new ArrayList<>();
// 读取word
Optional<HWPFDocument> wordOptional = Optional.empty();
@ -186,22 +180,32 @@ public class TextFileReadUtil {
// 去除换行符并过滤掉空行
.map(text -> text.replaceAll("\\r", ""))
// 按行存储至列表对象中
.forEach(megerText::append);
.forEach(lineTextList::add);
} catch (IOException e) {
throw new UnsupportedFileException("文件异常,无法进行读取:" + file.getAbsolutePath(), e);
}
return megerText.toString();
return lineTextList;
}
/**
* 用于合并新版word2007及以上版本word文档中每段的内容并以字符串的形式返回
* 用于合并旧版word2003版本word文档中每段的内容并以字符串的形式返回
* @param file 待读取文件对象
* @param isLine 是否插入换行符
* @return 合并后的文本
*/
public static String megerTextToNewWord(File file) {
StringBuilder megerText = new StringBuilder();
public static String megerTextToOldWord (File file, boolean isLine) {
return megerText(oldWordToLineList(file), isLine);
}
/**
* 用于读取新版word2007及以上版本word文档中每段的内容并将段落内容以集合的形式返回
* @param file 待读取文件对象
* @return 读取的段落集合
*/
public static List<String> newWordToLineList(File file) {
List<String> lineTextList = new ArrayList<>();
// 读取word
Optional<XWPFDocument> wordOptional = Optional.empty();
try (FileInputStream fip = new FileInputStream(
@ -224,32 +228,62 @@ public class TextFileReadUtil {
//将段落转换为为本
.map(XWPFParagraph::getText)
//拼接文本
.forEach(megerText::append);
;
.forEach(lineTextList::add);
} catch (IOException e) {
throw new UnsupportedFileException("文件异常,无法进行读取:" + file.getAbsolutePath(), e);
}
return megerText.toString();
return lineTextList;
}
/**
* 用于合并txt格式村文本文档中每段的内容并以字符串的形式返回
* 用于合并新版word2007及以上版本word文档中每段的内容并以字符串的形式返回
* @param file 待读取文件对象
* @param isLine 是否插入换行符
* @return 合并后的文本
*/
public static String megerTextToTxt(File file) {
StringBuilder megerText = new StringBuilder();
public static String megerTextToNewWord(File file, boolean isLine) {
return megerText(newWordToLineList(file), isLine);
}
/**
* 用于读取txt格式纯文本文档中每段的内容并将段落内容以集合的形式返回
* @param file 待读取文件对象
* @return 读取的段落集合
*/
public static List<String> txtToLineList(File file) {
List<String> lineTextList = new ArrayList<>();
try (BufferedReader br = new BufferedReader(
new FileReader(Optional.ofNullable(file).orElseThrow(() -> new UnsupportedFileException("未传入文件对象"))))) {
// 按行遍历文件内容
br.lines().forEach(megerText::append);
br.lines().forEach(lineTextList::add);
} catch (IOException e) {
throw new UnsupportedFileException("文件异常,无法进行读取:" + file.getAbsolutePath(), e);
}
return lineTextList;
}
/**
* 用于合并txt格式纯文本文档中每段的内容并以字符串的形式返回
* @param file 待读取文件对象
* @param isLine 是否插入换行符
* @return 合并后的文本
*/
public static String megerTextToTxt(File file, boolean isLine) {
return megerText(txtToLineList(file), isLine);
}
/**
* 用于对集合型内容进行合并
* @param textList 内容集合
* @param isLine 是否插入换行符
* @return 拼接后的文本
*/
private static String megerText(List<String> textList, boolean isLine) {
StringBuilder megerText = new StringBuilder();
textList.stream().map(str -> str += (isLine ? "\n" : "")).forEach(megerText::append);
return megerText.toString();
}
}