I am trying to read a from the input using BufferedReader. It works the first time but the second time it is ran I get an exception.
john#fekete:~/devel/java/pricecalc$ java frontend.CUI
> gsdfgd
Invalid command!
> I/O Error getting string: java.io.IOException: Stream closed
I/O Error: java.io.IOException: java.io.IOException: Stream closed
> I/O Error getting string: java.io.IOException: Stream closed
I/O Error: java.io.IOException: java.io.IOException: Stream closed
> I/O Error getting string: java.io.IOException: Stream closed
It just keeps running with that in a loop. I must have missed something.
public static void main(String args[]) {
if (args.length == 0) {
while (!exit) {
try {
exit = processLine(commandLine());
} catch (IOException e) {
System.out.println("I/O Error: " + e);
}
}
System.out.println("Bye!");
} else if (args.length == 1) {
String line = new String(args[0]);
processLine(line);
} else {
String line = new String(args[0]);
for (String np : args) {
line = new String(line + " " + np);
}
processLine(line);
}
}
static private String commandLine() throws IOException {
String str = new String();
try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in))) {
System.out.print("> ");
str = new String(br.readLine());
str = str.trim();
} catch (IOException e) {
System.out.println("I/O Error getting string: "+ str + " " + e);
throw new IOException(e);
}
return str;
}
It really all seems to be about commandLine() not working so I've just included that and main.
Yes, you're closing the stream here:
try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in)))
That try-with-resources statement will close the BufferedReader at the end of the block, which will close the InputStreamReader, which will close System.in.
You don't want to do that in this case, so just use:
// Deliberately not closing System.in!
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
try {
...
}
It's still possible that this won't quite behave as you want though, as the BufferedReader could potentially consume (and buffer) more data. You'd be better off creating the BufferedReader once (in the calling code) and passing it to the method.
Oh, and I suggest you get rid of this:
String str = new String();
There's no need for it at all. This would be better:
String str = "";
But even then, it's a pointless assignment. Likewise you don't need to create a new String from the one returned by readLine(). Just use:
return br.readLine().trim();
... within the try block. Also, there's no point in logging str within the catch block, as it's going to be empty - the IOException will only be thrown when reading the line...
Related
I was trying to implement this code but was getting some "Use try-with-resources or close this "BufferedReader" in a "finally" clause" in sonarqube i have already read other's answer but none of them helped me, so can anyone please guide me where exactly i have to do code changes(Really don't have any background for above error in sonarqube)
public static List getlockList(String componentPath) throws IOException
{
List<String> listOfLines = new ArrayList<String>();
BufferedReader bufReader = null;
try {
bufReader = new BufferedReader(new FileReader(componentPath));
String line = bufReader.readLine();
//Looking for the pattern starting with #(any number of #) then any String after that
Pattern r = Pattern.compile("(^[#]*)(.*)");
while (line != null) {
line = line.trim();
if(!("".equals(line)))
{
if(line.matches("^#.*"))
{
Matcher m = r.matcher(line);
if (m.find( ))
{
//System.out.println("Found value: " + m.group(2) );
unlockList.add(m.group(2).trim());
}
}
else
{
listOfLines.add(line);
//empty lines removed
}
line = bufReader.readLine();
}
else
{
line = bufReader.readLine();
}
}
} catch(Exception ex) {
log.info(ex);
} finally {
if (bufReader != null)
bufReader.close();
}
return listOfLines;
}
The BufferedReader should be created in a try-block similar to this:
public static List getlockList(String componentPath) throws IOException
{
List<String> listOfLines = new ArrayList<String>();
try(BufferedReader bufReader = new BufferedReader(new FileReader( componentPath)))
{
// do your magic
}
return listOfLines;
}
The Reader will be closed automatically even if an exception occur. There is also a description of the rule which covers a compliant solution: https://rules.sonarsource.com/java/tag/java8/RSPEC-2093
The whole logic for reading file lines must be surrounded with try catch block. This is because you can get exception like FileNotFoundException and so on. After you read the lines you have to close your buffer reader in final clause because if there is exception thrown then the BufferedReader might not be closed and you will have a memory leak problems.
You can use also try with resources which is new way of handling closable resources like BufferedReader. Then you do not need to call bufReader.close();
Here is oracle documentation with examples:
https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
I'm currently trying to save the output of my code into a text file, when I run it on a different project it generates the output file and stores the output respectively, however when I run the same code in a different project it gives me blank output file and I do not really know what's the matter. I'm confused as to where to put the .close() function and the flush function as well. Thank you in advance!
FileWriter output = new FileWriter("set.txt");
BufferedWriter writer = new BufferedWriter(output);
InputStream fis_n = new FileInputStream("/Users/User/NetBeansProjects/Test/src/test/sample.txt");
InputStreamReader isr_n = new InputStreamReader(fis_n, Charset.forName("UTF-8"));
BufferedReader br_n = new BufferedReader(isr_n);
while ((input = br_n.readLine()) != null) {
String[] s = input.split(":");
if (s[1].equals(text)) {
writer.write(s[0] + "'s result is " + sample_text);
writer.newLine();
break;
}
}
writer.close();
output.close();
This is what the edited code looks like, yet still the output file "set.txt" is empty upon running the program.
FileWriter output = new FileWriter("set.txt");
BufferedWriter writer = new BufferedWriter(output);
InputStream fis_n = new FileInputStream("/Users/User/NetBeansProjects/Test/src/test/sample.txt");
InputStreamReader isr_n = new InputStreamReader(fis_n, Charset.forName("UTF-8"));
BufferedReader br_n = new BufferedReader(isr_n);
try {
while ((input = br_n.readLine()) != null) {
String[] s = input.split(":");
if (s[1].equals(text)) {
writer.write(s[0] + "'s result is " + sample_text);
writer.newLine();
break;
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
writer.close();
fis_n.close();
isr_n.close();
br_n.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// fis_n.close();
//isr_n.close();
//br_n.close();
}
This is what the final code looks like:
public static void dictionary(String sample_text, String text) throws FileNotFoundException, IOException {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(
new FileInputStream("/Users/User/NetBeansProjects/Test/src/test/sample.txt"),
Charset.forName("UTF-8")
));
try {
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream("/Users/User/NetBeansProjects/Test/src/test/set.txt"),
Charset.forName("UTF-8")
));
try {
String input;
while ((input = reader.readLine()) != null) {
String[] s = input.split(":");
if (s[1].equals(text)) {
writer.write(s[0] + "'s result is " + sample_text);
writer.newLine();
break;
}
}
} finally {
writer.close();
}
} finally {
reader.close();
}
} catch (IOException e) {
// Error handling
}
}
This is the main method where the dictionary method is being called.
public static void main(String[] args) throws FileNotFoundException, IOException {
case 2: {
BufferedReader d_br = new BufferedReader(new InputStreamReader(
new FileInputStream("/Users/User/NetBeansProjects/Test/src/test/input_file.txt"),
Charset.forName("UTF-8")
));
try {
String d_line;
while ((d_line = d_br.readLine()) != null) {
String h_input = test(d_line);
dictionary(d_line, h_input);
}
} catch(IOException e){
}finally {
d_br.close();
}
break;
}
}
You should put writer.close() after the while loop, and preferable, into the finally section.
If there is no requirement to store partially-processed files (as in most cases), you may remove flush at all. In the other case, it is better to leave it where it is.
The generic case of resource usage on Java 7+ looks like follows (this syntax is called try-with-resources:
try (
Resource resource1 = // Resource 1 initialization
Resource resource2 = // Resource 2 initialization
...
) {
// Resource utilization
} catch (XXXException e) {
// Something went wrong
}
Resource are freed (closed) automatically by try-with-resources.
If you need to use Java 6 or earlier, the above code could be roughly translated to the following (actually there are some subtle differences, that is not important at this level of details).
try {
Resource1 resource1 = // Resource initialization
try {
Resource2 resource2 = // Resource initialization
try {
// Resource utilization
} finally {
// Free resource2
resource2.close();
}
} finally {
// Free resource1
resource1.close();
}
} catch (XXXException e) {
// Something went wrong
}
Notice, how nested try-finally blocks used for resource management.
In your particular case we need to manage two resources: Reader and Writer, so the code will look as follows:
try (
// Notice, we build BufferedReader for the file in a single expression
BufferedReader reader = new BufferedReader(new InputStreamReader(
new FileInputStream("sample.txt"),
StandardCharsets.UTF_8 // Better replacement for Charset.forName("UTF-8")
));
// Alternative way to do the same
// BufferedReader reader = Files.newBufferedReader(Paths.get("sample.txt"), StandardCharsets.UTF_8);
// Output charset for writer provided explicitly
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream("set.txt"),
StandardCharsets.UTF_8
))
// Alternative way to do the same
// BufferedWriter writer = Files.newBufferedWriter(Paths.get("set.txt"), StandardCharsets.UTF_8)
) {
String input;
while ((input = reader.readLine()) != null) {
String[] s = input.split(":");
if (s[1].equals(text)) {
writer.write(s[0] + "'s result is " + text);
writer.newLine();
break;
}
}
} catch (IOException e) {
// Error handling
}
Or, using pre-Java7 syntax:
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(
new FileInputStream("sample.txt"),
Charset.forName("UTF-8")
));
try {
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream("set.txt"),
Charset.forName("UTF-8")
));
try {
String input;
while ((input = reader.readLine()) != null) {
String[] s = input.split(":");
if (s[1].equals(text)) {
writer.write(s[0] + "'s result is " + text);
writer.newLine();
break;
}
}
} finally {
writer.close();
}
} finally {
reader.close();
}
} catch (IOException e) {
// Error handling
}
First of all, you call the flush method of a writer, whenever you want the current buffer to be written immediately. If you just write a file completely without any intermediate operation on your output, you do not need to call it explicitly, since the close call will do that for you.
Secondly, you only call the close method of the top-level reader or writer, in your case BufferedWriter. The close call is forwarded to the other assigned readers or writers. Multiple consecutive close calls do not have any effect on a previously closed instance, see here.
As a general note to using readers and writers, consider this pattern:
// This writer must be declared before 'try' to
// be visible in the finally block
AnyWriter writer = null;
try {
// Instantiate writer here, because it can already
// throw an IOException
writer = new AnyWriter();
// The the writing in a loop or as you wish
// If you need to write out the buffer in
// between, call flush
} catch (IOException e) {
// Something went wrong while writing
} finally {
try {
if (writer != null)
writer.close();
} catch (IOException e) {
// Exception while trying to close
}
}
The finally block is ALWAYS executed. If you need a more compact syntax and you use at least Java 7, you can have a look at the try-with notation here.
I have tried doing it like this:
import java.io.*;
public class ConvertChar {
public static void main(String args[]) {
Long now = System.nanoTime();
String nomCompletFichier = "C:\\Users\\aahamed\\Desktop\\test\\test.xml";
Convert(nomCompletFichier);
Long inter = System.nanoTime() - now;
System.out.println(inter);
}
public static void Convert(String nomCompletFichier) {
FileWriter writer = null;
BufferedReader reader = null;
try {
File file = new File(nomCompletFichier);
reader = new BufferedReader(new FileReader(file));
String oldtext = "";
while (reader.ready()) {
oldtext += reader.readLine() + "\n";
}
reader.close();
// replace a word in a file
// String newtext = oldtext.replaceAll("drink", "Love");
// To replace a line in a file
String newtext = oldtext.replaceAll("&(?!amp;)", "&");
writer = new FileWriter(file);
writer.write(newtext);
writer.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
However the code above takes more time to execute than creating two different files:
import java.io.*;
public class ConvertChar {
public static void main(String args[]) {
Long now = System.nanoTime();
String nomCompletFichier = "C:\\Users\\aahamed\\Desktop\\test\\test.xml";
Convert(nomCompletFichier);
Long inter = System.nanoTime() - now;
System.out.println(inter);
}
private static void Convert(String nomCompletFichier) {
BufferedReader br = null;
BufferedWriter bw = null;
try {
File file = new File(nomCompletFichier);
File tempFile = File.createTempFile("buffer", ".tmp");
bw = new BufferedWriter(new FileWriter(tempFile, true));
br = new BufferedReader(new FileReader(file));
while (br.ready()) {
bw.write(br.readLine().replaceAll("&(?!amp;)", "&") + "\n");
}
bw.close();
br.close();
file.delete();
tempFile.renameTo(file);
} catch (IOException e) {
// writeLog("Erreur lors de la conversion des caractères : " + e.getMessage(), 0);
} finally {
try {
bw.close();
} catch (Exception ignore) {
}
try {
br.close();
} catch (Exception ignore) {
}
}
}
}
Is there any way to do the 2nd code without creating a temp file and reducing the execution time? I am doing a code optimization.
The main reason why your first program is slow is probably that it's building up the string oldtext incrementally. The problem with that is that each time you add another line to it it may need to make a copy of it. Since each copy takes time roughly proportional to the length of the string being copied, your execution time will scale like the square of the size of your input file.
You can check whether this is your problem by trying with files of different lengths and seeing how the runtime depends on the file size.
If so, one easy way to get around the problem is Java's StringBuilder class which is intended for exactly this task: building up a large string incrementally.
The main culprit in your first example is that you're building oldtext inefficiently using String concatenations, as explained here. This allocates a new string for every concatenation. Java provides you StringBuilder for building strings:
StringBuilder builder = new StringBuilder;
while(reader.ready()){
builder.append(reader.readLine());
builder.append("\n");
}
String oldtext = builder.toString();
You can also do the replacement when you're building your text in StringBuilder. Another problem with your code is that you shouldn't use ready() to check if there is some content left in the file - check the result of readLine(). Finally, closing the stream should be in a finally or try-with-resources block. The result could look like this:
StringBuilder builder = new StringBuilder();
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
String line = reader.readLine();
while (line != null) {
builder.append(line.replaceAll("&(?!amp;)", "&"));
builder.append('\n');
line = reader.readLine();
}
}
String newText = builder.toString();
Writing to a temporary file is a good solution too, though. The amount of I/O, which is the slowest to handle, is the same in both cases - read the full content once, write result once.
I want to extract the first column in a file using the delimiter "," and save it into a new File.
Output generates this exception :
Exception in thread "main" java.lang.NullPointerException
at Extract.main(Extract.java:26)
Here is the code that I used butI am not sure if it is correct or not:
public class Extract {
public Extract(){
}
public static void main(String[] args) {
BufferedReader in = null;
try {
BufferedWriter out = new BufferedWriter(new FileWriter("/home/omar/Téléchargements/nursery.tmp"));
in = new BufferedReader(new FileReader("pima.txt"));
String read = null;
while ((read = in.readLine()) != null) {
read = in.readLine();
String[] splited = read.split(",");
if (splited.length > 0)
{
out.append(splited[0].toString());
out.newLine();
}
}
} catch (IOException e) {
System.out.println("There was a problem: " + e);
e.printStackTrace();
} finally {
try {
in.close();
} catch (Exception e) {
}
}
File f = new File("prima.txt");
f.delete();
File f2 = new File("pima.tmp");
f2.renameTo(new File("pima.txt"));
}
}
Remove the first line, ie read = in.readLine();, from inside your while() loop.
The problem is that you are reading the line when you are checking the while condition and inside while loop you are reading a line again (but this time a new line, because readLine not only reads a line but also moves the reading pointer to next line) so you are getting the next line.
Once you are past the end of the file you get null instead of a line, that is why you are getting Exception.
I have the following code which prints the output of the DataIntegrationV8.jar to the JTextArea. Is it possible to print an exception thrown by that program in the same JTextArea?
protected Integer doInBackground() throws Exception {
Process process;
InputStream iStream;
try {
//run the DataIntegration.jar
process = Runtime.getRuntime().exec("java -jar DataIntegrationV8.jar sample.xml");
istream = process.getInputStream();
} catch (IOException e) {
throw new IOException("Error executing DataIntegrationV8.jar");
}
//get the output of the DataIntegration.jar and put it to the
//DataIntegrationStarter.jar form
InputStreamReader isReader = new InputStreamReader(iStream);
BufferedReader bReader = new BufferedReader(isReader);
String line;
while ((line = bReader.readLine()) != null) {
jtaAbout.append(line + "\n");
}
Thread.sleep(1);
return 42;
}
By default exception stacktraces are displayed to System.err. You could include the output from the ErrorStream to the JTextArea.
BufferedReader error = new BufferedReader(new InputStreamReader(process.getErrorStream()));
String errorLine = null;
while ((errorLine = error.readLine()) != null) {
jtaAbout.append(errorLine + "\n");
}
You could check the error code returned by the program and it it is not zero, you know the output is a java stacktrace as the program terminated ...... poorly.