从多个Java源文件中删除/注释掉System.out.println。

5
我想从我的Java代码中删除/注释所有出现的System.out.println。这个System.out.println可能在ifif elseforwhile或任何地方。由于源代码文件很大,我无法手动完成。
请帮助我自动化这个过程。是否有可用于此任务的重构工具?我可以使用Eclipse JDT吗?

最好的(也比较笨拙)解决方案是获取一些Java代码解析器并分析程序,然后剥离System.out.println。另一个不太可靠的解决方案是构建一个正则表达式来匹配println语句并排除棘手的情况(我相当确定有些人会尝试这样做,但成功的可能性会千差万别)。 - nhahtdh
@nhahtdh:我已经使用了正则表达式,但对于一些情况(如if(condition))失败了。 sop(); - Snehika
您使用的集成开发环境(IDE)和操作系统(OS)的信息将会很有用。 - MrSmith42
@MrSmith42 我正在使用Windows 7和Eclipse IDE。 - Snehika
@nhahtdh你能建议我使用哪个解析器吗?还有如何使用它? - Snehika
@user1930395:你需要花费相当多的时间学习API并进行一些严肃的编码。如果你有时间,可以看看Eclipse JDT ASTParser。 - nhahtdh
7个回答

6

更新

此处所述,创建一个空输出(NullOutPut)。

public final DevNull { 
    public final static PrintStream out = new PrintStream(new OutputStream() {
        public void close() {}
        public void flush() {}
        public void write(byte[] b) {}
        public void write(byte[] b, int off, int len) {}
        public void write(int b) {}

    } );
}

System.out.print替换为DevNull.out.print

稍后切换到日志框架,这将使您能够轻松处理内容


链接


我做不到。有些代码是像if(条件)sop else sop这样的。 - Snehika
假设代码如下: for(int i=0;i<10;i++){ System.out.println("XYZ"); } - Snehika

3
你可以在源代码文件中使用原始的查找/替换功能来注释掉(或删除)语句,但是任何正则表达式都很容易被破坏,所以也许最好了解一下像log4j或slf4j这样的日志框架。
首先看大局:与其使用通常的System.out.println(),你最终会使用类似以下的代码行:
logger.debug("Just entered main");

日志框架可以通过简单的属性文件进行配置,这样你就可以拥有多个appender(控制台、文件、数据库等),并在需要时单独关闭每个appender(例如控制台appender)。如果要切换到另一个日志API,仍然需要在源文件中执行原始查找/替换,并可能手动修复一些东西,在IDE内部或使用类似于以下命令的命令:

find src/ -name '*.java' | \
xargs sed -i -e 's/System.out.println/logger.verbose/g'

1
我认为这是一个不错的解决方案 - 用日志功能替换println。虽然这个解决方案可能会出现问题,但实际上它出问题的情况非常奇怪。所以我点了赞。 - nhahtdh
感谢@nhahtdh。我同意sed不是重构工具,当正则表达式不能完美解决问题时,我总是反对使用它们。但这一次,我认为这是一个很好的开发时间/健壮性权衡,因为这不是一个旨在多次运行于不同输入源上的程序,而是一个快速重构代码库的单次操作,然后就可以丢弃该工具了。 - Raffaele
@Raffaele 我不想用logwriters替换System.out,因为System.out只是为了调试目的而放置的,必须将其删除。 - Snehika
1
@user1930395,我概述了我的解决方案和你的建议的优缺点。调试语句不仅在进一步开发中需要,而且在生产环境中也是必要的。如果以后出现问题怎么办?您将不得不更改代码并进行实时修补。使用日志框架,您可以打开和关闭附加程序,并指定日志级别(调试、详细信息、信息)-但您有权做任何您想做的事情。我认为您在这里有机会成为一名更好的开发人员,但请随意在您的代码中使用println,并在部署时将其删除。 - Raffaele

2
如Jigar Joshi所说,使用“查找和替换”方法可能会对您有很大帮助,特别是如果您除了“System.out.println”之外不干涉代码。
如果您不必编辑/更改源代码,我将提出不同的解决方案。您可以在驱动程序中禁用“System.out”流,然后这些语句将不会打印任何内容。您只需要像这样设置:
System.setOut(new PrintStream(new OutputStream() {
    public void write(int b) {
        // No operation.
    }
    public void close() {}
    public void flush() {}
    public void write(byte[] b) {}
    public void write(byte[] b, int off, int len) {}
    public void write(int b) {}
}));

