5

I want to remove/comment all the occurrences of System.out.println from my java code. This System.out.println may be inside if ,if else,for, while or any where. I cannot do it manually due to large source code files.

Please help me automate this process. Is there any refactoring tool available for this task? Can I use eclipse JDT for this?

Snehika
  • 51
  • 1
  • 4
  • The best (and clunky) solution is to grab some Java code parser and analyze the program, and strip off the System.out.println. Another less foolproof solution is to construct a regex that matches println statement and exclude the tricky cases (I'm quite sure some people will try to do this, but the success will vary a lot). – nhahtdh Dec 26 '12 at 18:04
  • @nhahtdh:I have used regex but failed for some cases such as if(condition) sop(); – Snehika Dec 26 '12 at 18:07
  • Information about the IDE you use and the OS would be useful. – MrSmith42 Dec 26 '12 at 18:07
  • @MrSmith42 I am using Windows 7 and eclipse ide – Snehika Dec 26 '12 at 18:56
  • @nhahtdh Can you please suggest me the parser to use? and also how to use it? – Snehika Dec 26 '12 at 18:59
  • @user1930395: You need to spend quite some time learning the API and do some serious coding. If you have time on your hand, you can take a look at Eclipse JDT ASTParser. – nhahtdh Dec 26 '12 at 19:01

7 Answers7

6

Update

As mentioned here create a 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) {}

    } );
}

and replace System.out.print with DevNull.out.print

and later switch to logging framework that will allow you to handle stuff easily


Linked

Community
  • 1
  • 1
jmj
  • 237,923
  • 42
  • 401
  • 438
3

You could use raw find/replace functionality in source code files to comment out (or remove) statements, but whatever regular expression can be easily broken, so maybe you'd better be aware of logging frameworks like log4j or slf4j.

Big picture first: instead of using the usual System.out.println(), you'll end up using a line of code like:

logger.debug("Just entered main");

The logging framework can be configured with a simple property file, so you can have multiple appenders (console, file, database, whatever) and shut down each one separately on demand (for example the console appender). To switch to a logging API you still have to perform raw find/replace on source files, and possibly fix a couple of things by hand, either whithin your IDE, or with a command like:

find src/ -name '*.java' | \
xargs sed -i -e 's/System.out.println/logger.verbose/g'
Raffaele
  • 20,627
  • 6
  • 47
  • 86
  • 1
    I think this is a good solution - replacing the println with logging functionality. Although the solution can trip, the case that it would is pretty weird actually. So upvoted. – nhahtdh Dec 26 '12 at 18:07
  • Thanks @nhahtdh. I agree that *sed* is not a refactoring tool, and I always discourage regex's when they don't fix perfectly. This time I think it's a good devtime/robustness tradeoff, because this is not a program intended to be run multiple times on different input sources, but a single shot to quickly refactor his codebase, and then throw the tool away – Raffaele Dec 26 '12 at 18:14
  • @Raffaele I do not want to replace with logwriters since System.outs were put just for debugging purpose and they must be removed. – Snehika Dec 26 '12 at 18:50
  • 1
    @user1930395 I outlined the pros and cons of my solution and of your proposal. Debug statements are needed not only for further development, but also **in production**. What if later something doesn't work? You'd have to make change to your code and patch it live. With a logging framework you can turn appenders on and off, and you can specify a logging level (debug, verbose, info) - but you are entitled to do whatever you want. I think you have the opportunity to improve as a developer here, but feel free to use println's in your code and remove them at deploy – Raffaele Dec 26 '12 at 18:56
2

In case you do not use IDE, on Linux:

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

on Windows you can do the same if you have a cygwin installed.

aviad
  • 8,229
  • 9
  • 50
  • 98
2

As Jigar Joshi said, using find & replace approach might help you a lot, especially if you don't interfere the code apart from System.out.println.

I would propose a different solution if editing/changing the source code is not MUST for you. You can disable the System.out stream in your driver program, then nothing will be printed by these statements. You only need to set it like this:

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
  • 237,923
  • 42
  • 401
  • 438
Juvanis
  • 25,802
  • 5
  • 69
  • 87
1

