删除java文件中的所有类型的注释

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23333031/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 21:59:25  来源:igfitidea点击:

Removing all types of comments in java file

javaeclipsecomments

提问by haripcce

I have a java project and i have used comments in many location in various java files in the project. Now i need to remove all type of comments : single line , multiple line comments . Please provide automation for removing comments. using tools or in eclipse etc.

我有一个 java 项目,我在项目的各种 java 文件的许多位置使用了注释。现在我需要删除所有类型的注释:单行、多行注释。请提供自动删除评论。使用工具或在 eclipse 等中。

Currently i am manually trying to remove all commetns

目前我正在手动尝试删除所有commetns

回答by Andrew Vitkus

I had to write somehting to do this a few weeks ago. This should handle all comments, nested or otherwise. It is long, but I haven't seen a regex version that handled nested comments properly. I didn't have to preserve javadoc, but I presume you do, so I added some code that I belive should handle that. I also added code to support the \r\n and \r line separators. The new code is marked as such.

几周前我不得不写一些东西来做到这一点。这应该处理所有注释,嵌套或其他方式。它很长,但我还没有看到正确处理嵌套注释的正则表达式版本。我不必保留 javadoc,但我认为您这样做了,所以我添加了一些我认为应该处理的代码。我还添加了支持 \r\n 和 \r 行分隔符的代码。新代码被标记为这样。

public static String removeComments(String code) {
    StringBuilder newCode = new StringBuilder();
    try (StringReader sr = new StringReader(code)) {
        boolean inBlockComment = false;
        boolean inLineComment = false;
        boolean out = true;

        int prev = sr.read();
        int cur;
        for(cur = sr.read(); cur != -1; cur = sr.read()) {
            if(inBlockComment) {
                if (prev == '*' && cur == '/') {
                    inBlockComment = false;
                    out = false;
                }
            } else if (inLineComment) {
                if (cur == '\r') { // start untested block
                    sr.mark(1);
                    int next = sr.read();
                    if (next != '\n') {
                        sr.reset();
                    }
                    inLineComment = false;
                    out = false; // end untested block
                } else if (cur == '\n') {
                    inLineComment = false;
                    out = false;
                }
            } else {
                if (prev == '/' && cur == '*') {
                    sr.mark(1); // start untested block
                    int next = sr.read();
                    if (next != '*') {
                        inBlockComment = true; // tested line (without rest of block)
                    }
                    sr.reset(); // end untested block
                } else if (prev == '/' && cur == '/') {
                    inLineComment = true;
                } else if (out){
                    newCode.append((char)prev);
                } else {
                    out = true;
                }
            }
            prev = cur;
        }
        if (prev != -1 && out && !inLineComment) {
            newCode.append((char)prev);
        }
    } catch (IOException e) {
        e.printStackTrace();
    }

    return newCode.toString();
}

回答by Serge Ballesta

Dealing with source code is hard unless you know more on the writing of comment. In the more general case, you could have // or /* in text constants. So your reallyneed to parse the file at a syntaxic level, not only lexical. IMHO the only bulletproof solution would be to start for example with the java parser from openjdk.

除非您对注释的编写了解更多,否则处理源代码是很困难的。在更一般的情况下,您可以在文本常量中使用 // 或 /*。所以你真的需要在语法级别解析文件,而不仅仅是词汇。恕我直言,唯一的防弹解决方案是从openjdk的 java 解析器开始。

If you know that your comments are never deeply mixed with the code (in my exemple comments MUSTbe full lines), a python script could help

如果您知道您的注释永远不会与代码深度混合(在我的示例中,注释必须是整行),python 脚本可能会有所帮助

multiple = False
for line in text:
    stripped = line.strip()
    if multiple:
        if stripped.endswith('*/'):
            multiple = False
            continue
    elif stripped.startswith('/*'):
        multiple = True
    elif stripped.startswith('//'):
        pass
    else:
        print(line)

回答by Tiago Lopo

This is an old post but this may help someone who enjoys working on command line like myself:

