Find the location in code of a system.out.println - java

Lets say I'm working in a very large project, and have noticed an empty print line, so I'm assuming there is a System.out.println(""); located somewhere in the code. How would I go about trying to figure out where it is, short of just searching the entire project for all occurrences of System.out.println?

If you're using Java 8+, Durian has a StackDumper class which makes it easy to find where a given line is being printed:
StackDumper.dumpWhenSysOutContains("SomeTrigger")
When "SomeTrigger" is printed, this will get dumped to System.err:
+----------\
| Triggered by SomeTrigger
| at package.MyClass.myMethod(MyClass.java:62)
| (the rest of the stacktrace)
+----------/
For your case (looking for an empty string), it's a little more complicated:
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());
Now if there's something like this:
System.out.println("ABC");
System.out.println("123");
System.out.println("");
System.out.println("DEF");
Then your console will look like this:
ABC
123
+----------\
| Found empty line
| at package.MyClass.myMethod(MyClass.java:62)
| (the rest of the stacktrace)
+----------/
DEF

You could implement your own PrintStream and use System.setOut to replace the default stdout. Then either put a debugging marker inside the class (if an empty string is printed), or print out the method name through the call stack (throw and catch an exception and get the stack information).

Example:
/** 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)
}
Just call methods of following class, which helps developers to controll 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);
}
});
}
}

This can be due to some of the library also,if you feel that it is because of only System.out.println then,
Solution 1 :
Below code snippet should help you to find out the place where it is getting executed.
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();
}
}
}
Solution 2 :
Since IDE's are available,please get the help from them.If you are using eclipse
Menu -> Search - > File Search-> Place System.out.println(""); in containing search and search for it.
I would rather say not to use the System.out.println in any of the code,for which you can make use of checkstyle and be confident that hence forth no developers use them.

Define a class NewPrintStream extends 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"));
}
}
Then in main class set stdout/stderr print stream
System.setOut(new NewPrintStream("aaa"));
System.setErr(new NewPrintStream("aaa"));

Put a conditional breakpoint in PrintStream.println(String x) with the condition set to x.equals("") or whatever your string may be.

Related

How to pass a file name as parameter, create and then read the file

I have a method as follows:
public(String input_filename, String output_filename)
{
//some content
}
how to create an input_filename at run time and read the input_filename .I have to pass input_filename as a parameter
Please be patient as I am new to Java
Here a complete sample:
Save it as Sample.java
compile it with: javac Sample.java
run it with: java Sample "in.txt" "out.txt"
or: java Sample
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
public class Sample {
public static void main(String[] args) throws IOException {
if(args.length == 2)
{
doFileStuff(args[0],args[1]);
}
else {
doFileStuff("in.txt","out.txt");
}
}
public static void doFileStuff(String input_filename, String output_filename) throws IOException {
if(!Files.exists(Paths.get(input_filename)))
{
System.err.println("file not exist: " + input_filename);
return;
}
if(!Files.exists(Paths.get(output_filename)))
{
System.err.println("file still exist, do not overwrite it: " + output_filename);
return;
}
String content = new String(Files.readAllBytes(Paths.get(input_filename)));
content += "\nHas added something";
Files.write(Paths.get(output_filename), content.getBytes(StandardCharsets.UTF_8));
}
}
I'm unsure what you want to do with this method, but I hope this can help you a bit.
If you want inputs during runtime, use the Scanner class. A guide on how to use it here
Also if you want an output in your class you should use "return", and not have it as a parameter.
Do note that you haven't named your class yet, or specified the output type.
How it could look:
public String className(String input){
return input;
}

Java - Unable to create a file

I am in a Linux Envirnomnet. I am also using Netbeans. Here is my code below:
import java.io.*;
public class myFirstJavaProgram {
public static void main(String[] args) {
File file = new File("home/gk/Hello1.txt");
// creates the file
file.createNewFile();
// creates a FileWriter Object
}
}
You forgot a slash before home. It is looking for a folder that most likely does not exist inside the classpath.
EDIT
After you pointed out the exception you were receiving I realized that a checked exception is not being handled. You need to catch the possible IOException or include the exception in the method signature.
import java.io.*;
/**
*
* #author Ashwin Parmar
*/
public class myFirstJavaProgram {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
try {
File file = new File("/home/gk/Hello1.txt");
file.createNewFile();
} catch(IOException e) {
System.out.println(e.getMessage());
}
// creates a FileWriter Object
}
}
When dealing with any File IO action in Java, it is always best to use a try/catch loop
Error in your path.
This home/gk/Hello1.txt should be /home/gk/Hello1.txt