I've used the jEdit text editor to accomplish tasks like this. There are probably other text editors that can do the same, the important feature is find and replace searching through directories/subdirectories.

  1. Open up a find and replace dialogue.
  2. Make sure the search folders and subdirectories options are checked. Again, this is the key to getting things handled across your entire project.
  3. Write "System.out.println" in the find field. Write a regular expression to handle the arguments.
  4. Write //System.out.println or perhaps more safely "/*System.out.println*/" in the replace field (or just leave it blank if that's preferable). Use the regular expression matches to replace the original arguments to the function.
  5. I suggest you replace the first few occurrences manually to make sure everything is going as expected. Once you're convinced it is, hit replace all and celebrate.

I'm not a Java programmer, but this solution should work for any language. Hope that helps. Good luck!

Noah Dyer
  • 407
  • 5
  • 10
  • Doh! This was my first answer. Trying to be helpful, but I see that I've been marked down. I've read through the rules and such. If anyone would be willing to explain to me if this is because of the answer itself, or because of some convention I've broken, I'd be grateful. – Noah Dyer Dec 26 '12 at 18:18
  • +1. Your solution would work, maybe one Java lover gave you -1. – Tapas Bose Dec 26 '12 at 18:21
  • How would the replacement `"/System.out.println/"` work? `Write a regular expression to handle the arguments.` - does it match the whole statement? – nhahtdh Dec 26 '12 at 18:26
  • Sorry, @nhahtdh. That was me learning the editor. Didn't realize asterisks were special characters. Edited accordingly. – Noah Dyer Dec 26 '12 at 18:27
  • I was just remarking that a block comment might be more appropriate than a line comment, since it appears this code is used within more complex lines of code, not on its own line, or as the last characters in a line. – Noah Dyer Dec 26 '12 at 18:29
  • @NoahDyer: Matching argument to println statement might not be as easy as you think - if done without assumption. From your post, it seems the regex has to *match the whole println statement*, but your point 4 is a bit misleading. Your solution will fail when the if/for statement doesn't have braces. – nhahtdh Dec 26 '12 at 19:08
  • @nha I wrote a reply with examples that was too long. I've abbreviated it here. Is there a convention for private messaging or otherwise extending conversations like this? Anyhow, here's the gist of what I wrote. – Noah Dyer Dec 26 '12 at 20:08
  • I've been wrong many times before, but I don't think the hard part is writing the regex to handle what's surrounding the println() function, whether it's inside a condition or loop, etc. I think the difficult part is handling what's inside the arguments. For example, I believe "System.out.println\\(.+\\)" will match the desired text, so long as the argument to be printed isn't the return value of another function. If you need to handle that case, then you'd have to look for pairs of () within the argument, rather than just match the first ). – Noah Dyer Dec 26 '12 at 20:10
  • [^\\)]+ is probably more appropriate than .+\\), to handle any whitespace in strings, etc. To the original question, from a practical level, it might be beneficial to the 5-10 seconds per occurrence to manually step through each of the replacements even if there are hundreds, just to make sure nothing crazy is happening. If there are thousands, then it may be a better strategy to hit that replace all button and then fix any mishaps. – Noah Dyer Dec 26 '12 at 20:23
  • @NoahDyer: It is safer(?) to match `S.o.p\([\s\S]*?\);` since this would only break if `);` appear in a string. The thing is the code OP is working with does not follow coding guideline - so it is very messy to be fixed by matching and commenting/removing (that's why you have to care its surrounding). Stepping through all the matches involves a lot of manual labor. Of course it works, but not the ideal solution (though it is usually the solution one takes up when one cannot find a good tool and are lazy to write one oneself). – nhahtdh Dec 27 '12 at 04:00
0

Do a simple find and replace. That should do.

Ivo
  • 450
  • 3
  • 18
  • What to do for this then for(int i=0;i<10;i++){ System.out.println("XYZ"); } – Snehika Dec 26 '12 at 18:01
  • Which IDE / editor provide find/replace spanning over all source-files? – MrSmith42 Dec 26 '12 at 18:06
  • If u search and replace `(System.out.println("XYZ"); for //System.out.println("XYZ");)` it doesnt matter if the print is inside a loop. – Ivo Dec 26 '12 at 18:06
  • @Ivo: It does make a difference: The closing brace will be commented out. – nhahtdh Dec 26 '12 at 18:13
  • @Ivo ok now consider about if else scenario without brackets if(condition) sop();//To be commented Some other code statement; – Snehika Dec 26 '12 at 19:02
0

You can make all System.out.println in your application not to print anything in console. Create a class like:

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;
   }
}

Use it as:

public class Test {

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

The will not be printed anymore.

Tapas Bose
  • 28,796
  • 74
  • 215
  • 331