This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 7 years ago.
My code is supposed to read a file line by line, to put each one in a string array named: tuples, (tuples=ligne.split(" "); ) and then add this tuples to an arraylist, one line read = one element of the arraylist.
Unfortunately, my code doesn't work! My buffered reader throws a NullPointerException in my loop!
Error returned in the ExtractFile() method, line 120: tuples= ligne.split(" ");
File file = new File("Department.txt");
BufferedReader in;
PrintWriter out;
String ligne;
int nbCols; //number of metadatas in my file.txt
String metadata[] = new String[nbCols];
String[] tuples = new String[nbCols];//1ere case indique num ligne
ArrayList<String[]> itemset = new ArrayList<String[]>();
public ArrayList ExtractionFile () {
try {
int i = 1;
in = new BufferedReader(new FileReader(file));
while ((ligne = in.readLine()) != null) {
while (ligne.charAt(0) != '1') {
ligne = in.readLine();//browse until line 1 is found
}
tuples = ligne.split(" ");
itemset.add(tuples);
System.out.println(Arrays.toString(itemset.get(0)));
for (i = 2; i < TuplesCount(); i++) {
ligne = in.readLine();
tuples = ligne.split(" ");// THIS LINE THROWS THE EXCEPTION
itemset.add(tuples);
System.out.println(Arrays.toString(itemset.get(i)));
}
}
} catch (IOException es) {
es.printStackTrace();
} catch (ArrayIndexOutOfBoundsException exepti) {
exepti.printStackTrace();
}
return itemset;
}
A NullpointerException tells you that your code
attempts to use null in a case where an object is required. These include:
Calling the instance method of a null object.
...
In your case, you've told us that the error occurs on
tuples = ligne.split(" ");
You're trying to call split on ligne and - given the documentation quote above - that implies that ligne is null at that point.
It's worth noting that it is the second occurence of that line that throws the Exception, so it is not as simple as the file not having a line that starts with 1
Why?
You need to use a debugger or use lots of System.out.println to convince yourself how the value of ligne changes as your code executes and, crucially, where it becomes null.
In your case - we don't know what TuplesCount() returns, but the likelihood is that you keep iterating in that loop beyond the end of the file, so the line immediately before the one that fails
ligne = in.readline();
can return null and you never check for that at that point. Note that conditions for the loops are only checked after each iteration of the loop - so , except for the one right at the top in the condition of the while loop, all the calls to ligne = in.readline(); could return null and are never checked.
The code you provide us is really unreadable and should be formatted to easy debug it. Instead, you can try this simple code that i have tested on my IDE
package example;
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.ArrayList;
public class FileSplit {
public static void main(String[] args) {
ArrayList<String[]> phrases = new ArrayList<String[]>();
try{
BufferedReader in = new BufferedReader(new FileReader("Department.txt"));
String s;
while((s = in.readLine()) != null){
String[] words = s.split(" ");
phrases.add(words);
}
}catch(Exception e){
e.printStackTrace();
}
for(int i=0;i<phrases.size();i++){
for(int j=0;j<phrases.get(i).length;j++)
System.out.println(phrases.get(i)[j]);
}
}
}
Are you testing this with a file which doesn't contain a line 1? If so, you run this it will keep executing the inner loop despite the fact that the value is null, resulting in an exception the time after the last line has been read. To fix this change the inner loop to be an if.
Like so:
public ArrayList ExtractionFile() {
try {
int i = 1;
in = new BufferedReader(new FileReader(file));
ligne = in.readLine(); //It can be more readable to seperate the assignment and the condtion
while (ligne != null) {
if (ligne.charAt(0) != '1') {
ligne = in.readLine();//browse until line 1 is found
} else {
tuples = ligne.split(" ");
itemset.add(tuples);
System.out.println(Arrays.toString(itemset.get(0)));
for (i = 2; i < TuplesCount(); i++) {
ligne = in.readLine();
tuples = ligne.split(" ");// CETTE LIGNE SOULEVE L EXCEPTION
itemset.add(tuples);
System.out.println(Arrays.toString(itemset.get(i)));
}
}
}
} catch (IOException es) {
es.printStackTrace();
} catch (ArrayIndexOutOfBoundsException exepti) {
exepti.printStackTrace();
}
return itemset;
}
private int TuplesCount() {
return Arrays.asList(tuples).size();
}
public static void main(String[] args){
Main main = new Main();
main.ExtractionFile();
}
}
As per some of the points above, please do format your code - it makes it easier to get help! Also, read up on breakpoints!
Related
This question already has answers here:
Scanner is skipping nextLine() after using next() or nextFoo()?
(24 answers)
Closed 1 year ago.
I'm trying to read in a text file which looks similar to this:
0000000000
0000100000
0001001000
0000100000
0000000000
Here is my code:
public static int[][] readBoard(String fileName) throws FileNotFoundException {
File life = new File(fileName);
Scanner s = new Scanner(life);
int row = s.nextInt();
int columns = s.nextInt();
int [][] size = new int [row][columns];
for (int i=0; i <= row; i++) {
String [] state = new String [columns];
String line = s.nextLine();
state = line.split("");
for (int j=0; i <= columns; i++) {
size[i][j] = Integer.parseInt(state[j]);
}
}
return size;
}
It keeps giving me this error. I think it's the Integer.parseInt(state[j]) that is giving me trouble, but I don't know why.
Exception in thread "main" java.lang.NumberFormatException: For input string: ""
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:68)
at java.base/java.lang.Integer.parseInt(Integer.java:662)
at java.base/java.lang.Integer.parseInt(Integer.java:770)
at Project5.readBoard(Project5.java:33)
at Project5.main(Project5.java:9)
I've executed your code with the example input, and you have logical issues in the code. With the exmaple input the code doesn't even reach the parseInt() line where the asked NumberFormatException could be thwrown. I assume you have tried your code in a different input. The Exception message is staithforward, you tried to parse an empty string to number. It's a typical NumberFormatException. The parseInt() function can throw Exception, so your code must be prepared for it.
The other problem is a basic logical issue in your algorithm. Your row and column variables will be populated with the first to integer token from the text. Based on the exampe input the first integer token will be the first row 0000000000 which integer value is 0, and the second token is 0000100000 which will parsed as 100000. So you are trying to initialize an array with these dimensions which is imposible.
To calculate the row count, you have to read the file line by line. And to get the column counts you have the check the length of the lines. (It can open a new question, how do you want to handle the not properly formatted input file, because in the file the line length can be various.)
That means you can only be sure with the dimensions of the board if you have already iterated though the file content. To prevent the multiple iteration you should use dinamic collection instead of a standard array, like ArrayList.
That means while you are read the file line by line, you can process the the characters one after another in a line. In this step you should be concidered about the invalid characters and the potential empty characters in the end of the file. And during this iteration the final collection can be built.
This example shows a potention solution:
private static int processCharacter(char c) {
try {
return Integer.parseInt((Character.toString(c)));
} catch (NumberFormatException e) {
return 0;
}
}
public static List<List<Integer>> readBoard(String fileName) throws FileNotFoundException {
List<List<Integer>> board = new ArrayList<>();
File file = new File(fileName);
FileReader fr = new FileReader(file);
try (BufferedReader br = new BufferedReader(fr)) {
String line;
while ((line = br.readLine()) != null) {
line = line.trim(); // removes empty character from the line
List<Integer> lineList = new ArrayList<>();
if(line.length() > 0) {
for (int i = 0; i < line.length(); i++) {
lineList.add(Main.processCharacter(line.charAt(i)));
}
board.add(lineList);
}
}
} catch (IOException e) {
e.printStackTrace();
}
return board;
}
I am working on a game, and I want to use this text file of mythological names to procedurally generate galaxy solar-system names.
When I read the text file, I tell the while-loop I'm using to continue if there is something that's not a name on a given line. That seems to throw an exception in some (not all) areas where there are multiple lines without names.
How can I make the program work without throwing exceptions or reading lines without names on them?
My Code:
public class Rewrite {
public static void main(String[] args) {
loadFromFile();
}
private static void loadFromFile() {
String[] names = new String[1000];
try {
FileReader fr = new FileReader("src/res/names/Galaxy_System_Names.txt");
BufferedReader br = new BufferedReader(fr);
String aLine;
int countIndex = 0;
while ((aLine = br.readLine()) != null) {
// skip lines without names
if (aLine.equals(String.valueOf(System.lineSeparator()))) {
aLine = br.readLine();
continue;
} else if (aLine.equals("&")) {
aLine = br.readLine();
continue;
} else if (aLine.startsWith("(")) {
aLine = br.readLine();
continue;
}
System.out.println(aLine);
// capitalize first letter of the line
String firstLetter = String.valueOf(aLine.charAt(0));
aLine = firstLetter + aLine.substring(1);
names[countIndex++] = aLine;
}
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
The Exception Thrown:
Exception in thread "main" java.lang.StringIndexOutOfBoundsException: String index out of range: 0
at java.base/java.lang.StringLatin1.charAt(StringLatin1.java:47)
at java.base/java.lang.String.charAt(String.java:702)
at utilities.Rewrite.loadHumanNamesFromFile(Rewrite.java:39)
at utilities.Rewrite.main(Rewrite.java:10)
Text-File sample: This throws an error after the name "amor"
áed
áedán
aegle
aella
aeneas
aeolus
aeron
(2)
&
aeson
agamemnon
agaue
aglaea
aglaia
agni
(1)
agrona
ahriman
ahti
ahura
mazda
aias
aigle
ailill
aineias
aino
aiolos
ajax
akantha
alberic
alberich
alcides
alcippe
alcmene
alcyone
alecto
alekto
alexander
alexandra
alexandros
alf
(1)
alfr
alkeides
alkippe
alkmene
alkyone
althea
alvis
alvíss
amalthea
amaterasu
amen
ameretat
amirani
ammon
amon
amon-ra
amor
&
amordad
amulius
amun
From the docs of the BufferedReader::readLine:
Returns: A String containing the contents of the line, not including any line-termination characters
Thus when you get to this part of the file:
amor
&
It will read the blank line and strip the linebreak character, and all that will be left is an empty String. Therefore it will not be caught by your if statement:
if (aLine.equals(String.valueOf(System.lineSeparator())))
You need to add in a check for isEmpty()
After amor is an empty line. You're trying to get the char at index 0 of an empty line. Since it's an empty line, it obviously has no chars, and as such there's no char at index 0
I am trying to iterate through a CSV file in Java. It iterates through the entire file, but will get to the end of the file and try to read the next blank line and throw an error. My code is below.
public class Loop() {
public static void main(String[] args) {
BufferedReader br = null;
String line = "";
try {
HashMap<Integer, Integer> changeData = new HashMap<Integer, Integer>();
br = new BufferedReader(new FileReader("C:\\xxxxx\\xxxxx\\xxxxx\\the_file.csv"));
String headerLine = br.readLine();
while ((line = br.readLine()) != null) {
String[] data = line.split(",");
/*Below is my latest attempt at fixing this,*/
/*but I've tried other things too.*/
if (data[0].equals("")) { break; }
System.out.println(data[0] + " - " + data[6]);
int changeId = Integer.parseInt(data[0]);
int changeCv = Integer.parseInt(data[6]);
changeData.put(changeId, changeCv);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
Like I typed, this works fine until it gets to the end of the file. When it gets to the end of the file, I get the error Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0 at com.ucg.layout.ShelfTableUpdates.main(ShelfTableUpdates.java:23). I've stepped through the code by debugging it in Spring Tool Suite. The error comes up whenever I try to reference data[0] or data[6]; likely because there is nothing in that line. Which leads me back to my original question of why it is even trying to read the line in the first place.
It was my understanding that while ((line = br.readLine()) != null) would detect the end of the file, but it doesn't seem to be. I've tried re-opening the file and deleting all of the blank rows, but that did not work.
Any idea how I can detect the end of the file so I don't get an error in this code?
ANSWER:
Credit goes to user #quemeraisc. I also was able to replace the commas with blanks, and if the line then equals null or "", then you know that it is the end of the file; in my case, there are no blank rows before the end of the file. This still does not solve the problem of detecting the end of the file in that if I did have blank rows in between my data that were not the EOF then this would detect those.
Solution 1:
if (data.length < 7) {
System.out.println(data.length);
break;
}
Solution 1:
if (line.replace(",", "").equals(null) || line.replace(",", "").equals("")) {
System.out.println(line.replace(",", ""));
break;
}
Just skip all blank lines:
while ((line = br.readLine()) != null) {
if( line.trim().isEmpty() ) {
continue;
}
....
....
The last line may contain some control characters (like new line, carriage return, EOF and others unvisible chars), in this case a simple String#trim() doesn't remove them, see this answer to know how to remove them: How can i remove all control characters from a java string?
public String readLine() will read a line from your file, even empty lines. Thus, when you split your line, as in String[] data = line.split(","); you get an array of size 1.
Why not try :
if (data.length >= 7)
{
System.out.println(data[0] + " - " + data[6]);
int changeId = Integer.parseInt(data[0]);
int changeCv = Integer.parseInt(data[6]);
changeData.put(changeId, changeCv);
}
which will make sure there are at least 7 elements in your array before proceeding.
To skip blank lines you could try:
while ((line = reader.readLine()) != null) {
if(line.length() > 0) {
String[] data = line.split(",");
/*Below is my latest attempt at fixing this,*/
/*but I've tried other things too.*/
if (data[0] == null || data[0].equals("")) { break; }
System.out.println(data[0] + " - " + data[6]);
int changeId = Integer.parseInt(data[0]);
int changeCv = Integer.parseInt(data[6]);
changeData.put(changeId, changeCv);
}
}
Instead of replace method use replaceAll method. Then it will work.
I'm trying to read from a .java the methods I have on it, also the classes, I'm using taggs to identify them and stored them, the problem is that using BufferedReader sometimes just doesn't work, the buffer skips a lot of lines for a reason that I can't understand, sometimes when checking the file by myself I just put random spaces between lines, and that fixes some parts, but I can't get the Buffer read all my text without skipping anything, my code so far is like this:
public class ReadFile {
public static void main(String[] args) {
int numclas=0,numbase=0,numbaseagr=0,numbmet=0,numag=0;
String mt="//MT";
String[] nomclass2 = new String[10];
String[] nommetodo2 = new String[50];
boolean metodo=false;
BufferedReader in = null;
try {
in = new BufferedReader(new FileReader("\\Program.java"));
String read = null;
while ((read = in.readLine()) != null) {
read = in.readLine();
String[] splited = read.trim().split("\\s+");
for(int i=0;i<splited.length;i++){
System.out.println(splited[i]);
if(splited[i].equals("class")){
nomclass2[numclas]=splited[i+1];
numclas=numclas+1;
}
if (splited[i].equals(mt)){
metodo=true;
}
if (splited[i].equals("public")){
if (splited[i+1].equals("static")){
nommetodo2[numbmet]=splited[i+3];
numbmet=numbmet+1;
}
if (splited[i+1].equals("int")||splited[i+1].equals("double")||splited[i+1].equals("String")||splited[i+1].equals("boolean")){
nommetodo2[numbmet]=splited[i+2];
numbmet=numbmet+1;
}
if (splited[i].equals("int")||splited[i].equals("double")||splited[i].equals("String")||splited[i].equals("boolean")){
nommetodo2[numbmet]=splited[i+1];
numbmet=numbmet+1;
}
metodo=false;
}
if ((splited[i].equals("int")||splited[i].equals("double")||splited[i].equals("String")||splited[i].equals("boolean"))&&metodo){
nommetodo2[numbmet]=splited[i+1];
numbmet=numbmet+1;
metodo=false;
}
}
}
} catch (IOException e) {
System.out.println("There was a problem: " + e);
e.printStackTrace();
} finally {
try {
in.close();
} catch (Exception e) {
}
}
Now let me show you the .java I'm trying to read:
import java.text.DecimalFormat;
import java.io.*;
//Main file of the program 1
public class Program1 {
//MT
public static void main (String args []) {
DecimalFormat format=new DecimalFormat("##.##");
System.out.println("How many data do you want to insert?");
int num=Leer.Int();
Fila lista=new Fila();
Fila lista2=new Fila();
double x=0.0;
for(int i=0;i<num;i++){
x=Leer.Double();
lista.addNum(x);
}
double prom=0.0;
double desv=0.0;
prom=lista.getprom();
desv=lista.getdevst();
System.out.println("The mean for column 1 is: "+format.format(prom));
System.out.println("The Std.Dev for column 1 is: "+format.format(desv));
System.out.println("How many data do you want to insert?");
num=Leer.Int();
x=0.0;
for(int i=0;i<num;i++) {
x=Leer.Double();
lista2.addNum(x);
}
prom=0.0;
desv=0.0;
prom=lista2.getprom();
desv=lista2.getdevst();
System.out.println("The mean for column 2 is: "+format.format(prom));
System.out.println("The Std.Dev for column 2 is: "+format.format(desv));
}
}
And the result when I print the array
Date:
12/12/12
import
java.text.DecimalFormat;
//Main
file
of
the
program
1
//MT
DecimalFormat
format=new
DecimalFormat("##.##");
so on...
See how in the //MT the Buffer skips a lot of lines, a lot of this is happening (see how it ignores the first lines of the program), and I don't know how to fix it, because sometimes when I try to "fix it" and add some spaces in the lines, I get a nullpointer and the program ends.
Any help will be appreciated, thank you.
This is just a partial answer - at the very least your program is skipping every other line:
while ((read = in.readLine()) != null)
will read a line from the file. The line is immediately discarded because the immediately following statement:
read = in.readLine();
reads and processes the next line from the file.
(also, 'splited' should be 'splitted' along with numerous other spelling mistakes but they're not really affecting your program, just it's readability :-))
I'm trying to read a line of text from a text file and put each line into a Map so that I can delete duplicate words (e.g. test test) and print out the lines without the duplicate words. I must be doing something wrong though because I basically get just one line as my key, vs each line being read one at a time. Any thoughts? Thanks.
public DeleteDup(File f) throws IOException {
line = new HashMap<String, Integer>();
try {
BufferedReader in = new BufferedReader(new FileReader(f));
Integer lineCount = 0;
for (String s = null; (s = in.readLine()) != null;) {
line.put(s, lineCount);
lineCount++;
System.out.println("s: " + s);
}
}
catch(IOException e) {
e.printStackTrace();
}
this.deleteDuplicates(line);
}
private Map<String, Integer> line;
To be honest, your question isn't particularly clear - it's not obvious why you've got the lineCount, or what deleteDuplicates will do, or why you've named the line variable that way when it's not actually a line - it's a map from lines to the last line number on which that line appeared.
Unless you need the line numbers, I'd use a Set<String> instead.
However, all that aside, if you look at the keySet of line afterwards, it will be all the lines. That's assuming that the text file is genuinely in the default encoding for your system (which is what FileReader uses, unfortunately - I generally use InputStreamReader and specify the encoding explicitly).
If you could give us a short but complete program, the text file you're using as input, the expected output and the actual output, that would be helpful.
What I understood from your question is to print the lines which do not have duplicate words in the line.
May be you could try the following snippet for it.
public void deleteDup(File f)
{
try
{
BufferedReader in = new BufferedReader(new FileReader(f));
Integer wordCount = 0;
boolean isDuplicate = false;
String [] arr = null;
for (String line = null; (line = in.readLine()) != null;)
{
isDuplicate = false;
wordCount = 0;
wordMap.clear();
arr = line.split("\\s+");
for(String word : arr)
{
wordCount = wordMap.get(word);
if(null == wordCount)
{
wordCount = 1;
}
else
{
wordCount++;
isDuplicate = true;
break;
}
wordMap.put(word, wordCount);
}
if(!isDuplicate)
{
lines.add(line);
}
}
}
catch(IOException e)
{
e.printStackTrace();
}
}
private Map<String, Integer> wordMap = new HashMap<String, Integer>();
private List<String> lines = new ArrayList<String>();
In this snippet, lines will contain the lines which do not have duplicate words in it.
It would have been easier to find your problem if we knew what
this.deleteDuplicates(line);
tries to do. Maybe it is not clearing any of the data structure used. Hence, the words checked in previous lines will be checked for other lines too though they are not present.
Your question is not very clear.
But while going through your code snippet, I think you tried to remove duplicate words in each line.
Following code snippet might be helpful.
public class StackOverflow {
public static void main(String[] args) throws IOException {
List<Set<String>> unique = new ArrayList<Set<String>>();
BufferedReader reader = new BufferedReader(
new FileReader("C:\\temp\\testfile.txt"));
String line =null;
while((line = reader.readLine()) != null){
String[] stringArr = line.split("\\s+");
Set<String> strSet = new HashSet<String>();
for(String tmpStr : stringArr){
strSet.add(tmpStr);
}
unique.add(strSet);
}
}
}
Only problem with your code I see is That DeleteDup doesn't have return type specified.
Otherwise code looks fine and reads from file properly.
Please post deleteDuplicates method code and file used.
You are printing out every line read, not just the unique lines.
Your deleteDuplicateLines() method won't do anything, as there will never be any duplicates in the HashMap.
So it isn't at all clear what your actual problem is.