问题描述:读取项目中后缀为java文件中的代码里的中文,也就是过滤注释里的中文,输出代码里的中文到本地文件里。
首先搭建一个框架,因为是工具,因此有一个可视化界面,界面有两个按钮,一个打开本地文件,一个导出到本地。当点击打开本地文件时候,会将选择的文件夹下的所有后缀为java的代码中的中文输出到界面。导出的时候可以选择导出到哪里,文件名为test.txt。
先搭建页面
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.nio.charset.Charset;
import java.nio.charset.MalformedInputException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static javax.swing.WindowConstants.DISPOSE_ON_CLOSE;
public class Tool {
JFrame window;
JPanel panel,panel1,panel2;
JButton btn1,btn2;
JTextArea textArea;
JScrollPane scrollPane;//文本域放入滚动窗口
public Tool(String title){
initUi(title);
}
public static void main(String[] args) {
new Tool("我的窗口");
}
public void initUi(String title){
window = new JFrame(title);
panel = new JPanel();
panel1 = new JPanel();
//创建打开本地文件的按钮
btn1 = new JButton("打开文件");
btn1.setPreferredSize(new Dimension(100, 40));
//添加按钮监控事件
btn1.addActionListener(new button1ActionListener());
//设置按钮区域的边框属性
panel1.setBorder(BorderFactory.createTitledBorder("选择"));
panel1.add(btn1);
//创建导出按钮
btn2 = new JButton("导出");
btn2.setPreferredSize(new Dimension(100, 40));
//添加按钮监控事件
btn2.addActionListener(new button2ActionListener());
panel1.add(btn2);
panel2 = new JPanel();
textArea = new JTextArea("中文汉字有:",20,100);
textArea.setLineWrap(true);//自动换行
textArea.setEditable(false);//设置文本框是否可编辑
textArea.setForeground(Color.BLACK);
textArea.setFont(new Font("楷体",Font.BOLD,16));//设置字体样式
Dimension size = textArea.getPreferredSize();//获得文本域的首选大小
//设置文本域滚动框
scrollPane = new JScrollPane(textArea);
scrollPane.setBounds(110,90,size.width,size.height);
//设置文本区域的边框属性
panel2.setBorder(BorderFactory.createTitledBorder("内容"));
panel2.add(scrollPane);
panel.setLayout(new BorderLayout());//设置布局为BorderLayout
panel.add(panel1,BorderLayout.NORTH);
panel.add(panel2,BorderLayout.CENTER);
window.add(panel);
//设置窗口大小
window.setSize(1000,700);
//居中
window.setLocationRelativeTo(null);
//设置窗口可见
window.setVisible(true);
window.setDefaultCloseOperation(DISPOSE_ON_CLOSE);//设置关闭方式
}
}
注意上面的两句代码,给按钮添加监控事件,也就是点击之后做什么操作,后面的是内部类,接下来编写内部类的部分。
//添加打开文件按钮监控事件
btn1.addActionListener(new button1ActionListener());
//添加导出按钮监控事件
btn2.addActionListener(new button2ActionListener());
先编写打开文件按钮的内部类
//处理打开按钮单击事件的匿名内部类
class button1ActionListener implements ActionListener
{
@Override
public void actionPerformed(ActionEvent actionEvent)
{
//默认打开的位置是D盘下的文件
JFileChooser fc = new JFileChooser(new File("D:\\"));
//可以选择文件和目录,也就是用户打开点击可以选择的内容
fc.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
fc.showOpenDialog(null); //文件打开对话框
//获得用户选择的路径
String fileName = fc.getSelectedFile().getPath();
//执行判断方法,将内容输出到textArea
try {
isPrint(fileName);
} catch (IOException e) {
e.printStackTrace();
}
}
public void isPrint(String fileName) throws IOException{
try {
StringBuffer sb = new StringBuffer();
//用这个api来循环读取总文件下的所有文件
Stream<Path> paths = Files.walk(Paths.get(fileName));
//找出后缀为java的文件存放到list集合中
List<String> result = paths.map(x->x.toString()).filter(f->f.endsWith(".java")).collect(Collectors.toList());
for (String s:result){
//在控制台输出后缀为java文件的路径
System.out.println(s);
try{
//用这个api读每个后缀为java文件的内容,存放到list集合中,按行读取
List<String> lines = Files.readAllLines(Paths.get(s), Charset.forName("UTF-8"));
for (String l:lines){
//第一层过滤,过滤不是中文的行,包括注释。因为第二层之间过滤了所有的带*的,带\的,这里就不做处理了
/*if (isChinese(l)){
System.out.println(l);
}*/
//第二层过滤,去除注释行,带*带/的中文行,用正则表达式过滤
if (isContainChinese(l)){
//第三层,去除log,logger的行,因为我的要求是要去除打印到日志里的中文行,这里也过滤掉
if (!l.contains("log")){
//找出""之间的内容
Pattern p = Pattern.compile("\".*[\u4e00-\u9fa5|%].*\"");
Matcher m = p.matcher(l);
//第四层提取出一行带有冒号的字符,因为中文都是在冒号里,所以提取出冒号里的东西
if(m.find()){
//打印到控制台,发现不仅带冒号的中文打印出来了,而且英文的也打印出来了,这里写正则不好判断,因为中文里面也夹杂着英文,因此用逗号分割一下,在判断一下
System.out.println(m.group());
String[] split = m.group().split(",");
for (String s2:split){
if (isChinese(s2)){
System.out.println(s2);
//将过滤结果放入到sb里
sb.append(s2.toString());
sb.append("\n");
}
}
}
}
}
}
}catch (MalformedInputException e){
e.getMessage();
}
}
//将过滤的内容添加到界面上
textArea.setText(sb.toString());
} catch (IOException e) {
e.printStackTrace();
}
}
}
处理判断的两个静态方法
//判断出中文行带*的带/的,也就是注释行
public static boolean isContainChinese(String str) {
Pattern p = Pattern.compile("^[^*/]*[\u4e00-\u9fa5]+[^*/]*$");
Matcher m = p.matcher(str);
return m.find();
}
//找出中文的
public static boolean isChinese(String str){
Pattern p = Pattern.compile("[\u4e00-\u9fa5]+");
Matcher m = p.matcher(str);
return m.find();
}
在来编写导出按钮的内部类
//处理导出按钮单击事件的匿名内部类
class button2ActionListener implements ActionListener{
@Override
public void actionPerformed(ActionEvent e) {
BufferedWriter bw = null;
String choosePath = null;
String newPath=null;
try {
//弹出文件选择框
JFileChooser jfc = new JFileChooser("D:\\");
//仅仅显示目录
jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int option = jfc.showSaveDialog(null);
//选择保存
if (option==JFileChooser.APPROVE_OPTION){
choosePath = jfc.getSelectedFile().getPath();
newPath = choosePath.concat("/test.txt");
//获得选择的路径,创建test.txt文件
new File(newPath);
}
FileOutputStream os = new FileOutputStream(newPath);
bw = new BufferedWriter(new OutputStreamWriter(os));
for (String value:textArea.getText().split(" ")){
bw.write(value);
bw.newLine(); //换行
}
} catch (FileNotFoundException ex) {
throw new RuntimeException(ex);
} catch (IOException ex) {
throw new RuntimeException(ex);
}finally {
if (bw != null){
try {
bw.close();
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
}
}
}
总结:
目前只能判断编码格式是UTF-8的,导出文件不能用户命名,只能选择位置。
遇到的问题:
打成jar问题,idea默认 添加artifacts的时候META-INF文件位置是在 src/main/java/META_INF/
下创建目录,但是此目录(src/main/java/)
已标记为Sources Root,仅编译;修改成resource资源下的就行。