BufferedReader reads a value which is somehow null - java

Ok, so I was doing a program which has a config file handler, and what it does is that it reads in the lines from a text file, which looks something like this:
ImagePath=SomePath
The method reads line by line matching the key with the corresponding line, and after that it then searches for the '=' character position in the String, and then substrings it such that the value SomePath is obtained. However, there is an issue.
Basically, the issue I am facing is that the reader is able to read the file, as I put a statement to print out the lines variable and it does print out the line read. However, the issue is that this lines variable would then be manipulated, but an NullPointerException error would occur around there (the lines.substring(0,key.length()-1) part), suggesting that the lines variable suddenly became null even though it is shown that something was read into the variable. Thing is, what happens to this variable in between the print statement and the string manipulation? I am unable to fix this issue. Pardon my code which might look messy or whatnot. I was trying multiple variations of my code to try to mitigate the issue, but it seems to not work. What is shown below is my latest variation of the code.
public static String readConfig(String key) throws IOException
{
BufferedReader reader=null;
try
{
reader=new BufferedReader(new FileReader(config));
}
catch(FileNotFoundException e)
{
System.out.println("Failed to read file. Code: 3");
System.exit(0);
}
String lines=reader.readLine();
System.out.println(lines);
String returnValue=null;
while(true)
{
if(key.equals(lines.substring(0,key.length()-1)))
{
int plusPos=0;
for(int i=0;i<lines.length();i++)
{
if(lines.charAt(i)=='=')
{
plusPos=i;
}
}
if(plusPos==0)
{
reader.close();
return null;
}
returnValue=lines.substring(plusPos,lines.length()-1);
reader.close();
return returnValue;
}
lines=reader.readLine();
}
}
Edit 1: Ok, I see that Sbodd suggested that my code is kinda flawed, but well, the above snippet is just an instance to debug and test exactly which part of the loop does the line variable suddenly read null. Here is my original code snippet:
public static String readConfig(String key) throws IOException
{
BufferedReader reader=null;
try
{
reader=new BufferedReader(new FileReader(config));
}
catch(FileNotFoundException e)
{
System.out.println("Failed to read file. Code: 3");
System.exit(0);
}
String line;
String returnValue;
while((line=reader.readLine())!=null)
{
line=line.trim();
if(key.equals(line.substring(0,key.length()-1)))
{
int plusPos=0;
for(int i=0;i<line.length();i++)
{
if(line.charAt(i)=='=')
{
plusPos=i;
}
}
if(plusPos==0)
{
return null;
}
returnValue=line.substring(plusPos,line.length()-1);
return returnValue;
}
}
return null;
}

