so Im trying to write this class which is going to parse a file and read commands from it.
I want the ctor to just open the stream and do nothing else.
while I parse the file in other class methods.
But I'm getting a nullpointerexception when I try to read the file in the methods I made.
help will be apprecated :D
public class Parser {
private BufferedReader _input;
private String _command;
public Parser(String filename) throws FileNotFoundException {
FileInputStream fstream = new FileInputStream(filename);
BufferedReader _input = new BufferedReader(new InputStreamReader(fstream));
}
public boolean hasMoreCommands() throws IOException {
String line;
if ( (line = _input.readLine()) != null) {
return true;
} else {
_input.close();
return false;
}
}
public void advance() throws IOException {
String line;
do {
line = _input.readLine().trim();
} while (line.equals("") || line.substring(0,2).equals(COMMENT_SIGN));
String[] splittedLine = line.split(COMMENT_SIGN);
_command = splittedLine[0];
_command = _command.replace(" ", "");
}
my main for testing it + the exception trace
public static void main(String[] args) throws IOException {
Parser input = null;
input = new Parser("D:\\test.asm");
System.out.println( input.hasMoreCommands());
}
Exception in thread "main" java.lang.NullPointerException
at nand6.Parser.hasMoreCommands(Parser.java:40)
at nand6.Parser.main(Parser.java:116)
Have a look at this snippet of code
public Parser(String filename) throws FileNotFoundException {
FileInputStream fstream = new FileInputStream(_filename);
BufferedReader _input = new BufferedReader(new InputStreamReader(fstream));
}
Change
BufferedReader _input = new BufferedReader(new InputStreamReader(fstream));
to
_input = new BufferedReader(new InputStreamReader(fstream));
Your mistake : You are creating another local variable of type *BufferedReader _input* hence your class level variable is still null resulting in a NullPointerException
You are basically defining a new BufferedReader object called "_input" inside your constructor. You think that after calling the constructor you instantiate "_input" outside the constructor. But you are not, it refers to null. That's why you are getting NullPointerException. Just remove "BufferedReader" in front of "_input" inside your constructor, in order to refer to correct object.
Related
I have 5 input files in a folder, for each input file (1.in for example), I process it and produce a new output file (1.out) printing a integer in it.
How do I do this?
Right now this is what I have, I want to run different files like a2.in and print output in new file like a2.out (name them based on the input file names).
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("a1.in"));
PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter("a1.out")));
public int compareTo(Event a) {
return ans;
}
That depends on unit test and assertion library you are using, below is example for junit-jupiter akin junit5 and assertJ:
#ParameterizedTest
#CsvSource(delimiterString = ";", value = {"a1.in;a1.out", "a2.in;a2.out""})
void test(String input, String output) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (InputStream in = getStream(input); InputStream expected = getStream(output)) {
// test body reading from in and writing to baos
assertThat(new ByteArrayInputStream(baos.toByteArray()))
.hasSameContentAs(expected);
}
}
InputStream getStream(String resource) {
return getClass().getResourceAsStream("/" + resource);
}
UPD (Thanks Reinier for comments).
If your goal is to test #main method (i.e. you are writing CLI application, which reads and writes some files) and your #main method looks like:
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(args[0]));
PrintWriter pw = new PrintWriter(new BufferedWriter(new FileWriter(args[2])));
// do something with br and pw
}
consider redesigning it to something like:
public static void main(String[] args) throws IOException {
main(Files.newInputStream(Paths.get(args[0])), Files.newOutputStream(Paths.get(args[1])));
}
public static void main(InputStream in, OutputStream out) throws IOException {
try (
BufferedReader br = new BufferedReader(new InputStreamReader(in));
PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(out);
) {
// do something with br and pw
pw.flush();
}
}
in that case the testability of #main method gets improved.
In the below code I have used BufferedReader and InputStreamReader inside the try and but veracode complains the security as Improper Resource Shutdown or Release (CWE ID 404)
try (final BufferedReader bsr = new BufferedReader(new InputStreamReader(Myutils.class.getClassLoader()
.getResourceAsStream("fileName.txt")))) {
String currentLine;
while ((currentLine = bsr.readLine()) != null) {
// doing some operations
}
} catch (final Exception e) {
throw new IllegalStateException("exception occurres");
}
}
Also in another class I am extending HttpServletRequestWrapper
public class MyHttpServletRequestWrapper extends HttpServletRequestWrapper {
private BufferedReader reader;
#Override
public BufferedReader getReader() throws IOException {
if (null == this.reader) {
this.reader = new BufferedReader(new InputStreamReader(getInputStream(), getCharacterEncoding()));
}
return this.reader;
}
}
here in this.reader line veracode giving the Improper Resource Shutdown or Release (CWE ID 404). I think the framework (tomcat/spring) is handling this. But not sure why veracode saying this.
InputStream will be left open if an exception is thrown after opening the InputStream but before assigning the BufferedReader. In the example you've provided this can only happen if the InputStreamReader constructor throws an exception. To avoid this you can use the following code:
try (final InputStream is = Example.class.getClassLoader().getResourceAsStream("filename.txt");
final InputStreamReader inputStreamReader = new InputStreamReader(is);
final BufferedReader bsr = new BufferedReader(inputStreamReader);) {
I want to make a little script in JAVA to receive a file name in the linux terminal and read that file.
This is what i'm trying:
import java.util.Scanner;
import java.io.*;
class ItauScript {
public static void main(String[] args) {
Scanner reader = new Scanner(System.in);
System.out.println("Filename: ");
String fileName = reader.next();
FileReader fileReader = new FileReader(fileName);
BufferedReader bufferedReader = new BufferedReader(fileReader);
System.out.println(bufferedReader.readLine());
}
}
But the code doesn't compile. I get this error message:
hello.java:10: error: unreported exception FileNotFoundException; must
be caught or declared to be thrown
FileReader fileReader = new FileReader(fileName);
^ hello.java:13: error: unreported exception IOException; must be caught or declared to be thrown
System.out.println(bufferedReader.readLine());
I can open the file if i put it on hardcode on a string.
But i need to receive it as an input from the terminal.
What am i missing?
Try:
import java.util.Scanner;
import java.io.*;
class ItauScript {
public static void main(String[] args) {
Scanner reader = new Scanner(System.in);
System.out.println("Filename: ");
String fileName = reader.next();
try {
FileReader fileReader = new FileReader(fileName);
BufferedReader bufferedReader = new BufferedReader(fileReader);
System.out.println(bufferedReader.readLine());
} catch (IOException e) {
// handle exception (if any) here
}
}
}
And as others suggested, it's very helpful to read what the IDE/Compiler tells you in case of errors ...
Hope that helps
FileNotFoundException is a checked Exception (as is the parent class IOException thrown by readLine), modify main to re-throw1 it like
public static void main(String[] args) throws IOException {
or surround it with a try-catch (with resources) like
try (FileReader fileReader = new FileReader(fileName);
BufferedReader bufferedReader = new BufferedReader(fileReader)) {
System.out.println(bufferedReader.readLine());
} catch (IOException e) {
e.printStackTrace();
}
1But you should still close the bufferedReader in a finally.
You need to handle the possible exception. You can specify that the enclosing method main throws the exception, but it would be better to handle it yourself.
import java.util.Scanner;
import java.io.*;
class ItauScript {
public static void main(String[] args) {
Scanner reader = new Scanner(System.in);
try
{
System.out.println("Filename: ");
String fileName = reader.next();
FileReader fileReader = new FileReader(fileName);
BufferedReader bufferedReader = new BufferedReader(fileReader);
System.out.println(bufferedReader.readLine());
}
catch(IOException e)
{
e.printStackTrace();
//TODO handle error
return;
}
}
}
I have following test program to read a file from HDFS.
public class FileReader {
public static final String NAMENODE_IP = "172.32.17.209";
public static final String FILE_PATH = "/notice.html";
public static void main(String[] args) throws MalformedURLException,
IOException {
String url = "hdfs://" + NAMENODE_IP + FILE_PATH;
InputStream is = new URL(url).openStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line = br.readLine();
while(line != null) {
System.out.println(line);
line = br.readLine();
}
}
}
It is giving java.net.MalformedURLException
Exception in thread "main" java.net.MalformedURLException: unknown protocol: hdfs
at java.net.URL.<init>(URL.java:592)
at java.net.URL.<init>(URL.java:482)
at java.net.URL.<init>(URL.java:431)
at in.ksharma.hdfs.FileReader.main(FileReader.java:29)
Register Hadoop's Url handler. Standard Url handler won't know how to handle hdfs:// scheme.
Try this:
public static void main(String[] args) throws MalformedURLException,
IOException {
URL.setURLStreamHandlerFactory(new FsUrlStreamHandlerFactory());
String url = "hdfs://" + NAMENODE_IP + FILE_PATH;
InputStream is = new URL(url).openStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line = br.readLine();
while(line != null) {
System.out.println(line);
line = br.readLine();
}
}
I get the same issue while writing a Java application for reading from hdfs on hadoop 2.6.
My solution is : Add
hadoop-2.X/share/hadoop/hdfs/hadoop-hdfs-2.X.jar to your classpath.
In our case we had to combine it with other answer:
https://stackoverflow.com/a/21118824/1549135
So firstly in our HDFS setup class (Scala code):
val hadoopConfig: Configuration = new Configuration()
hadoopConfig.set("fs.hdfs.impl", classOf[DistributedFileSystem].getName)
hadoopConfig.set("fs.file.impl", classOf[LocalFileSystem].getName)
And later, like in accepted answer:
https://stackoverflow.com/a/25971334/1549135
URL.setURLStreamHandlerFactory(new FsUrlStreamHandlerFactory)
Try(new URL(path))
Side note:
We already had:
"org.apache.hadoop" % "hadoop-hdfs" % "2.8.0" in our dependencies and it did not help.
So Im trying to get a basic reader going so that I can work with files for an authentication process later.
The problem I am having is that I get an error on my BufferedReader line that causes my try function to throw an illegal start exception and it wont run. Eclipse is showing me an error on the semicolon at the end of the br declaration and says I should be putting a { but I can't see why that would be neccessary.
BufferedReader br = new BufferedReader(new FileReader("Assign4.txt"));
I have tried to put that there but it breaks the entire try section.
package main;
import java.io.*;
public class file_interface
{
BufferedWriter wr = new BufferedWriter(new FileWriter("target.txt"));
BufferedReader br = new BufferedReader(new FileReader("Assign4.txt"));
try
{
int count = 1;
StringBuilder sb = new StringBuilder();
String line = br.readLine();
while (line != null)
{
sb.append(count++);
sb.append(line);
sb.append("\n");
wr.write(line);
line = br.readLine();
}
}
catch (IOException e)
{
System.err.println("Error: " + e);
}
finally
{
br.close();
wr.close();
}
}
}
Any Java sentence must be inside a method. This code is not.
The fact that BufferedWriter wr = new BufferedWriter(new FileWriter("target.txt")); works is because is declared as a default field (no scope mark was given) in your file_interface class and is being initialized. It is similar to do:
public class file_interface {
BufferedWriter wr;
public file_interface() {
wr = new BufferedWriter(new FileWriter("target.txt"));
}
}
Just create a method to hold your logic:
public class file_interface {
public void foo() {
//your code goes here...
//now this is not a field but a variable in the method
BufferedWriter wr = new BufferedWriter(new FileWriter("target.txt"));
BufferedReader br = new BufferedReader(new FileReader("Assign4.txt"));
//rest of your code...
try {
//...
} catch (...) {
//...
}
//...
}
}
Then just call your method in your client class. For example, a class with the main method:
public class AMainClass {
public static void main(String[] args) {
file_interface fi = new file_interface();
fi.foo();
}
}
Another example, a class with another method:
public class SomeClientClass {
public void bar() {
file_interface fi = new file_interface();
fi.foo();
}
}
Note: You should also follow the Java Naming Conventions, so you should rename file_interface by FileInterface or even MyFileUtil since interface word sounds more to declare an, uhm, interface.