*The following code builds a "2D" array from strings in a text file. At present it is returning a NullPointException error on the line:
temp = thisLine.split(delimiter);
My question is, am I correct in understanding that temp is returning null? If so, why, and how do I add a check for null? I'm rather new to Java, and this is my first attempt at creating a string array of arrays from a file.*
--------Edit--------
The above has been solved.
For those interested below is the code returning a IndexOutOfBoundsException. Specifically the line:
fileContents.set(i, fileContents.get(i).replace(hexLibrary[i][0], hexLibrary[i][1]));
System.out.println("SnR after this");
String[][] hexLibrary; // calls the replaces array from the LibToArray method
hexLibrary = LibToArray();
for(int i=0;i<502;i++){
{
fileContents.set(i, fileContents.get(i).replace(hexLibrary[i][0], hexLibrary[i][1]));
}
}
for (String row : fileContents) {
System.out.println(row); // print array to cmd
}
______________________________
public static String[][] LibToArray()
{
String thisLine;
String[] temp;
String delimiter=",";
String [][] hexLibrary = new String[502][2];
try
{
BufferedReader br= new BufferedReader(new FileReader("hexlibrary.txt"));
for (int j=0; j<502; j++) {
thisLine=br.readLine();
temp = thisLine.split(delimiter);
for (int i = 0; i < 2; i++) {
hexLibrary[j][i]=temp[i];
}
}
}
catch (IOException ex) { // E.H. for try
JOptionPane.showMessageDialog(null, "File not found. Check name and directory."); // error message
}
return hexLibrary;
}
It's more likely that thisLine is null. That will happen if you run out of input before 502 lines are read. If thisLine is not null, then thisLine.split(delimiter) will not return null. You should always check for a null line:
for (int j=0; j<502; j++) {
thisLine=br.readLine();
if (thisLine != null) {
temp = thisLine.split(delimiter);
for (int i = 0; i < 2; i++) {
hexLibrary[j][i]=temp[i];
}
} else {
// report error: premature end of input file
break; // no point in continuing to loop
}
}
Personally, I'd write your method to not assume any particular file length:
public static String[][] LibToArray() {
List<String[]> lines = new ArrayList<>();
String delimiter=",";
try (BufferedReader br= new BufferedReader(new FileReader("hexlibrary.txt"))) {
String line = br.readLine();
while (line != null) {
String[] tmp = line.split(delimiter);
// the next line is dangerous--what if there was only one token?
// should add a check that there were at least 2 elements.
lines.add(new String[] {tmp[0], tmp[1]});
line = br.readLine();
}
} catch (IOException ex) {
JOptionPane.showMessageDialog(null, "File not found. Check name and directory.");
}
String[][] hexLibrary = new String[lines.length][];
lines.toArray(hexLibrary);
return hexLibrary;
}
(The above uses the new Java 7 try-with-resources syntax. If you're using an earlier Java, you should add a finally clause that closes br before the method returns.
If the first line (or any line) of hexlibrary.txt is empty or is not delimited by ","s, the String array returned by split() will probably be null.
To check for that, just add an if-condition around your second for loop, something like this:
if (temp == null) { /* your loop here */ }
You are not checking for end of the stream while reading the file.
Method readLine returns a null if the reader reaches end of the stream. You are hitting this point (null) in the first for loop (before it exits), depending on number of lines in the text file.
Related
I need to read a text file into a 2D array, I can read files into the program perfectly fine (see my code below) however I cannot get my head around how to read them into a 2D array. The array the function is reading into is a global array hence why it's not in the function.
Also I won't know the amount of rows the array has at first (currently set at 300 as it won't be over this) and I know this could cause a problem, I've seen some people suggest using ArrayLists however I have to have a 2D array so I was also wondering if there was a way to change an ArrayList to a 2D array and if this would be more effective?
public static String readMaze(String fileName) {
String line = null;
try {
FileReader fileReader = new FileReader(fileName);
BufferedReader bufferedReader = new BufferedReader(fileReader);
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
for (int i = 0; i < mazeNew.length; i++) {
for (int j = 0; j < mazeNew[i].length; j++) {
// mazeNew[i][j] = ; - this is where I think something needs to be added
}
}
}
bufferedReader.close();
}
catch (FileNotFoundException ex) {
System.out.println("Unable to open file: " + fileName);
}
catch (IOException ex) {
System.out.println("Error reading file: " + fileName);
}
return fileName;
}
example text file:
11 4
5 6
4 6
0 5
3 5
8 7
1 4
There's a few options here, but generally you'll want to use the Java Scanner class as it's designed for exactly this kind of thing. Alternatively, use an existing structured data format (like JSON or XML) and an existing parser to go with it - the advantage being you can make use of a vast amount of tools and libraries which deal with those formats and don't have to re-invent anything.
However, following through with the scanner approach, it would be like so:
public static ArrayList<int[]> readMaze(String fileName) {
// Number of ints per line:
int width=2;
// This will be the output - a list of rows, each with 'width' entries:
ArrayList<int[]> results=new ArrayList<int[]>();
String line = null;
try {
FileReader fileReader = new FileReader(fileName);
BufferedReader bufferedReader = new BufferedReader(fileReader);
Scanner mazeRunner = new Scanner(bufferedReader);
// While we've got another line..
while (mazeRunner.hasNextLine()) {
// Setup current row:
int[] row = new int[width];
// For each number..
for (int i = 0; i < width; i++) {
// Read the number and add it to the current row:
row[i] = mazeRunner.nextInt();
}
// Add the row to the results:
results.add(row);
// Go to the next line (optional, but helps deal with erroneous input files):
if ( mazeRunner.hasNextLine() ) {
// Go to the next line:
mazeRunner.nextLine();
}
}
mazeRunner.close();
}
catch (FileNotFoundException ex) {
System.out.println("Unable to open file: " + fileName);
}
catch (IOException ex) {
System.out.println("Error reading file: " + fileName);
}
return results;
}
If you have fixed no. of columns you can use this, but make sure input file must follow the same no of coulmns.
FileReader fileReader = new FileReader(fileName);
Scanner sc = new Scanner(fileReader);
int row=0, col=0;
while ((sc.hasNext()) != null) {
if(col < colSize){ //colSize is size of column
mazeNew[row][col]= sc.nextInt();
}
else{
col=0;
row++;
}
}
Below is the core logic, you would probably also like to to handle some errors, such as how many elements is a line split into, are there empty lines, etc.
List<String[]> list = new ArrayList<>();
Pattern pattern = Pattern.compile("\\s+");
while ((line = bufferedReader.readLine()) != null) {
list.add(pattern.split(line, -1));
}
String[][] mazeNew = list.toArray(new String[0][0]);
Something like this would work
it wont only read 2d text files .. it should work fine with any dimensions
public class Utile{
public static ArrayList<int[]> readMaze(String path){
ArrayList<int[]> result = new ArrayList<>();
try{
Scanner sc = new Scanner(new File(path));
String[] temp;
String line;
while(sc.hasNextLine()){
line = sc.nextLine();
if (line.length() != 0){ //if the line is empty it will cause NumberFormatException
temp = line.split(" ");
int[] val = new int[temp.length];
for(int i = 0;i < temp.length;i++){
val[i] = Integer.pareseInt(temp[i]);
}
result.add(val);
}
}
sc.close();
}catch(Exception e){
e.printStackTrace(); //just log it for now
}
return result;
}
}
I am not a java expert, but in PHP I would do it with explode(). But I found an example how to do the same in java using string.split(). The result is the same ... an 2D Array of the content. If possible you should try to add an delimiter to the rows inside that text document. But you could split the rows on the space character either.
Example:
String foo = "This,that,other";
String[] split = foo.split(",");
StringBuilder sb = new StringBuilder();
for (int i = 0; i < split.length; i++) {
sb.append(split[i]);
if (i != split.length - 1) {
sb.append(" ");
}
}
String joined = sb.toString();
Just at it says in the title, I can save something inside the rtf file sometimes(my save function is a working progress). Im using a mac, and i cant save as a txt. I do not know if this is normal or not and I having troubles with it since I dont know why but I get an arrayoutofbounds error when I try to use the line Player p = new Player(splitLine[0], splitLine[1], splitLine[2]);
Here is my read and write code.
final String FILE_PATH = "/Users/macbookair/Desktop/comp sci ia/TypingPractice/Player records.rtf";
BufferedReader reader;
PrintWriter writer;
Player[] readRecords() {
// This is called by AppLogic.load() which runs when the AppLogic is
// instantiated.
// The array of Person objects that we create from the load file
// This holds the current line from the load file
String nextLine;
// This is a two-element array that holds name/surname once it has
// been split at the # sign
String[] splitLine = new String[4];
for(int i=0; i< splitLine.length;i++){
splitLine[i] = "0";
}
// This is just a counter of how many lines I've read in
int count = 0;
try {
reader = new BufferedReader(new FileReader(FILE_PATH));
// Get the first line
nextLine = reader.readLine();
// Loop until we've been through every line in the file
while (nextLine != null) {
// Split the current line at the # sign
splitLine = nextLine.split("#");
Player p = new Player(splitLine[0], splitLine[1], splitLine[2]);
// Put it in the array
playerArray[count] = p;
// Increment the counter
count = count + 1;
// Get the next line
nextLine = reader.readLine();
}
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
void writeRecords(Player[] p) {
try {
writer = new PrintWriter(new FileWriter(FILE_PATHPhrase));
// Loop through each Person in the Person array
for (int i = 0; i < p.length; i++) {
// Write the name, then a # sign, then the surname
writer.println(p[i].getWPM() + "#" + p[i].getMistakes() + "#" + p[i].getTime());
}
} catch (Exception e) {
e.printStackTrace();
}
writer.close();
}
I have loaded from text files many times before without thi issue, I have read and re-read my code and I (personally) cant see why I would get this issue, I am completely lost.
static public ArrayList<Media> importMedia(String fileName) throws IOException
{
try {
ArrayList<Media> mList = new ArrayList<>();
BufferedReader reader = new BufferedReader(new FileReader(fileName));
String line = reader.readLine();
int numberOfItems = Integer.valueOf(line);
while((line = reader.readLine()) != null)
{
String[] split = line.split(",");
if(split[0].contains("mp3"))
{
Mp3 mp3 = new Mp3(split[1]/*title*/,split[0]/*filename*/,Integer.parseInt(split[4])/*releaseyear*/,split[2]/*artist*/,split[3]/*album*/,split[5]/*label*/,Double.parseDouble(split[6])/*runtime*/);
mList.add(mp3);
}else if (split[0].contains("gif"))
{
Gif gif = new Gif(split[1]/*title*/,split[0]/*filename*/,Integer.parseInt(split[6])/*releaseyear*/,Double.parseDouble(split[2])/*width*/,Double.parseDouble(split[3])/*height*/,split[4]/*equipName*/,split[5]/*equipModel*/);
mList.add(gif);
}else if(split[0].contains("avi"))
{
String castNames = "";
boolean first = true;
for(int i = 7; i < 15; i++)
{
if(!(split[i].isEmpty()))
{
if(first)
{
castNames += split[i];
first = false;
}else{
castNames += "," + split[i];
}
}
}
Avi avi = new Avi(split[1]/*title*/,split[0]/*filename*/,Integer.parseInt(split[3])/*releaseyear*/,split[2]/*studio*/,split[5]/*director*/,castNames/*castnames*/,Double.parseDouble(split[4])/*runtime*/,Integer.parseInt(split[6])/*cast*/);
mList.add(avi);
}else{
}
}
return mList;
} catch (Exception ex) { System.out.println(ex.toString()); }
return null;
}
Now it will only get the first 3 files(Console shown in picture)
I am simply trying to loop through and I am not sure why it would be out of bounds, I cannot see anything wrong with the loop, or why its giving me some but not all.
In this code you are using a String Array split from index 0 to index 14.
It would be good to do some defensive programming by checking length of String Array.
Please check the length of array before proceeding to use it in your programme.
like split.length >14
By using this habit you can always escape from 'ArrayIndexOutOfBoundsException'
I am trying to read information from a file. The first thing in the file is an integer, but when I try to read it I get a NullPointerException. I also tried reading the first thing in the file as a string, and again I got a NullPointerException. I then added the print statement that is in the catch statement when I connect the file. When I run the code, that print statement is evaluated. What is the source of my issue? Thanks.
private boolean collectSystem(String loc) {
Scanner fileIn = null;
try {
fileIn = new Scanner(new File(loc));
} catch (FileNotFoundException e) {
System.out.println("File not found, IntakeSystem");
}
// Determine number of equations
try {
n = fileIn.nextInt();
} catch (InputMismatchException e) {
return false;
}
// Collect the text in the file as a string
String info = "";
while (fileIn.hasNextLine()) {
info = info + fileIn.nextLine();
}
fileIn.close();
//Separate equations in file
String[] eqns = new String[n];
int start = 0;
int end = info.indexOf(";");
for (int i = 0; i < n; i++) {
if(end == -1) return false;
String nextLine = info.substring(start, end);
eqns[i] = nextLine;
start = end + 1;
end = info.indexOf(";", start);
}
for (int i = 0; i < n; i++) {
System.out.println(eqns[n]);
}
return true;
}
From the comments what is happening is that you are passing in a path that points to a file that doesn't exist, Make sure you are actually passing in a valid file path first.
A way to make it easier with debugging:
Replace System.out.println("File not found, IntakeSystem"); in the first catch block with throw new IllegalArguementException(e) or return false;, because otherwise your file object will still be null and the execution will continue if the String loc argument does not point to an existing file; Which via the OP comments is your issue.
I am able to read a file using a Scanner. When the return type is void, I am able to read and print the data to the console, however, immediately afterward it throws an ArrayOutOfBoundsException. Ideally, I want to return as a string array, however, I only get an ArrayOutOfBoundsException. In both cases, the exception is thrown at the line cancers[j] = input.nextLine(). I have already made sure the size of the array is correct. When I do not hardcode the size of it, then the compiler throws a NullPointerException at the same line (which makes sense since the size of the array is not declared).
I need the method to return a string array as I have to do additional manipulations to it.
public String[] readCancer() {
cancers = new String[21];
int j = 0;
try {
input = new Scanner(myData);
String result;
while(input.hasNext()) {
++j;
cancers[j] = input.nextLine();
//System.out.println(cancers[j]);
}
} catch (FileNotFoundException fnfx) {
JOptionPane.showMessageDialog(null, "Txt file could not be found");
}
return cancers;
}
I tried re-writing the method in a slightly different way but I get the same error, only this time it is at output[i] = result;
public String[] readCancers() {
FileInputStream fis;
DataInputStream dis;
BufferedReader br;
InputStreamReader isr;
String result;
String[] output = new String[21];
int i = 0;
try {
fis = new FileInputStream(myData);
dis = new DataInputStream(fis);
isr = new InputStreamReader(dis);
br = new BufferedReader(isr);
while((result = br.readLine()) != null) {
++i;
output[i] = result;
}
} catch (FileNotFoundException fnfx) {
fnfx.printStackTrace();
} catch (IOException iox) {
iox.printStackTrace();
}
return output;
}
It's hard to know how many elements your file has but I'm assuming you have 21 elements and so you need a 21 element array. You've declared an array of 21 elements but the following code:
++j;
Means the following:
j = j+1;
And then you add an element to your array using j which results in you skipping j = 0 completely and the 21st item tries to get placed at the 22nd element of the array, which is out of bounds. What you might want is something like this:
cancers[j];
j++;
Or:
cancers[j++];
That way you're not going to go out of bounds. If you have more than 21 items then I'd suggest you increase the array size.
As the commenters to your question: it can be an off-by-one type error, because you skipped the first array element. But once you have a fixed size array to read in, you'd have to bound check the value of i or j in the while loop in any case: while(input.hasNext() && j < 20) or while((result = br.readLine()) != null && i < 21).
Then after the loop check if there would be any extra input, that may indicate an error, you have to handle that.