这是一篇旧帖子,但这可能会帮助像我这样喜欢在命令行上工作的人:

The perlone-liner below will remove all comments:

下面的perl一行将删除所有评论:

perl -0pe 's|//.*?\n|\n|g; s#/\*(.|\n)*?\*/##g;' test.java

Example:

例子:

cat test.java
this is a test

/**
*This should be removed
*This should be removed
*/

this should not be removed

//this should be removed

this should not be removed

this should not be removed //this should be removed

Output:

输出:

perl -0pe 's#/\*\*(.|\n)*?\*/##g; s|//.*?\n|\n|g' test.java
this is a test



this should not be removed



this should not be removed

this should not be removed 

If you want get rid of multiple blank lines as well:

如果您还想摆脱多个空行:

perl -0pe 's|//.*?\n|\n|g; s#/\*(.|\n)*?\*/##g; s/\n\n+/\n\n/g' test.java
this is a test

this should not be removed

this should not be removed

this should not be removed 

EDIT:Corrected regex

编辑:更正正则表达式

回答by Auslay

If you are using Eclipse IDE, you could make regex do the work for you.

如果您使用 Eclipse IDE,您可以让正则表达式为您完成这项工作。

Open the search window (Ctrl+F), and check 'Regular Expression'.

打开搜索窗口 (Ctrl+F),然后选中“正则表达式”。

Provide the expression as /\*\*(?s:(?!\*/).)*\*/

提供表达式为 /\*\*(?s:(?!\*/).)*\*/

Prasanth Bhate has explained it in Tool to remove JavaDoc comments?

Prasanth Bhate 在删除 JavaDoc 注释的工具中对此进行了解释

回答by MartinL

you can try it with the java-comment-preprocessor:

你可以用 java-comment-preprocessor 试试:

java -jar ./jcp-6.0.0.jar --i:/sourceFolder --o:/resultFolder -ef:none --r

source

来源

回答by Ertu?rul ?etin

I made a open source libraryand uploaded to github, its called CommentRemover you can remove single line and multiple line Java Comments.

我做了一个开源上传到github,它叫CommentRemover,可以删除单行和多行Java注释。

It supports remove or NOT remove TODO's.
Also it supports JavaScript , HTML , CSS , Properties , JSP and XML Comments too.

它支持删除或不删除 TODO。
它还支持 JavaScript 、 HTML 、 CSS 、 Properties 、 JSP 和 XML 注释。

There is a little code snippet how to use it (There is 2 type usage):

有一个小代码片段如何使用它(有 2 种用法):

First way InternalPath

第一种方式InternalPath

 public static void main(String[] args) throws CommentRemoverException {

 // root dir is: /Users/user/Projects/MyProject
 // example for startInternalPath

 CommentRemover commentRemover = new CommentRemover.CommentRemoverBuilder()
        .removeJava(true) // Remove Java file Comments....
        .removeJavaScript(true) // Remove JavaScript file Comments....
        .removeJSP(true) // etc.. goes like that
        .removeTodos(false) //  Do Not Touch Todos (leave them alone)
        .removeSingleLines(true) // Remove single line type comments
        .removeMultiLines(true) // Remove multiple type comments
        .startInternalPath("src.main.app") // Starts from {rootDir}/src/main/app , leave it empty string when you want to start from root dir
        .setExcludePackages(new String[]{"src.main.java.app.pattern"}) // Refers to {rootDir}/src/main/java/app/pattern and skips this directory
        .build();

 CommentProcessor commentProcessor = new CommentProcessor(commentRemover);
                  commentProcessor.start();        
  }

Second way ExternalPath

