【问题标题】:Find the location in code of a system.out.println在 system.out.println 的代码中查找位置
【发布时间】:2014-09-07 15:07:21
【问题描述】:

假设我在一个非常大的项目中工作,并且注意到一个空打印行,所以我假设有一个 System.out.println("");位于代码中的某处。除了在整个项目中搜索所有出现的 System.out.println 之外,我将如何尝试找出它在哪里?

【问题讨论】:

  • 在项目范围内搜索 System.out.println .. 你在使用像 Eclipse 这样的 IDE 吗?
  • 我是,但我正在尝试找出更好的方法,因为这似乎经常发生,并且整个代码库中有大量的 syso。
  • 听起来您需要一个项目范围的“调试”机制......并且您希望完全删除 System.out.println(在您实现的“调试”类或“输出”类之外。

标签: java reflection


【解决方案1】:

您可以实现自己的PrintStream 并使用System.setOut 替换默认的标准输出。然后要么在类里面放一个调试标记(如果打印的是空字符串),要么通过调用栈打印出方法名(抛出并捕获异常并获取栈信息)。

【讨论】:

  • 有没有办法在不抛出异常的情况下得到它?
  • 异常只是用来获取stacktrace(虽然应该有更直接的获取方式)。
  • stackoverflow.com/questions/1069066/… 这详细说明了一种无一例外的方法。谢谢!
【解决方案2】:

如果您使用的是 Java 8+,Durian 有一个 StackDumper 类,可以轻松找到给定行的打印位置:

StackDumper.dumpWhenSysOutContains("SomeTrigger")

当打印“SomeTrigger”时,这将被转储到System.err

+----------\
| Triggered by SomeTrigger
| at package.MyClass.myMethod(MyClass.java:62)
| (the rest of the stacktrace)
+----------/

对于你的情况(寻找一个空字符串),它有点复杂:

PrintStream sysOutClean = System.out;
StringPrinter sysOutReplacement = new StringPrinter(StringPrinter.stringsToLines(line -> {
    if (line.isEmpty()) {
        StackDumper.dump("Found empty line");
    }
    sysOutClean.println(line);
}));
System.setOut(sysOutReplacement.toPrintStream());

现在如果有这样的事情:

System.out.println("ABC");
System.out.println("123");
System.out.println("");
System.out.println("DEF");

然后您的控制台将如下所示:

ABC
123
+----------\
| Found empty line
| at package.MyClass.myMethod(MyClass.java:62)
| (the rest of the stacktrace)
+----------/

DEF

【讨论】:

  • 这非常适合查找其他人不必要添加的打印行,并且没有任何我可以搜索的文本(只是将对象传递给字符串)。我如何在不使用 Maven 的情况下使用 Durian 的无耻插件:stackoverflow.com/questions/37171460/…
【解决方案3】:

例子:

/** Control sysout prints */
public static void main(String[] arg) throws Exception {
     System.out.println("Default"); //print normally

     SysOutController.setSysOutLocationAddressor();
     System.out.println("With Address"); //prints with calling location, and on click location cursor directly focus when System.out.**() called

     SysOutController.ignoreSysout();
     System.out.println("Ignored"); //this line will never prints

     SysOutController.resetSysOut();
     System.out.println("Default"); //print normally as it is (reset)
}

只需调用下面类的方法,方便开发者控制sysout

import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;

/** 
 * Class which controls System.out prints in console <br/>
 * this class will helps developers to control prints in console
 * @implSpec
 * <pre><code>
 * System.out.println("Default"); //print normally
 * 
 * SysOutController.setSysOutLocationAddressor();
 * System.out.println("With Address"); //prints with calling location
 * 
 * SysOutController.ignoreSysout();
 * System.out.println("Ignored"); //this line will never prints
 * 
 * SysOutController.resetSysOut();
 * System.out.println("Default"); //print normally as it is (reset)
 * </code></pre>
 * @author Dharmendrasinh Chudasama
 */
public class SysOutController {

    private static void setOut(OutputStream out){
        System.setOut(new PrintStream(out));
    }

    private static final OutputStream CONSOLE = new FileOutputStream(FileDescriptor.out);

    /**
     * Reset System.out.print* method
     * @author Dharmendrasinh Chudasama
     */
    public static void resetSysOut() { setOut(CONSOLE); }

    /**
     * System.out.print* will not print anything in console
     * @author Dharmendrasinh Chudasama
     */
    public static void ignoreSysout() {
        setOut(new OutputStream() {
            @Override public void write(int b) throws IOException {}
        });
    }

    /**
     * Address/location of calling System.out.* method will append in console
     * @author Dharmendrasinh Chudasama
     */
    public static void setSysOutLocationAddressor() {
        setOut(new OutputStream() {
            @Override
            public void write(int b) throws IOException {
                if(b=='\n'){ //if newLine
                    final StackTraceElement callerStEl = new Throwable().getStackTrace()[9];
                    String pathData =
                        "\u001B[37m"    //low-visibality
                        + "\t :: ("+callerStEl.getFileName()+":"+callerStEl.getLineNumber()+") ["+callerStEl+"]"  //code path
                        + "\u001B[0m ";  //reset
                    CONSOLE.write(pathData.getBytes());

                }

                CONSOLE.write(b);
            }
        });
    }
}

【讨论】:

    【解决方案4】:

    这也可能是某些库的原因,如果您觉得只是 System.out.println 的原因,那么,

    解决方案 1: 下面的代码 sn-p 应该可以帮助您找出执行它的位置。

            import java.io.FileNotFoundException;
            import java.io.PrintStream;
    
            public class CustomPrintStream extends PrintStream {
    
            public CustomPrintStream(String fileName) throws FileNotFoundException {
                super(fileName);
            }
    
                @Override
                public void print(String s) {
    
                    try{
                        if(s == null || s.equals("")){
                            throw new Exception("Invalid print message");
                        }
                        super.print(s);
                    }catch(Exception e){
                        //TODO Change to your logger framework and leave it as same 
                        e.printStackTrace();
                    }
                }
    
                public static void main(String[] args) {
                    try {
     //TODO : Change to your favorite path and make sure mentioned
    //file is available
                        CustomPrintStream customPrintStream = new CustomPrintStream
        ("/home/prem/Desktop/test.log");
                        System.setOut(customPrintStream);
                        System.out.println("");
    
                    } catch (FileNotFoundException e) {
                        //TODO Change to your logger framework and leave it as same 
                        e.printStackTrace();
                    }
                }
            }
    

    解决方案 2: 由于 IDE 可用,请从他们那里获得帮助。如果您使用的是 eclipse 菜单 -> 搜索 -> 文件搜索-> 放置 System.out.println("");在包含搜索和搜索它。

    我宁愿不要在任何代码中使用 System.out.println,您可以使用 checkstyle 并确信从此没有开发人员使用它们。

    【讨论】:

      【解决方案5】:

      定义一个类 NewPrintStream 扩展 PrintStream

      import java.io.FileNotFoundException;
      import java.io.PrintStream;
      import org.slf4j.Logger;
      import org.slf4j.LoggerFactory;
      
      public class NewPrintStream extends PrintStream {
        private static final Logger LOGGER = LoggerFactory.getLogger(NewPrintStream.class);
      
        public NewPrintStream(String fileName) throws FileNotFoundException {
          super(fileName);
        }
      
        @Override
        public void println(String x) {
          LOGGER.info("xxxxxxx", new Exception("xxxx"));
        }
      }
      

      然后在主类中设置stdout/stderr打印流

      System.setOut(new NewPrintStream("aaa"));
      System.setErr(new NewPrintStream("aaa"));
      

      【讨论】:

        【解决方案6】:

        PrintStream.println(String x) 中放置一个条件断点,条件设置为x.equals("") 或任何您的字符串。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-12-22
          • 2021-11-01
          • 2013-10-18
          • 1970-01-01
          • 2014-04-13
          • 2013-03-22
          • 1970-01-01
          • 2023-04-01
          相关资源
          最近更新 更多