Your code will always throw a NPE when it reaches the end of the file.
From the documentation for BufferedReader:
[readLine returns] A String containing the contents of the line, not including any line-termination characters, or null if the end of the stream has been reached.
Since your code is:
lines = reader.readLine();
while (true) {
//do stuff with lines
lines=reader.readLine();
}
when you reach end-of-file, reader.readLine will return null, you'll still pass your while check (since "true" is always true), and then you'll try and use that null pointer.
You could just replace while(true) with while (lines != null).
A typical pattern to do this instead would be
while ((lines = reader.readLine()) != null) {
//do stuff with lines
}
(Note that here, you don't make the first call to readLine outside the while loop, since your condition will be tested before the first execution of the loop.)

Your string comparison will always fail.
if(key.equals(lines.substring(0,key.length()-1)))
Will attempt to match "ImagePat" and "ImagePath", which will fail. This will then cause a second iteration of the loop, with lines now equal to null.
Your comparison should be:
if (key.equals(lines.substring(0, key.length())))
Also, your return value should be
returnValue = lines.substring(plusPos + 1, lines.length());
to properly return the value.
You should also look at the Properties class, it will make things a lot easier.

Related

BufferedReader does not read all the lines in text file

I have a function.
public ArrayList<String> readRules(String src) {
try (BufferedReader br = new BufferedReader(new FileReader(src))) {
String sCurrentLine;
while ((sCurrentLine = br.readLine()) != null) {
System.out.println(sCurrentLine);
lines.add(sCurrentLine);
}
} catch (IOException e) {
e.printStackTrace();
}
return lines;
}
My file have 26.400 lines but this function just read 3400 lines at end of file.
How do I read all lines in file.
Thanks!
Why don't you use the utility method Files.readAllLines() (available since Java 7)?
This method ensures that the file is closed when all bytes have been read or an IOException (or another runtime exception) is thrown.
Bytes from the file are decoded into characters using the specified charset.
public ArrayList<String> readRules(String src) {
return Files.readAllLines(src, Charset.defaultCharset());
}
while ((sCurrentLine = br.readLine()) != null)
It is likely that you have an empty line or a line that is treated as null.
Try
while(br.hasNextLine())
{
String current = br.nextLine();
}
Edit: Or, in your text file, when a line is too long, the editor automatically wraps a single line into many lines. When you don't use return key, it is treated as a single line by BufferedReader.
Notepad++ is a good tool to prevent confusing a single line with multiple lines. It numbers the lines with respect to usage of return key. Maybe you could copy/paste your input file to Notepad++ and check if the line numbers match.
You can also cast into a List of strings using readAllLines() and then loop through it.
List<String> myfilevar = Files.readAllLines(Paths.get("/PATH/TO/MY/FILE.TXT"));
for(String x : myfilevar)
{
System.out.println(x);
}

nullpointer exception at a search method in Java

So I tracked down the bugger, but I am no closer to understanding what is wrong. Here is what the compiler says:
Exception in thread "main" java.lang.NullPointerException at
BasicFile.Search(BasicFile.java:215) at
TestFile.main(TestFile.java:42)
Line 215 is the one that starts with while, first one.
String Search(String key) throws IOException {
int lines = 0;
String line = "";
String foundAt = "";
BufferedReader BF = new BufferedReader(new FileReader(f));
try {
while ((line = BF.readLine().toLowerCase()) != null) {
lines++;
//create tokenizer words with what is in line
StringTokenizer words = new StringTokenizer(line);
while(words.hasMoreTokens()) { //while words has tokens left
//go to next token and compare to key
if (words.nextToken().equals(key.toLowerCase()))
foundAt = foundAt + "\n" + lines + ":" + line;
//do nothing continue loop
}
}
BF.close();
} catch(FileNotFoundException e) {
}
return foundAt;
}
When your buffer reader runs out of lines it returns null. You are trying to call toLowerCase method on null which ends up throwing the null pointer exception.
Refactor your code in a way that it doesn't require you to execute toLowerCase before ensuring the line is non-null.
For example:
String next;
while ((next = BF.readLine()) != null) {
String line = next.toLowerCase();
// ...
}
while ((line = BF.readLine().toLowerCase()) != null)
What happens if BF.readline() returns null?
remove .toLowerCase() from the test
Please, stop it, your code is giving me cancer! There are a number of stylistic errors in the code that you need to fix.
First off in java, method names always begin with a lowercase letter. You are programming in Java, not C#, so you need to use the Java naming conventions. That means your method should be called search, not Search.
The same goes for variable names. What is BF supposed to mean, anyway? Replace it with in, please.
Next up, unless this method is in an object that itself represents that particular file, the global variable f should be passed as a parameter instead.
BufferedReader is AutoCloseable, so you should use a try-with-resources to deal with closing it.
You need to add a javadoc comment to it, documenting its parameters with #param, its return with #return, and exactly why it might need to throw an IOException with #exception.
Here is a mostly-fixed version of your code:
/**
* Needs Javadoc
*/
String search(String key, File f) throws IOException {
int lines = 0
String line = "";
String foundAt = "";
try(BufferedReader in = new BufferedReader(new FileReader(f)) {
while ((line = in.readLine().toLowerCase()) != null) { //the line in question
lines++;
StringTokenizer words = new StringTokenizer(line);
while(words.hasMoreTokens())
if (words.nextToken().equals(key.toLowerCase()))
foundAt = foundAt + "\n" + lines + ":" + line;
}
} catch(FileNotFoundException e){}
return foundAt;
}
Now, the problem here is that in.readline() returns a null sometimes. Calling a method on a null is always a NullPointerException. Therefore you get a NullPointerException when you attempt to call that null's missing toLowerCase() method.
You need to convert it toLowerCase after you ensure it is non-null.

How to skip certain line from Text file in java?

I am currently learning Java and I have faced this problem where I want to load a file that consists a huge number of lines (I am reading the file line by line ) and the thing I want to do is skip certain lines (pseudo-code).
the line thats starts with (specific word such as "ABC")
I have tried to use
if(line.startwith("abc"))
But that didn't work. I am not sure if I am doing it wrong, that's why I am here asking for a help, below part of the load function:
public String loadfile(.........){
//here goes the variables
try {
File data= new File(dataFile);
if (data.exists()) {
br = new BufferedReader(new FileReader(dataFile));
while ((thisLine = br.readLine()) != null) {
if (thisLine.length() > 0) {
tmpLine = thisLine.toString();
tmpLine2 = tmpLine.split(......);
[...]
Try
if (line.toUpperCase().startsWith(­"ABC")){
//skip line
} else {
//do something
}
This will converts the line to all the Upper Characters by using function toUpperCase() and will check whether the string starts with ABC .
And if it is true then it will do nothing(skip the line) and go into the else part.
You can also use startsWithIgnoreCase which is a function provided by the Apache Commons . It takes the two string arguments.
public static boolean startsWithIgnoreCase(String str,
String prefix)
This function return boolean.
And checks whether a String starts with a specified prefix.
It return true if the String starts with the prefix , case insensitive.
If the case isn't important try using the StringUtils.startsWithIgnoreCase(String str,
String prefix) of Apache Commons
This function return boolean.
See javadoc here
Usage:
if (StringUtils.startsWithIgnoreCase(­line, "abc")){
//skip line
} else {
//do something
}
If you have large a input File, you code will create a OutOfMemoryError. there is nothing you can do against it without editing te code (adding more memory will fail, if the file gets bigger).
I beleave you store the selected lines in memory. If the file gets lager (2GB or so) you'll have 4GB in memory. (The old Value of the String and the new one).
You have to work with streams to solve this.
Create a FileOutpuStream, and write the selcted line into that Stream.
Your method must be changed. For a large input yo cannot return a String:
public String loadfile(...){
You can return a Stream or a file.
public MyDeletingLineBufferedReader loadFile(...)
you can use:
BufferedReader br = new BufferedReader(new FileReader("file.txt"));
String lineString;
try{
while((lineString = br.readLine()) != null) {
if (lineString.toUpperCase().startsWith(­"abc")){
//skip
} else {
//do something
}
}
}
or
static boolean startsWithIgnoreCase(String str, String prefix) method in org.apache.commons.lang.StringUtils like below.
BufferedReader br = new BufferedReader(new FileReader("file.txt"));
String lineString;
try{
while((lineString = br.readLine()) != null) {
if (StringUtils.startsWithIgnoreCase(­lineString, "abc")){
//skip
} else {
//do something
}
}
}

while EOF in JAVA?

Following to some forums answers I'm using this:
while (fileReader.nextLine() != null) {
String line = fileReader.nextLine();
System.out.println(line);
}
... but it throws exception at the end anyway
(Exception in thread "main" java.util.NoSuchElementException: No line found)
Each call to nextLine() moves onto the next line, so when you are actually at the last readable line and the while check passes inspection, the next call to nextLine() will return EOF.
Perhaps you could do one of the following instead:
If fileReader is of type Scanner:
while ((line = fileReader.hasNextLine()) != null) {
String line = fileReader.nextLine();
System.out.println(line);
}
If fileReader is of type BufferedReader:
String line;
while ((line = fileReader.readLine()) != null) {
System.out.println(line);
}
So you're reading the current line in the while condition and saving the line in a string for later use.
you should use while (fileReader.hasNextLine())
To read a file Scanner class is recommended.
Scanner scanner = new Scanner(new FileInputStream(fFileName), fEncoding);
try {
while (scanner.hasNextLine()){
System.out.println(scanner.nextLine());
}
}
finally{
scanner.close();
}
The others told you enough about your issue with multiple calls of readLine().
I just wanted to leave sth about code style:
While you see this line = assignement and != null check together in one while condition in most examples (like #gotomanners example here) I prefer using a for for it.
It is much more readable in my opinion ...
for (String line = in.readLine(); line != null; line = in.readLine()) {
...
}
Another nice way to write it you see in #TheCapn's example. But when you write it that way you easily see that's what a for-loop is made for.
I do not like assignments scrambled with conditions in one line. It is bad style in my opinion. But because it is so MUCH popular for that special case here to do it that way I would not consider it really bad style. (But cannot understand who established this bad style to become that popular.)
The problem is that you're reading nextLine() on the while loop and THEN reading it to a variable. Not only are you getting every 2nd line printed out you're opening yourself to the exception being thrown. An example:
File:
Hello,
Blah blah blah,
Sincerely,
CapnStank
PS. Something something
On first iteration through the loop. The check on while will consume the "Hello," as not equal to null. Inside the loop body you'll see Blah blah blah, printed to the System.
The process will repeat with Sincerely, being consumed and Capnstank printing out.
Finally the while will consume the "PS" line while the String line = fileReader.nextLine() retreives an exception from the file because there's nothing further to read.
To resolve the issue:
String line = fileReader.nextLine();
while (line != null) {
System.out.println(line);
line = fileReader.nextLine();
}
nextLine() will throw an exception when there's no line and it will never return null,you can try the Scanner Class instead : http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Scanner.html
while(inFile.hasNext())
This is correct in java programming language
//By: Ishraga Mustafa Awad Allam
import java.io.*;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class B_C_Data {
public static void main(String[] args) {
try {
// Create a file reader
FileInputStream fr = new FileInputStream(args[0]);
// Create a file output stream
DataInputStream dr = new DataInputStream(fr);
// Read and display data
while (dr.available() > 0) {
System.out.println(dr.readDouble());
}
// Close file input stream
dr.close();
}
catch(Exception e) {
System.out.println("Exception: " + e);
}
}
}

Read a single file with multiple BufferedReaders

I'm working on a program that needs to update a line that depends its value on the result of a line that goes read after. I thought that I could use two BufferedReaders in Java to position the reader on the line to update while the other one goes for the line that fixes the value (it can be an unknown number of lines ahead). The problem here is that I'm using two BufferedReaders on the same file and even if I think I'm doing right with the indexes the result in debug doesn't seem to be reliable.
Here's the code:
String outFinal
FileName=fileOut;
File fileDest=new File(outFinalFileName);
try {
fout = new BufferedWriter(
new OutputStreamWriter(
new FileOutputStream(fileDest)));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
FileReader inputFile=null;
try {
inputFile = new FileReader(inFileName);
} catch (FileNotFoundException e2) {
e2.printStackTrace();
}
BufferedReader fin = new BufferedReader(inputFile);
BufferedReader finChecker = new BufferedReader(inputFile); //Checks the file and matches record to change
String line="";
String lineC="";
int lineNumber=0;
String recordType="";
String statusCode="";
try {
while ((lineC = finChecker.readLine()) != null) {
lineNumber++;
if (lineNumber==1)
line=fin.readLine();
recordType=lineC.substring(0,3);//Gets current Record Type
if (recordType.equals("35")){
while(!line.equals(lineC)){
line=fin.readLine();
if (line==null)
break;
fout.write(line);
}
}else if (recordType.equals("32")){
statusCode=lineC.substring(4,7);
if(statusCode.equals("XX")){
updateRecordLine(line,fout);
}
}
}
returnVal=true;
} catch (IOException e) {
e.printStackTrace();
}
Thanks in advance.
Well, the BufferedReader only reads stuff, it doesn't have the ability to write data back out. So, what you would need is a BufferedReader to get stuff in, and a BufferedWriter that takes all the input from the BufferedReader, and outputs it to a temp file, with the corrected/appended data.
Then, when you're done (i.e. both BufferedReader and BufferedWriter streams are closed), you need to either discard the original file, or rename the temp file to the name of the original file.
You are basically copying the original file to a temp file, modifying the line in question in the temp file's output, and then copying/renaming the temp file over the original.
ok, i see some problem in your code exactly on these lines-->
recordType=lineC.substring(0,3);//Gets current Record Type
if (recordType.equals("35")){
if you see on the first line, you are getting the substring of recordType into recordType. Now recordType length is 3. If at all the recordType has only 2 characters, then substring throws arrayIndexOutOfBoundsException. So when no runtime exceptions, its length is 3 and on the next line you are calling the equals method that has a string with 2 characters.
Will this if block ever run ?

Categories