第二种方式 ExternalPath

 public static void main(String[] args) throws CommentRemoverException {

 // example for externalInternalPath

 CommentRemover commentRemover = new CommentRemover.CommentRemoverBuilder()
        .removeJava(true) // Remove Java file Comments....
        .removeJavaScript(true) // Remove JavaScript file Comments....
        .removeJSP(true) // etc..
        .removeTodos(true) // Remove todos
        .removeSingleLines(false) // Do not remove single line type comments
        .removeMultiLines(true) // Remove multiple type comments
        .startExternalPath("/Users/user/Projects/MyOtherProject")// Give it full path for external directories
        .setExcludePackages(new String[]{"src.main.java.model"}) // Refers to /Users/user/Projects/MyOtherProject/src/main/java/model and skips this directory.
        .build();

 CommentProcessor commentProcessor = new CommentProcessor(commentRemover);
                  commentProcessor.start();        
  }

回答by Bernhard Stadler

You can remove all single- or multi-line block comments (but not line comments with //) by searching for the following regular expression in your project(s)/file(s) and replacing by $1:

您可以//通过在您的项目/文件中搜索以下正则表达式并替换为来删除所有单行或多行块注释(但不是带有 的行注释)$1

^([^"\r\n]*?(?:(?<=')"[^"\r\n]*?|(?<!')"[^"\r\n]*?"[^"\r\n]*?)*?)(?<!/)/\*[^\*]*(?:\*+[^/][^\*]*)*?\*+/

^([^"\r\n]*?(?:(?<=')"[^"\r\n]*?|(?<!')"[^"\r\n]*?"[^"\r\n]*?)*?)(?<!/)/\*[^\*]*(?:\*+[^/][^\*]*)*?\*+/

It's possible that you have to execute it more than once.

您可能必须多次执行它。

This regular expression avoids the following pitfalls:

此正则表达式避免了以下陷阱:

  1. Code between two comments /* Comment 1 */ foo(); /* Comment 2 */

  2. Line comments starting with an asterisk: //***NOTE***

  3. Comment delimiters inside string literals: stringbuilder.append("/*");; also if there is a double quote inside single quotes before the comment

  1. 两个注释之间的代码 /* Comment 1 */ foo(); /* Comment 2 */

  2. 以星号开头的行注释: //***NOTE***

  3. 字符串文字中的注释分隔符:stringbuilder.append("/*");; 如果注释前的单引号内有双引号

To remove all single-line comments, search for the following regular expression in your project(s)/file(s) and replacing by $1:

要删除所有单行注释,请在您的项目/文件中搜索以下正则表达式并替换为$1

^([^"\r\n]*?(?:(?<=')"[^"\r\n]*?|(?<!')"[^"\r\n]*?"[^"\r\n]*?)*?)\s*//[^\r\n]*

^([^"\r\n]*?(?:(?<=')"[^"\r\n]*?|(?<!')"[^"\r\n]*?"[^"\r\n]*?)*?)\s*//[^\r\n]*

This regular expression also avoids comment delimiters inside double quotes, but does NOT check for multi-line comments, so /* // */will be incorrectly removed.

这个正则表达式也避免了双引号内的注释分隔符,但不检查多行注释,因此/* // */会被错误地删除。

回答by Nabuska

This is what I came up with yesterday. This is actually homework I got from school so if anybody reads this and finds a bug before I turn it in, please leave a comment =)

这是我昨天想到的。这实际上是我从学校得到的作业,所以如果有人在我上交之前阅读了这篇文章并发现了错误,请发表评论 =)

ps. 'FilterState' is a enum class

附:'FilterState' 是一个枚举类

public static String deleteComments(String javaCode) {
    FilterState state = FilterState.IN_CODE;

    StringBuilder strB = new StringBuilder();

    char prevC=' ';
    for(int i = 0; i<javaCode.length(); i++){
        char c = javaCode.charAt(i);
        switch(state){
            case IN_CODE:
                if(c=='/')
                    state = FilterState.CAN_BE_COMMENT_START;
                else {
                    if (c == '"')
                        state = FilterState.INSIDE_STRING;
                    strB.append(c);
                }
                break;
            case CAN_BE_COMMENT_START:
                if(c=='*'){
                    state = FilterState.IN_COMMENT_BLOCK;
                }
                else if(c=='/'){
                    state = FilterState.ON_COMMENT_LINE;
                }
                else {
                    state = FilterState.IN_CODE;
                    strB.append(prevC+c);
                }
                break;
            case ON_COMMENT_LINE:
                if(c=='\n' || c=='\r') {
                    state = FilterState.IN_CODE;
                    strB.append(c);
                }
                break;
            case IN_COMMENT_BLOCK:
                if(c=='*')
                    state=FilterState.CAN_BE_COMMENT_END;
                break;
            case CAN_BE_COMMENT_END:
                if(c=='/')
                    state = FilterState.IN_CODE;
                else if(c!='*')
                    state = FilterState.IN_COMMENT_BLOCK;
                break;
            case INSIDE_STRING:
                if(c == '"' && prevC!='\')
                    state = FilterState.IN_CODE;
                strB.append(c);
                break;
            default:
                System.out.println("unknown case");
                return null;
        }
        prevC = c;
    }
    return strB.toString();
}

回答by Ankit Arora

public class TestForStrings {

公共类 TestForStrings {

/**
 * The main method.
 *
 * @param args
 *            the arguments
 * @throws Exception
 *             the exception
 */
public static void main(String args[]) throws Exception {

    String[] imports = new String[100];
    String fileName = "Menu.java";
    // This will reference one API at a time
    String line = null;
    try {
        FileReader fileReader = new FileReader(fileName);
        // Always wrap FileReader in BufferedReader.
        BufferedReader bufferedReader = new BufferedReader(fileReader);
        int startingOffset = 0;

        // This will reference one API at a time

        List<String> lines = Files.readAllLines(Paths.get(fileName),
                Charset.forName("ISO-8859-1"));

        // remove single line comments
        for (int count = 0; count < lines.size(); count++) {
            String tempString = lines.get(count);

            lines.set(count, removeSingleLineComment(tempString));

        }
        // remove multiple lines comment
        for (int count = 0; count < lines.size(); count++) {
            String tempString = lines.get(count);

            removeMultipleLineComment(tempString, count, lines);
        }

        for (int count = 0; count < lines.size(); count++) {
            System.out.println(lines.get(count));
        }
    } catch (FileNotFoundException ex) {
        System.out.println("Unable to open file '" + fileName + "'");
    } catch (IOException ex) {
        System.out.println("Error reading file '" + fileName + "'");
    } catch (Exception e) {

    }

}

/**
 * Removes the multiple line comment.
 *
 * @param tempString
 *            the temp string
 * @param count
 *            the count
 * @param lines
 *            the lines
 * @return the string
 */
private static List<String> removeMultipleLineComment(String tempString,
        int count, List<String> lines) {
    try {
        if (tempString.contains("/**") || (tempString.contains("/*"))) {
            int StartIndex = count;
            while (!(lines.get(count).contains("*/") || lines.get(count)
                    .contains("**/"))) {
                count++;
            }
            int endIndex = ++count;
            if (StartIndex != endIndex) {
                while (StartIndex != endIndex) {
                    lines.set(StartIndex, "");
                    StartIndex++;
                }
            }
        }

    } catch (Exception e) {
        // Do Nothing
    }
    return lines;
}

/**
 * Remove single line comments .
 *
 * @param line
 *            the line
 * @return the string
 * @throws Exception
 *             the exception
 */

private static String removeSingleLineComment(String line) throws Exception {
    try {
        if (line.contains(("//"))) {
            int startIndex = line.indexOf("//");
            int endIndex = line.length();
            String tempoString = line.substring(startIndex, endIndex);
            line = line.replace(tempoString, "");
        }
        if ((line.contains("/*") || line.contains("/**"))
                && (line.contains("**/") || line.contains("*/"))) {
            int startIndex = line.indexOf("/**");
            int endIndex = line.length();
            String tempoString = line.substring(startIndex, endIndex);

            line = line.replace(tempoString, "");

        }

    } catch (Exception e) {
        // Do Nothing
    }
    return line;
}

}

}