How to detect each JavaDoc block start-and-end line in a source-code file?

I am creating a parsing utility, to read through a (duplicate of a) Java source-code file, and re-output it with some extra information inserted at certain points in the JavaDoc blocks.
The first step was to figure out where each JavaDoc block begins and ends. Below is the code I wrote to do that.
I hope this helps somebody.
This takes the path to a Java source-code file, and outputs the start and end lines for each found JavaDoc block.
import java.io.File;
import java.io.IOException;
import java.util.regex.Pattern;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.LineIterator;
import xbn.io.RTIOException;
/**
<P>Prints the start and end line-numbers for all JavaDoc blocks in a Java source-code file. The one and only parameter is the path to the file. This assumes that the JavaDoc open-comment (slash-asterisk-asterisk) is the first non-whitespace on its line. The end comment (asterisk-slash) may be anywhere on the line.</P>
java PrintJDBlocksStartStopLineNumsXmpl C:\java_code\PrintJDBlocksStartStopLineNumsXmpl.java
**/
public class PrintJDBlocksStartStopLineNumsXmpl {
/**
<P>The main function.</P>
**/
public static final void main(String[] as_1RqdJavaSourcePath) {
//Read command-line parameter
String sJPath = null;
try {
sJPath = as_1RqdJavaSourcePath[0];
} catch(ArrayIndexOutOfBoundsException aibx) {
throw new NullPointerException("Missing one-and-only required parameter: Path to java source-code file.");
}
System.out.println("Java source: " + sJPath);
//Establish line-iterator
LineIterator li = null;
try {
li = FileUtils.lineIterator(new File(sJPath)); //Throws npx if null
} catch(IOException iox) {
throw new RTIOException("PrintJDBlocksStartStopLinesXmpl", iox);
}
Pattern pTrmdJDBlockStart = Pattern.compile("^[\\t ]*/\\*\\*");
String sDD = "..";
int iLn = 1;
boolean bInJDBlock = false;
while(li.hasNext()) {
String sLn = li.nextLine();
if(!bInJDBlock) {
if(pTrmdJDBlockStart.matcher(sLn).matches()) {
bInJDBlock = true;
System.out.print(iLn + sDD);
}
} else if(sLn.indexOf("*/") != -1) {
bInJDBlock = false;
System.out.println(iLn);
}
iLn++;
}
if(bInJDBlock) {
throw new IllegalStateException("Reach end of file. JavaDoc not closed.");
}
}
/**
<P>Another one</P>
**/
private static final void oneMoreForGoodMeasure() {
}
}
Output:
[C:\java_code]java PrintJDBlocksStartStopLineNumsXmpl C:\java_code\PrintJDBlocksStartStopLineNumsXmpl.java
Java source: C:\java_code\PrintJDBlocksStartStopLineNumsXmpl.java
8..12
14..16
54..56
My original answer was the first step in creating FilteredLineIterator.
FilteredLineIterator filters another string iterator (which is normally the lines in a text file), keeping or discarding each line based on the entities in which it exists: "blocks", "single line" and "stealth block" entities. Each kept line may be altered.
(FilteredLineIterator is part of XBN-Java. Download the necessary jars here.)
The following example declares a "JavaDoc block" block entity, and a "Java multi-line comment" stealth entity. The stealth entity is necessary to avoid the final line in non-JavaDoc comment blocks from incorrectly causing "end line found before block opened" errors (since both JavaDoc and non-JavaDoc comment blocks end with */).
import com.github.xbn.linefilter.entity.KeepMatched;
import com.github.xbn.linefilter.entity.EntityRequired;
import com.github.xbn.linefilter.FilteredLineIterator;
import com.github.xbn.linefilter.KeepUnmatched;
import com.github.xbn.linefilter.Returns;
import com.github.xbn.linefilter.entity.BlockEntity;
import com.github.xbn.linefilter.entity.NewBlockEntityFor;
import com.github.xbn.linefilter.entity.NewStealthBlockEntityFor;
import com.github.xbn.linefilter.entity.StealthBlockEntity;
import com.github.xbn.testdev.GetFromCommandLineAtIndex;
import com.github.xbn.util.IncludeJavaDoc;
import java.util.Iterator;
/**
<P>{#code java PrintAllJavaDocBlockStartAndEndLineNums C:\java_code\example_input\JavaClassWithOneCommentAndTwoJavaDocBlocks_input.txt}</P>
**/
public class PrintAllJavaDocBlockStartAndEndLineNums {
public static final void main(String[] cmd_lineParams) {
//Example setup
Iterator<String> itr = GetFromCommandLineAtIndex.fileLineIterator(
cmd_lineParams, 0,
null); //debugPath
Example proper:
StealthBlockEntity javaMlcStealth = NewStealthBlockEntityFor.javaComment(
"comment", IncludeJavaDoc.NO,
null, //dbgStart (on:System.out, off:null)
null, //dbgEnd
KeepMatched.YES, EntityRequired.YES, null,
null); //dbgLineNums
BlockEntity javaDocBlock = NewBlockEntityFor.javaDocComment_Cfg(
"doccomment",
null, //dbgStart
null, //dbgEnd
EntityRequired.YES, null,
null). //dbgLineNums
keepAll().build();
FilteredLineIterator filteredItr = new FilteredLineIterator(
itr, Returns.KEPT, KeepUnmatched.NO,
null, null, //dbgEveryLine and its line-range
javaMlcStealth, javaDocBlock);
while(filteredItr.hasNext()) {
filteredItr.next();
if(filteredItr.getActiveChildType().isBlock() &&
filteredItr.getActiveChildBlock().isStartLine()) {
System.out.print("Block: " + filteredItr.getNextLineNum() + "..");
} else if(filteredItr.getActiveChildType().isBlock() &&
filteredItr.getActiveChildBlock().isEndLine()) {
System.out.println(filteredItr.getNextLineNum());
}
}
}
}
Output:
Block: 9..11
Block: 13..24
Block: 28..30
An alternative is to print the block line numbers with automated debugging:
BlockEntity javaDocBlock = NewBlockEntityFor.javaDocComment_Cfg(
"doccomment",
null, //dbgStart
null, //dbgEnd
EntityRequired.YES, null,
System.out). //<--Automated line-number debugging
keepAll().build();
FilteredLineIterator filteredItr = new FilteredLineIterator...
while(filteredItr.hasNext()) {
filteredItr.next();
}
Output:
[9:BLOCK:"doccomment"] block-start
[11:BLOCK:"doccomment":active] block end
[13:BLOCK:"doccomment"] block-start
[24:BLOCK:"doccomment":active] block end
[28:BLOCK:"doccomment"] block-start
[30:BLOCK:"doccomment":active] block end
Input file:
/*
Not a JavaDoc block. The following sub-mode is ignored, because it's not in a JavaDoc block.
//sub-mode...START
//sub-mode...END
*/
package fully.qualified.package.name;
/**
<P>A JavaDoc block</P>
*/
public class StayClassy {
/**
<P>Another JavaDoc block</P>
<P>info</P> //sub-mode...START
<P>info</P>
<P>info</P> //sub-mode...END
<P>info</P>
*/
public StayClassy() {
//Do stuff
}
/**
<P>Does stuff.</P>
*/
public void doStuff() {
}
}

