ChenZhen 搜索
首页 标签 归档 留言板 友链 ChatGPT 提示库 AI工具导航网 🚇开往 关于我

使用java操作文件给指定目录下所有类统一添加 @author 创建者信息

这段Java代码用于自动更新源代码文件中的创建者信息(作者信息)以及注释。它的主要功能包括: 1. **遍历指定目录下的Java文件**:通过指定的项目路径,递归地处理目录下的所有Java文件。 2. **更新创建者信息**:针对每个Java文件,它会寻找最后一个`import`语句和`public class`或`public interface`等(即类的声明语句)之间的位置,在此处尝试定位文件的开头,并且会在文件的开头插入作者信息。

ChenZhen 2023-12-12T17:36:59
cover

使用java操作文件给指定目录下所有类统一添加 @author 创建者信息

  • 作者:ChenZhen

  • 本人不常看网站消息,有问题通过下面的方式联系:

    • 邮箱:1583296383@qq.com
    • vx: ChenZhen_7
  • 我的个人博客地址:https://www.chenzhen.space/🌐

  • 版权:本文为博主的原创文章,本文版权归作者所有,转载请附上原文出处链接及本声明。📝

  • 如果对你有帮助,请给一个小小的star⭐🙏

概要

这段Java代码用于自动更新源代码文件中的创建者信息(作者信息)以及注释。它的主要功能包括:

  1. 遍历指定目录下的Java文件:通过指定的项目路径,递归地处理目录下的所有Java文件。

  2. 更新创建者信息:针对每个Java文件,它会寻找最后一个import语句和public classpublic interface等(即类的声明语句)之间的位置,在此处尝试定位文件的开头,并且会在文件的开头插入作者信息。

  3. 检测和处理注释:程序会检查文件中是否包含注释,如果存在注释,则会检查其中是否已包含作者信息,如果没有,则在注释中的合适位置插入新的作者信息,如果已经存在作者信息,则替换为新的作者信息。

  4. 输出比较结果:在更新作者信息后,会输出部分的原始内容与更新后内容的比较结果,通过高亮显示差异部分,以便用户检查更改,不满意可跳过处理。

  5. 文件写回:按回车更新,完成后,会将修改后的内容写回到相应的Java文件中。

总体来说,这段代码的主要目的是自动化处理Java文件中的创建者信息,确保每个文件都有统一的作者信息,并提供了对比功能,让用户可以直观地看到更改的部分。

运行截图:

控制台会显示import语句和类的声明之间的位置的代码,左边是代码修改前的,右边是代码修改后,修改过的内容会通过红色高亮显示。

在这里插入图片描述

代码:

首先,指定项目路径;其次,输入作者名;然后运行即可。

package com.example.demo1;