覆盖了其他方法。 - jmj
@JigarJoshi 由于这个原因会有任何性能损失吗? - Snehika
根据你写的内容多少,它应该会更快,因为它现在不会写任何东西。 - jmj

2

如果你不使用集成开发环境(IDE),在Linux上:

sed '/System.out.println/d' %YOUR_PROJ_DIR%/*.java

在Windows上,如果您安装了cygwin,则可以执行相同的操作。

当println跨越多行时,出现相同的问题。 - nhahtdh

1

我使用jEdit文本编辑器来完成这样的任务。可能还有其他文本编辑器可以做到同样的事情,重要的功能是在目录/子目录中查找和替换。

  1. 打开查找和替换对话框。
  2. 确保搜索文件夹和子文件夹选项已经被勾选。 再次强调,这是跨整个项目处理事务的关键。
  3. 在查找字段中写入"System.out.println"。编写一个正则表达式来处理参数。
  4. 在替换字段中写入//System.out.println或者更安全的"/*System.out.println*/"(如果需要的话也可以将其留空)。使用正则表达式匹配来替换函数的原始参数。
  5. 我建议您手动替换前几个出现的实例,以确保一切都按预期进行。一旦您确信它是正确的,请点击“全部替换”并庆祝。

虽然我不是Java程序员,但这个解决方案应该适用于任何语言。希望能帮到你。祝你好运!


糟糕!这是我的第一个答案。我试图提供帮助,但我看到我被评为负分。我已经仔细阅读了规则等内容。如果有人愿意向我解释,这是因为答案本身还是因为我违反了某些惯例,我将不胜感激。 - Noah Dyer
+1。你的解决方案是可行的,也许有一个Java爱好者给了你-1。 - Tapas Bose
抱歉,@nhahtdh。那是我在学习编辑器。没有意识到星号是特殊字符。已做出修改。 - Noah Dyer
@nha 我写了一个带有示例的回复,但太长了。我在这里进行了缩写。是否有私信或其他扩展此类对话的惯例?无论如何,这是我写的要点。 - Noah Dyer
我之前犯过很多错误,但我认为难点不在于编写正则表达式来处理println()函数周围的内容,无论它是在条件或循环内部等。我认为困难的部分是处理参数中的内容。例如,我相信"System.out.println\(.+\)"将匹配所需的文本,只要要打印的参数不是另一个函数的返回值。如果您需要处理该情况,则必须查找参数中的()对,而不仅仅是匹配第一个)。 - Noah Dyer
显示剩余5条评论

0

您可以使应用程序中的所有System.out.println不在控制台上打印任何内容。创建一个类似于:

import java.io.PrintStream;


public class MyStream extends PrintStream {
   private static final MyStream INSTANCE = new MyStream();

   public static void init() {
      System.setOut(INSTANCE);
   }

   private MyStream() {
      super(System.out);
   }

   @Override
   public void println(Object x) {
      return;
   }

   @Override
   public void println(String x) {
      return;
   }
}

使用方法如下:

public class Test {

    public static void main(String... args) {
        MyStream.init();
        System.out.println("This line will not print");
    }
}

这段代码将不再被打印出来。


@Raffaele 抱歉在发布之前没有看到他的解决方案。 - Tapas Bose

0

做一个简单的查找和替换。那就可以了。


那么针对这个问题应该怎么做呢? for(int i=0;i<10;i++){ System.out.println("XYZ"); } - Snehika
哪些IDE /编辑器提供跨越所有源文件的查找/替换功能? - MrSmith42
如果您搜索并替换 (System.out.println("XYZ");//System.out.println("XYZ");),即使打印语句在循环内部也没有关系。 - Ivo
@Ivo:这确实有所不同:结束大括号将被注释掉。 - nhahtdh
@Ivo 现在考虑一下没有括号的if else场景 if(条件)
sop();//待注释
其他一些代码语句;
- Snehika

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接