需求:有一堆英语考试真题(PDF格式),读取PDF,然后分析每个单词出现的词频,输出到一个txt文本中,每行是“单词 词频”,结果按照词频降序排列。
思路:使用一个LinkedHashMap,Key是单词,Value是词频,逐个遍历每个pdf文件,读取pdf中的所有文本,对于文本按照各种标点符号进行分割,将全部单词转为小写,遍历每个单词,看在map中是否存在,存在则词频+1,不存在则put增加新的单词。
代码如下:
import com.yzk18.commons.IOHelpers;
import com.yzk18.docs.PDFHelpers;
import org.apache.pdfbox.pdmodel.PDDocument;
import java.util.*;
public class WordFrequency {
public static void main(String[] args) {
//扫描PDF文件目录
String dir = "E:\\英语\\六级英语\\2020年7月";
//遍历文件夹下所有PDF文件
String[] pdfFiles = IOHelpers.getFilesRecursively(dir,"pdf");
LinkedHashMap<String,Integer> map = new LinkedHashMap<>();
for (String pdfFile : pdfFiles)
{
PDDocument doc = PDFHelpers.openFile(pdfFile);
//读取这个PDF所有的文本
String text = PDFHelpers.parseText(doc);
//通过不同标点符号分割出单词
String[] words = text.toLowerCase().split("\\s|\\.|\\,|\\:|\\!|\\?|;|\\(|\\)");
for(String word : words)
{
//如果这个word不是英语单词,则跳过
if(!isEnglishWord(word))
{
//处理下一个单词
continue;
}
if(word.equals(""))
{
continue;
}
//是否是全部由字母组成的
Integer freq = map.get(word);//获得当前的词频
if(freq==null)
{
map.put(word,1);//之前没出现过这个单词,记录为1
}
else
{
map.put(word,freq+1);//如果出现过则递增
}
}
PDFHelpers.close(doc);
}
String outputString="";
List<Map.Entry<String, Integer>> infoIds =new ArrayList<Map.Entry<String, Integer>>(map.entrySet());
//按照词频排序
Collections.sort(infoIds, new Comparator<Map.Entry<String, Integer>>() {
@Override
public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
Integer p1 = o1.getValue();
Integer p2 = o2.getValue();;
return Integer.valueOf(p2)-Integer.valueOf(p1);//如果要升序, 改为return Integer.valueOf(p1)-Integer.valueOf(p2);
}
});
//转换成新map输出
LinkedHashMap<String, Integer> newMap = new LinkedHashMap <String, Integer>();
for(Map.Entry<String,Integer> entity : infoIds){
newMap.put(entity.getKey(), entity.getValue());
}
//输出词频
for(String word : newMap.keySet())//keySet()是map中所有key的集合
{
int freq = map.get(word);
//System.out.println(word+"="+freq);
outputString = outputString+word+" "+freq+"\r\n";
}
//结果输出到某个路径下的txt文件中
IOHelpers.writeAllText("d:/1.txt", outputString);
}
//判断s是否是一个英文单词(全部由英文字母组成)
public static boolean isEnglishWord(String s)
{
for(int i=0;i<s.length();i++)
{
char ch = s.charAt(i);
//只要碰到一个非字母,函数就返回false
if(Character.isLowerCase(ch)==false)
{
return false;
}
}
return true;//如果运行到这里,就说明每个都是字母
}
}
输出结果如下:
这样,就可以自己网上下载四六级真题,通过词频背单词啦,( ̄▽ ̄)~*。