import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class CreatorInfoUpdater {

    public static void main(String[] args) throws IOException {
        // 指定项目路径
        String directoryPath = "D:\\project\\新建文件夹\\demo1\\src\\main\\java\\com\\example\\demo1"; 
        // 指定你的作者名
        String author = "chenzhen";
        
        // 处理文件
        File directory = new File(directoryPath);
        // 判断目录是否存在
        if (directory.exists() && directory.isDirectory()) {
            processFiles(directory,author);
        } else {
            System.out.println("Invalid directory path");
        }
        Scanner scanner = new Scanner(System.in);
        scanner.close();

    }

    /**
     *  给文件添加创建者信息  
     *  检查文件中是否包含注释,如果存在注释,则会检查其中是否已包含作者信息
     *  如果有:则换成新的作者
     *  如果没有:则在注释中的合适位置插入新的作者信息。
     * @param file
     * @throws IOException
     */
    private static void insertCreatorInfo(File file,String author) throws IOException {

        Scanner scanner = new Scanner(System.in);
        

        String creatorInfo =
                "/**\n" +
                " * @author "+ author + "\n" +
                " */";


        // 读取文件内容
        BufferedReader reader = new BufferedReader(new FileReader(file));
        String line;
        StringBuilder content = new StringBuilder();
        // 逐行读取文件内容并保存到StringBuilder中
        while ((line = reader.readLine()) != null) {
            content.append(line).append("\n");
        }
        reader.close();

        int start = -1;
        int end = -1;

        //创建正则表达式模式,匹配最后一个import语句
        Pattern pattern = Pattern.compile("import\\s+[^;]+;");
        Matcher matcher = pattern.matcher(content);

        int importOrPackStartIdx = -1;
        int importOrPackEndIdx = -1;

        // 找到最后一个匹配的import语句
        while (matcher.find()) {
            importOrPackStartIdx = matcher.start();
            importOrPackEndIdx = matcher.end();
        }
        if (importOrPackStartIdx == -1 || importOrPackEndIdx == -1) {
            //创建正则表达式模式,匹配package语句
            Pattern packPattern = Pattern.compile("package\\s+[^;]+;");
            Matcher packMatcher = packPattern.matcher(content);
            if (!packMatcher.find()) {
                System.err.println("未找到import或package语句 文件:" + file.getAbsolutePath() );
                System.out.println("输入任意键继续:");
                scanner.nextLine();
                return;
            }
            importOrPackStartIdx = packMatcher.start();
            importOrPackEndIdx = packMatcher.end();

        }
        String codeAfterImport = content.substring(importOrPackEndIdx);
        start = importOrPackEndIdx;


        // 创建正则表达式模式,匹配public class或public interface
        Pattern classInterfacePattern = Pattern.compile("(?<!\\S)(public\\s+(class|interface|enum|abstract|@interface))\\b");
        Matcher classInterfaceMatcher = classInterfacePattern.matcher(codeAfterImport);

        int classInterfaceStartIdx = -1;
        int classInterfaceEndIdx = -1;

        // 找到匹配的public class或public interface
        if (classInterfaceMatcher.find()) {
            classInterfaceStartIdx = importOrPackEndIdx + classInterfaceMatcher.start();
            classInterfaceEndIdx = importOrPackEndIdx + classInterfaceMatcher.end();
        }

        if (classInterfaceStartIdx == -1 || classInterfaceEndIdx == -1) {
   ;
            System.err.println("未找到匹配的public class或public interface 文件:" + file.getAbsolutePath());
            System.out.println("输入任意键继续:");
            scanner.nextLine();

            return;
        }
        String betweenImportAndClass =  content.substring(importOrPackEndIdx, classInterfaceStartIdx);


        // 创建正则表达式模式,匹配多行注释
        Pattern commentPattern = Pattern.compile("/\\*.*?\\*/", Pattern.DOTALL);
        Matcher commentMatcher = commentPattern.matcher(betweenImportAndClass);
        StringBuffer buffer = new StringBuffer();
        boolean hasComment = false;
        //  */的偏移量
        int insertionIndex = 0;
        //如果已经有注释了
        if (commentMatcher.find()) {
            // 获取注释
            String comment = commentMatcher.group();
            // 创建正则表达式模式,匹配多行注释中的现有的作者信息
            Pattern authorPattern = Pattern.compile("(@author|@author:)\\s+[^\\n]+");
            Matcher authorMatcher = authorPattern.matcher(comment);
            StringBuffer authorBuffer = new StringBuffer();
            insertionIndex = comment.indexOf("*/");
            //如果注释中已经有其他的@author作者信息,统一替换
            if (authorMatcher.find()) {
                System.out.println("注释中已经有其他的创建者信息" + authorMatcher.group());
                authorMatcher.appendReplacement(authorBuffer, "@author " + author);
                authorMatcher.appendTail(authorBuffer);
                creatorInfo = authorBuffer.toString();
            }else{
                // 如果没有则在注释中间找到一个适当的位置插入作者信息
                String updatedComment = new StringBuilder(comment)
                        .insert(insertionIndex, "* @author " + author + "\n ")
                        .toString();
                commentMatcher.appendReplacement(buffer, updatedComment);
                //更正创建者信息
                creatorInfo = buffer.toString();
            }

            hasComment = true;

        }

        String betweenCommendAndClass = "";
        int commentEndIdx = importOrPackEndIdx;
        // 如果存在注释
        if (hasComment){
            commentEndIdx += insertionIndex + 4;
        }
        betweenCommendAndClass =  content.substring(commentEndIdx, classInterfaceStartIdx);

        // 创建正则表达式模式,匹配注解
        Pattern annotationPattern = Pattern.compile("(?<=^|\\s)@\\w+(?![\\w\\s]*\\*/)");
        Matcher annotationMatcher = annotationPattern.matcher(betweenCommendAndClass);

        int annotationStartIdx = -1;
        int annotationEndIdx = -1;

        // 找到第一个匹配的注解
        if (annotationMatcher.find()) {

            annotationStartIdx = commentEndIdx +  annotationMatcher.start();
            annotationEndIdx = commentEndIdx + annotationMatcher.end();
        }

        if (annotationStartIdx == -1 || annotationEndIdx == -1) {
            System.out.println("未找到匹配的注解");
            end = classInterfaceStartIdx - 1;
        }else{
            end = annotationStartIdx - 1;
        }

        String updateContent;


        creatorInfo = Arrays.stream(creatorInfo.split("\n"))
                .filter(item -> !item.trim().equals("*"))
                .collect(Collectors.joining("\n"));

        // 获取要替换的部分之前的字符串
        String partBefore = content.substring(0, start);
        // 获取要替换的部分之后的字符串
        String partAfter = content.substring(end); // 加1是为了不包含 endIndex 这个位置的字符
        // 组合新的字符串
        updateContent = partBefore + "\n\n" +  creatorInfo + partAfter;

        Matcher newClassInterfaceMatcher = classInterfacePattern.matcher(updateContent);
        if (newClassInterfaceMatcher.find()) {
            int newClassInterfaceEndIdx = newClassInterfaceMatcher.end();
            printAandB(content.substring(importOrPackStartIdx,classInterfaceEndIdx), updateContent.substring(importOrPackStartIdx,newClassInterfaceEndIdx));

        }else {
            System.err.println("未找到新的匹配的public class或public interface 文件:" + file.getAbsolutePath());
            System.out.println(content.substring(importOrPackStartIdx,classInterfaceEndIdx));
            System.out.println("输入任意键继续:");

            scanner.nextLine();

            return;
        }

        System.out.println("回车添加创建者信息,或者输入 'n' 跳过,");
        System.out.println("文件 = " + file.getAbsolutePath());

        String input = scanner.nextLine();

        if (input.equals("n")) {
            return;
        }
        // 写回到文件中
        BufferedWriter writer = new BufferedWriter(new FileWriter(file));
        writer.write(updateContent);
        writer.close();

    }


    /**
     * 递归处理给定目录下的所有文件,为所有的 Java 文件插入创建者信息。
     *
     * @param directory 要处理的目录
     * @throws IOException 如果发生 I/O 错误时抛出异常
     */
    private static void processFiles(File directory,String author) {
        // 获取目录下的所有文件
        File[] files = directory.listFiles();
        if (files == null){
            System.out.println("文件为空");
            return;
        }
      
        for (File file : files) {
            // 如果是目录,则递归处理子目录
            if (file.isDirectory()) {
                processFiles(file,author);
            } else if (file.getName().endsWith(".java")) {
                try {
                    // 插入创建者信息到 Java 文件中
                    insertCreatorInfo(file,author);
                    System.out.println("\n\n");
                } catch (Exception e) {
                    // 打印异常信息和出错文件的路径
                    e.printStackTrace();
                    System.err.println("文件出错 = " + file.getAbsolutePath());
                }
            }
        }
        
    }


    /**
     * 将两个字符串按行比较并打印输出,标记相同行和不同行。
     *
     * @param stringA 第一个字符串
     * @param stringB 第二个字符串
     */
    public static void printAandB(String stringA, String stringB) {
        // 按行分割两个字符串
        String[] linesA = stringA.split("\n");
        String[] linesB = stringB.split("\n");

        // 获取两个字符串中最大行数和最大行长度
        int maxLineLength = Math.max(linesA.length, linesB.length);
        int maxStringLength = 0;
        for (int i = 0; i < maxLineLength; i++) {
            String lineA = (i < linesA.length) ? linesA[i] : "";
            String lineB = (i < linesB.length) ? linesB[i] : "";
            int tempMax = Math.max(lineA.length(), lineB.length());
            maxStringLength = Math.max(maxStringLength, tempMax);
        }

        // 保存相同行的列表
        ArrayList<String> highlightList = new ArrayList<>();

        // 找出相同的行并加入到相同行的列表中
        for (int i = 0; i < maxLineLength; i++){
            String lineA = (i < linesA.length) ? linesA[i]: "";
            for (int j = 0; j < maxLineLength; j++) {
                String lineB = (j < linesB.length) ? linesB[j] : "";
                if (lineA.equals(lineB)) {
                    highlightList.add(lineA);
                }
            }
        }

        System.out.println("\n");

        // 打印并标记相同和不同的行
        for (int i = 0; i < maxLineLength; i++) {
            String lineA = (i < linesA.length) ? linesA[i] : "";
            String lineB = (i < linesB.length) ? linesB[i] : "";
            StringBuilder lineAbuilder = new StringBuilder(lineA);
            while (lineAbuilder.length() < maxStringLength) {
                lineAbuilder.append(" ");
            }
            String finalLineA = lineAbuilder.toString().replaceAll("[\\u4E00-\\u9FFF]", "x");

            if (highlightList.contains(lineA)) {
                System.out.print(finalLineA);
            } else {
                // 如果比较内容不同,在控制台输出时标记为红色
                System.out.print("\033[31m" + finalLineA.substring(0,lineA.length()) + "\033[0m" + finalLineA.substring(lineA.length()));

            }
            System.out.print("      =\t");
            if (highlightList.contains(lineB)) {
                System.out.println(lineB);
            } else {
                // 如果比较内容不同,在控制台输出时标记为红色
                System.out.println("\033[31m" + lineB + "\033[0m");

            }

        }
        System.out.println("\n");
    }

}

© 版权声明
😀😃😄😁😆😅🤣😂🙂🙃😉😊😇🥰😍🤩😘😗😚😙😋😛😜🤪😝🤑🤗🤭🤫🤔🤐🤨😐😑😶😏😒🙄😬🤥😌😔😪🤤😴😷🤒🤕🤢🤮🤧🥵🥶🥴😵🤯🤠🥳😎🤓🧐😕😟🙁☹️😮😯😲😳🥺😦😧😨😰😥😢😭😱😖😣😞😓😩😫🥱😤😡😠🤬