Java - System.setOut does not save an exception message

It seems that System.setOut() does not work in this test case.
Here are problem description.
test0 executes System.setOut(new PrintStream(byteBuffer)) so that it stores standard output.
test0 invokes AddChild1_wy_v1.main.
In the AddChild1_wy_v1.main, xml.addChild(null) generates an exception message.
The exception message should be stored in byteBuffer, but it seems it wasn't.. JVM stops running the test case once the exception message pops up. And the remaining code after AddChild1_wy_v1.main are not executed.
Is there a way for jvm to execute the remaining code in test0?
NanoAddChild1_wy_v1Tests.java
package tests;
import junit.framework.TestCase;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import net.n3.nanoxml.*;
public class NanoAddChild1_wy_v1Tests extends TestCase {
public void test0() throws Exception { //addchild1.out
String result;
ByteArrayOutputStream byteBuffer;
byteBuffer = new ByteArrayOutputStream();
System.setOut(new PrintStream(byteBuffer));
AddChild1_wy_v1.main(new String[] {"/home/junghyun/Dev/nanoxml/inputs/simple.xml"});
result = new String(byteBuffer.toByteArray());
assertEquals(result, "Exception in thread \"main\" java.lang.IllegalArgumentException: child must not be null\n\tat net.n3.nanoxml.XMLElement.addChild(XMLElement.java:165)\n\tat AddChild1_wy_v1.main(AddChild1_wy_v1.java:47)\n");
}
}
AddChild1_wy_v1.java
package tests;
import net.n3.nanoxml.IXMLParser;
import net.n3.nanoxml.IXMLReader;
import net.n3.nanoxml.StdXMLReader;
import net.n3.nanoxml.XMLElement;
import net.n3.nanoxml.XMLParserFactory;
import net.n3.nanoxml.XMLWriter;
public class AddChild1_wy_v1
{
public static void main(String args[])
throws Exception
{
if (args.length == 0) {
System.err.println("Usage: java DumpXML file.xml");
Runtime.getRuntime().exit(1);
}
IXMLParser parser = XMLParserFactory.createDefaultXMLParser();
IXMLReader reader = StdXMLReader.fileReader(args[0]);
parser.setReader(reader);
XMLElement xml = (XMLElement) parser.parse();
xml.addChild (null);
(new XMLWriter(System.out)).write(xml);
}
}
There's 3 default streams:
System.in : InputStream
System.out :PrintStream
System.err :PrintStream
So to set each one there is 3 methods:
public static void setIn(InputStream in) {...}
public static void setOut(PrintStream out) {...}
public static void setErr(PrintStream err) {...}
To set System.err you must use System.setErr(yourStream);
For another question: you just need to use
try {
//throwing exception
} catch (Exception e) {
//act on exception
}
It seems to me that you never write that Exception at all.
You just throw it upwards. Try catch it and have ex.printStackTrace();
Also that will go to standard error, unless you specifically say otherwise.
As by your request I will leave the test0 method unaltered, you can use it the way it is.
in AddChild1_wy_v1.java:
public class AddChild1_wy_v1 {
public static void main(String args[]) // note that I don't throw the Exception.
{
try {
if (args.length == 0) {
System.err.println("Usage: java DumpXML file.xml");
Runtime.getRuntime().exit(1);
}
IXMLParser parser = XMLParserFactory.createDefaultXMLParser();
IXMLReader reader = StdXMLReader.fileReader(args[0]);
parser.setReader(reader);
XMLElement xml = (XMLElement) parser.parse();
xml.addChild (null);
(new XMLWriter(System.out)).write(xml);
} catch (Exception any) {
any.printStackTrace(System.out); // note that I send the Stack Trace to standard out here.
}
}
}
Wrap your method call in a try-catch to continue past the exception:
try {
AddChild1_wy_v1.main(...);
} catch(Throwable t) {
t.printStackTrace();
}
// the rest of your code will execute
Exceptions are printed to standard error, not standard output. Try System.setErr.
Never post images of your code.

Redirect console output to string in Java

I have one method whose return type is void and it prints directly on console.
However I need that output in a String so that I can work on it.
As I can't make any changes to the method with return type void I have to redirect that output to a String.
How can I redirect it in Java?
If the function is printing to System.out, you can capture that output by using the System.setOut method to change System.out to go to a PrintStream provided by you. If you create a PrintStream connected to a ByteArrayOutputStream, then you can capture the output as a String.
Example:
// Create a stream to hold the output
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(baos);
// IMPORTANT: Save the old System.out!
PrintStream old = System.out;
// Tell Java to use your special stream
System.setOut(ps);
// Print some output: goes to your special stream
System.out.println("Foofoofoo!");
// Put things back
System.out.flush();
System.setOut(old);
// Show what happened
System.out.println("Here: " + baos.toString());
This program prints just one line:
Here: Foofoofoo!
Here is a utility Class named ConsoleOutputCapturer. It allows the output to go to the existing console however behind the scene keeps capturing the output text. You can control what to capture with the start/stop methods. In other words call start to start capturing the console output and once you are done capturing you can call the stop method which returns a String value holding the console output for the time window between start-stop calls. This class is not thread-safe though.
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.Arrays;
import java.util.List;
public class ConsoleOutputCapturer {
private ByteArrayOutputStream baos;
private PrintStream previous;
private boolean capturing;
public void start() {
if (capturing) {
return;
}
capturing = true;
previous = System.out;
baos = new ByteArrayOutputStream();
OutputStream outputStreamCombiner =
new OutputStreamCombiner(Arrays.asList(previous, baos));
PrintStream custom = new PrintStream(outputStreamCombiner);
System.setOut(custom);
}
public String stop() {
if (!capturing) {
return "";
}
System.setOut(previous);
String capturedValue = baos.toString();
baos = null;
previous = null;
capturing = false;
return capturedValue;
}
private static class OutputStreamCombiner extends OutputStream {
private List<OutputStream> outputStreams;
public OutputStreamCombiner(List<OutputStream> outputStreams) {
this.outputStreams = outputStreams;
}
public void write(int b) throws IOException {
for (OutputStream os : outputStreams) {
os.write(b);
}
}
public void flush() throws IOException {
for (OutputStream os : outputStreams) {
os.flush();
}
}
public void close() throws IOException {
for (OutputStream os : outputStreams) {
os.close();
}
}
}
}
Although this question is very old and has already very good answers I want to provide an alternative. I created a library specifically for this use case. It is called Console Captor and you can add it with the following snippet:
<dependency>
<groupId>io.github.hakky54</groupId>
<artifactId>consolecaptor</artifactId>
<version>1.0.0</version>
<scope>test</scope>
</dependency>
Example class
public class FooService {
public void sayHello() {
System.out.println("Keyboard not responding. Press any key to continue...");
System.err.println("Congratulations, you are pregnant!");
}
}
Unit test
import static org.assertj.core.api.Assertions.assertThat;
import nl.altindag.console.ConsoleCaptor;
import org.junit.jupiter.api.Test;
public class FooServiceTest {
#Test
public void captureStandardAndErrorOutput() {
ConsoleCaptor consoleCaptor = new ConsoleCaptor();
FooService fooService = new FooService();
fooService.sayHello();
assertThat(consoleCaptor.getStandardOutput()).contains("Keyboard not responding. Press any key to continue...");
assertThat(consoleCaptor.getErrorOutput()).contains("Congratulations, you are pregnant!");
consoleCaptor.close();
}
}
If you are using Spring Framework, there is a really easy way to do this with OutputCaptureExtension:
#ExtendWith(OutputCaptureExtension.class)
class MyTest {
#Test
void test(CapturedOutput output) {
System.out.println("ok");
assertThat(output).contains("ok");
System.err.println("error");
}
#AfterEach
void after(CapturedOutput output) {
assertThat(output.getOut()).contains("ok");
assertThat(output.getErr()).contains("error");
}
}

Categories

Resources