ArrayIndexOutOfBounds when trying to split a line from reader - java

I am trying to write a java program to parse relevant strings from a .txt file with a certain format.
I want to use the contents of the .txt file to initiate data for my classes. A sample file would look like this:
Movies
Lord of the Rings: 180
Fight Club: 120
...
Theaters
A:100
B:50
C:200
...
Shows
1,1,960
1,1,1080
1,1,1200
1,3,1020
1,3,1140
2,2,990
2,2,1210
...
Prices
Adult:10
Child:7
Senior:8
...
End
This is what I have so far (and it is returning an error when trying to read the above file to initialize my class.
public static void inititializeFromFile(String fileName) throws IOException {
BufferedReader reader = new BufferedReader(new FileReader(fileName));
String line;
while((line = reader.readLine()) != null) {
if(line.equals("Movies")) {
while (!(line.equals("Theaters"))) {
String currentline = line;
String[] parts = currentline.split(":");
String part1 = parts[0];
String part2 = parts[1];
movies.add(new Movie(part1, part2));
}
}
// do basic string comparisons here
if(line.equals("...")) {
// do something
}
else if(line.contains(":")) {
// most likely of type A:100, B:50
}
else if(line.equals("End")) {
// do something
}
else {
// anything else
}
}
reader.close();
}
}

Here is a sample program that will read in the file for you, line by line, and has some scenarios to determine what type of line we are looking at. I was lazy and threw the IOExceptions that might be thrown at me in the code - you should never do this, instead modify the program to use a try catch.
import java.io.*;
public class tmp {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new FileReader("file.txt"));
String line;
while((line = br.readLine()) != null) {
// do basic string comparisons here
if(line.equals("...")) {
// do something
}
else if(line.contains(":")) {
// most likely of type A:100, B:50
}
else if(line.equals("End")) {
// do something
}
else {
// anything else
}
}
br.close();
}
}

Related

Reading and splitting data from a text file

So I have a text file that looks like this...
4234
Bob
6858
Joe
I am trying to read the file with java and insert the data into an array. I want to separate the data by that empty line (space). Here is the code that I have come up with to solve the issue, but I am not quite there.
public class Main {
public static void main(String[] args) {
// This name is used when saving the file
BufferedReader input;
String inputLine;
try {
input = new BufferedReader(new FileReader("test.txt"));
while ((inputLine = input.readLine()) != null) {
System.out.println(Arrays.toString(inputLine.split(" ")));
}
} catch (IOException e) {
System.out.println(e.getMessage());
System.exit(1);
}
}
}
The issue that I am coming across is that the output from the code above looks something like this
[4234]
[Bob]
[]
[6858]
[Joe]
The outcome that I would like to achieve, and for the life of me can't think of how to accomplish, is
[4234, Bob]
[6858, Joe]
I feel like with many things that it is a relatively simple code change; I am just not sure what that is.
You need:
2D array
Logic to keep track of where you are in the array position
If your Line is a Number/String
This sounds like hw :) so I wont be solving it, I will just help a bit.
String[][] myData = define your 2D array;
//You need to create a consumer. This is what will take the String line, figure out where to put it into your 2D array.
Consumer<String> processLine = (line) -> {
if(StringUtils.isNumeric(line)){
//Put into array[counter][1]
}
else{
//its a String
//Put into array[counter][0]
}
};
The below try/catch, Opens a File, Reads its Lines, and goes over each one in order (forEachOrdered), ignoring all empty lines, and send it to your processLine consumer.
try (Stream<String> lines = Files.lines(Paths.get("C:/example.txt"), Charset.defaultCharset())) {
lines.filter(line -> !line.isEmpty()).forEachOrdered(processLine);
}
catch (Exception e){
//Handle Exception
}
Used Apache StringUtils http://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/StringUtils.html
IF you dont want to use any external Libs. You can probably do
Integer.parseInt(line) <-- If that throws an exception, its not a number
Your way of reading the file is not most convenient, in this case.. Scanner would have eased all this work; however, if you insist, that you want to use BufferedReader and FileReader, it's going to be a bit verbose, boilerplate and even ugly code, something like this:
public class Main {
public static void main(String[] args) {
// This name is used when saving the file
BufferedReader input;
String inputLine;
String answer = "";
try {
input = new BufferedReader(new FileReader("path\\to\\your\\test.txt"));
while ((inputLine = input.readLine()) != null) {
answer = answer + "[" + inputLine + ", ";
while ((inputLine = input.readLine()) != null && !inputLine.equals("")) {
answer += inputLine;
}
answer += "]";
System.out.println(answer);
answer = "";
}
} catch (IOException e) {
System.out.println(e.getMessage());
System.exit(1);
}
}
}
This code, with test.txt containing:
4234
Bob
6858
Joe
4234
John
5352
Martin
will output:
[4234, Bob]
[6858, Joe]
[4234, John]
[5352, Martin]
I don't know if it's an actual requirement for you to use arrays of strings, but the better way in the long run is to create a class.
class Person {
public String id;
public String name;
public String toString() { return String.format("[%s, %s]", id, name); }
}
(note: It's a bad idea to actually make the fields public, but this makes the code shorter. You should probably use getters and setters).
Now you can create Persons while reading the file.
List<Person> allInFile = new ArrayList<>();
try (BufferedReader reader = new BufferedReader(new FileReader("path\\to\\your\\test.txt"))) {
String line = reader.readLine();
while (line != null) {
line = line.trim();
// ignore empty lines
if (line.length() == 0) {
continue;
}
// this is an id; create a person and assign id
Person person = new Person();
person.id = line;
// read consecutive field, which is the name
person.name = reader.readLine();
// add the person to the list
allInFile.add(person);
}
}
allInFile.forEach(System.out::println);
Lots of improvements to be done on this, but the main point is to put the two data points into a class.
Try with this code:
it work only when file contains number followed by name otherwise pair would be different format
pair : [number, string]
public static void main(String[] args) {
BufferedReader input;
String inputLine;
List<String> pair = new ArrayList<String>();
List<String> list = new ArrayList<String>();
try {
input = new BufferedReader(new FileReader("Test.txt"));
while ((inputLine = input.readLine()) != null) {
if (!inputLine.isEmpty()) {
pair.add(inputLine);
}
if (pair.size() == 2) {
list.add(pair.toString());
pair.clear();
}
}
for (String s : list) {
System.out.println(s);
}
} catch (IOException e) {
System.out.println(e.getMessage());
System.exit(1);
}
}
After looking at the answers posted by my fellow Stack Overflow members I figured out that there was a very simple way of solving this issue and that was by using Scanner rather than using BufferedReader. I am not sure why I didn't think of this before, but hindsight is 2020. Anyway, the code below is what I used to solve my issue.
public static void main(String[] args) {
ArrayList<String> test = new ArrayList<>();
File file = new File("test.txt");
try {
Scanner sc = new Scanner(file);
while (sc.hasNextLine()) {
test.add(sc.next()); // The id
test.add(sc.next()); // The name
}
sc.close();
System.out.println(test.toString());
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
All this is doing is getting each line with the different data on it and is skipping the blank. From there it is adding it to an ArrayList for later processing. Remember K.I.S.S (Keep It Simple Stupid) no need to overcomplicate anything.

Combine a Read and Parse text.txt

Problem: I can't parse my file test.txt, by spaces. I can 1) read text files, and I can 2) parse strings, but I cannot connect the two and parse a text file! My purpose is to learn how to analyze text files. This is a simplified approach to that.
Progress: Thus far, I can read test.txt using FileReader and BufferedReader, and print it to console. Further, I can parse simple String variables. The individual operations run, but I'm struggling with parsing an actual text file. I believe this is because my test.txt is stored in the buffer, and after I .close() it, I can't print it.
Text File Content:
This is a
text file created, only
for testing purposes.
Code:
import java.io.*;
public class ReadFile {
//create method to split text file, call this from main
public void splitIt(String toTest)
{
String[] result = toTest.split(" ");
for (String piece:result)
{
//loop through the array and print each piece
System.out.print(piece);
}
}
public static void main(String[] args) {
//create readfile method
try
{
File test = new File("C:\\final\\test.txt");
FileReader fileReader = new FileReader(test);
BufferedReader reader = new BufferedReader(fileReader);
String line = null;
//While there are still lines to be read, read and print them
while((line = reader.readLine()) != null)
{
System.out.println(line);
splitIt(line);
}
reader.close();
}
//Catch those errors!
catch (Exception ex)
{
ex.printStackTrace();
}
// readFileMethod a = new readFileMethod(line);
System.out.println(a.splitIt());
}
}
Preemptive thank you for your sharing your knowledge. Many posts on reading and parsing have been solved here on SO, but I've not the understanding to implement others' solutions. Please excuse me, I've only been learning Java a few months and still struggle with the basics.
Ok lets make the splitting into a mthod
private static void splitIt (String toTest) {
String[] result = toTest.split(" ");
for (String piece:result)
{
//loop through the array and print each piece.
System.out.println(piece);
}
}
then you can call it from within
while((line = reader.readLine()) != null)
{
System.out.println(line);
splitIt (line);
}
Building on Scary Wombat and your code, i made some changes.
It should now print the Line that is being read in and each word that is separated by space.
import java.io.*;
public class ReadFile {
//create method to split text file, call this from main
public static void splitIt(String toTest)
{
String[] result = toTest.split(" ");
for (String piece:result)
{
//loop through the array and print each piece
System.out.println(piece);
}
}
public static void main(String[] args) {
//create readfile method
try
{
File test = new File("C:\\final\\test.txt");
FileReader fileReader = new FileReader(test);
BufferedReader reader = new BufferedReader(fileReader);
String line = null;
//While there are still lines to be read, read and print them
while((line = reader.readLine()) != null)
{
System.out.println(line); // print the current line
splitIt(line);
}
reader.close();
}
//Catch those errors!
catch (Exception ex)
{
ex.printStackTrace();
}
}
}

How to detect new line(or empty line) in a file?

I'm trying to write a program, which reads text from a file that is specified by the user. Now, this program should detect an empty line.
This is what I have unsuccessfully tried:
public static void editFile(String filePath) throws FileNotFoundException, IOException {
file = new File(filePath);
if(file.exists()) {
fileRead = new FileReader(file);
bufferedReader = new BufferedReader(fileRead);
String line = bufferedReader.readLine();
System.out.println(line);
while(line != null) {
line = bufferedReader.readLine();
if(line == "") {
//line = null;
System.out.println("a");
}
System.out.println(line);
}
}
}
To be more clear:
If I'm passing in a text file with for example this text:
test1
test2
test3
test4
it should print 2 a's in the console because of the empty spaces, but it doesn't.
Thank you for your time, I am glad for any suggestion you may have.
This is because the comparison is wrong. You can't use == to compare two strings, you need to use the equals method:
if(line.equals(""))
Since you are checking for empty string, you can also write
if(line.isEmpty())
How do I compare strings in java?
BackSlash is entirely correct, and has answered your question. I'd like to add that your code has some errors:
You're not closing the Reader
You're not testing the first line for blank
You're processing the null value when reaching EOF
The following corrects these errors.
public static void editFile(String filePath) throws IOException
{
File file = new File(filePath);
if (file.exists())
{
BufferedReader bufferedReader = new BufferedReader(new FileReader(file));
try
{
String line;
while ((line = bufferedReader.readLine()) != null)
{
if (line.isEmpty())
{
//line = null;
System.out.println("a");
}
System.out.println(line);
}
} finally {
bufferedReader.close();
}
}
}
Output is:
test1
test2
a
test3
a
test4
Note: You're still printing the blank line in addition to the "a".
What you're doing wrong is that you're comparing the variable itself, not its value with a null string.
Generally there are built-in functions in the string class that return true & false for checking if it's == with something.
if(line.equals("")) { ... }
Or you can just use any alternative way.

Counting values in a column of a .csv file Java

I'm tasked, by my professor, to write a program to read a .csv file (778 rows (including header row), 8 columns).
I need to:
1. Write a method to receive the name of the file as its argument and then print the number of lines in the file.
public void printNumberOfLinesInFile(String fileName)
Write a method to receive the name of the file as its argument and then print the number of private and non-private colleges.
public void printNumberOfPrivateNonPrivateCollegesInFile(String fileName)
Write a method to receive the name of the file as its argument and then print the private college name with largest out of state tuition.
public void printMostExpensivePrivateCollegeInFile(String fileName)
Write a method to receive the name of the file as its argument and then print the non-private college with largest out of state tuition.
public void printMostExpensiveNonPrivateCollegeInFile(String fileName)
Write a method to receive the name of the file as its argument and then print the number of applications and the number of applicants that are accepted for private and non-private colleges.
public void printNumberOfApplications(String fileName)
Write a method to receive the name of the file as its argument and then print following information for private and non-private colleges.
Average of expenses for books.
Average of expenses for room.
Average of personal expenses.
public void printAverageOfExpenses(String fileName)
Disclaimer: I do not want anyone to do my homework for me. I need to learn so I can apply my knowledge when I graduate and enter industry. I'm simply asking for a hint or a better way at writing the code.
My code thus far:
public class Week14
{
public String data;
public void printNumberOfLinesInFile(String inFile) throws IOException
{
int collegeCount = 0;
FileReader fileRead = new FileReader(inFile);
BufferedReader bufferRead = new BufferedReader(fileRead);
while(true)
{
String line = bufferRead.readLine();
if(line == null)
{
break;
}
collegeCount++;
//System.out.println(line);
}
System.out.println(collegeCount-1 + " Colleges total.");
}
public void printNumberOfPrivateNonPrivateCollegesInFile(String inFile) throws IOException
{
int privateCount = 0;
int nonprivateCount = 0;
int count = 0;
FileReader fileRead = new FileReader(inFile);
BufferedReader bufferRead = new BufferedReader(fileRead);
while((data = bufferRead.readLine())!= null)
{
String line = bufferRead.readLine();
String [] lineItems = line.split(",");
for(int i = 0; i < line.length(); i++)
{
if(lineItems[i].equals("Yes"))
{
privateCount++;
}
}
break;
}
System.out.println(privateCount+" private Colleges.");
System.out.println(nonprivateCount+ " non-private Colleges.");
}
public void printMostExpensivePrivateCollegeInFile(String inFile) throws FileNotFoundException, IOException
{
int mostExpensive = 0;
int currentExpensive = 0;
FileReader fileRead = new FileReader(inFile);
BufferedReader bufferRead = new BufferedReader(fileRead);
while((data = bufferRead.readLine())!= null)
{
String line = bufferRead.readLine();
if(line.equals("OutstateTuition"))
{
System.out.println(line);
}
else
{
System.out.println(line);
}
}
}
public void printMostExpensiveNonPrivateCollegeInFile(String fileName)
{
}
public void printNumberOfApplications(String fileName)
{
}
public void printAverageOfExpenses(String fileName)
{
}
public static void main(String[] args) throws FileNotFoundException, IOException
{
File inFile = new File("College.csv");
FileReader fileReader = new FileReader(inFile);
BufferedReader buffReader = new BufferedReader(fileReader);
Week14 w1 = new Week14();
//w1.printNumberOfLinesInFile("College.csv");
w1.printNumberOfPrivateNonPrivateCollegesInFile("College.csv");
//^^^The above line goes into an infinite loop^^^
//w1.printMostExpensivePrivateCollegeInFile("College.csv");
}
}
The problem is, I'm stuck on trying to count the amount of private and nonprivate colleges. In my method, printNumberOfPrivateNonPrivateCollegesInFile (line 39), I'm running into an exception: java.lang.ArrayIndexOutOfBoundsException: 8
I've asked my professor how I can avoid this, I've looked online and the problem seems to lie with the iterator int 'i'. I'm trying to traverse the array, and 'i' is out of bounds. When I put a '1' in
if(lineItems[i].equals("Yes"))
for my privateCount, there is an output of 67 from privateCount, (I think it is counting the individual characters for some reason).
My question, what would be the most effective way to traverse the entire .csv file, and to access individual columns so I can count them and output them?
Any help would be greatly appreciated.
edit:
I have changed the while loop:
while(true)
{
String line = bufferRead.readLine();
String [] lineItems = line.split(",");
if(line == null)
{
break;
}
for (String lineItem : lineItems) {
privateCount++;
}
}
Now I can traverse the entire .csv file, but I'm receiving a java.lang.NullPointerException when I try and count.
edit 2:
I've redone my while loop again,
while(true)
{
String line = bufferRead.readLine();
String [] lineItems = line.split(",");
for (String lineItem : lineItems) {
if (lineItem.equals("Yes")) {
privateCount++;
}
}
System.out.println(privateCount);
}
I'm now counting the right value for privateCount, but there's a NullPointerException at :
String [] lineItems = line.split(",");
and the loop will not let me put my 'echo' outside of the while-loop without a 'break' statement.
With respect to actual industry-level code, and assuming that assignment did not specifically focus on actual CSV decoding, I would recommend finding and using a library to handle low-level decoding, such as OpenCSV, SuperCSV or CSV-module for Jackson.
This way your code can focus on more interesting part of finding specific values, and not on intricate details like possible escaping and/or quoting of contents.
If the focus is on CSV edge cases this is not the approach to use; but for real production code one hopefully rarely if ever writes the actual low-level decoding part, given the existence of multiple good libraries for the task.
if(lineItems != null && lineItems.length>0){
// do your loop
}
if (lineItem!= null && !lineItem.trim().equals("") && lineItem.equals("Yes")) {
privateCount++;
}
most likely will prevent your null issue
public void printNumberOfPrivateNonPrivateCollegesInFile(String inFile) throws IOException
{
int privateCount = 0;
int nonprivateCount = 0;
FileReader fileRead = new FileReader(inFile);
BufferedReader bufferRead = new BufferedReader(fileRead);
try
{
while(true)
{
String line = bufferRead.readLine();
String [] lineItems = line.split(",");
//System.out.println(Arrays.toString(lineItems));
for (String lineItem : lineItems)
{
if (lineItem!= null && !lineItem.trim().isEmpty() && lineItem.equals("No"))
{
nonprivateCount++;
}
if (lineItem!= null && !lineItem.trim().isEmpty() && lineItem.equals("Yes"))
{
privateCount++;
}
}
//System.out.println(privateCount);
}
}
catch(NullPointerException npe)
{
}
System.out.println(privateCount);
System.out.println(nonprivateCount);
}
Fixed it. I'm now just catching the exception so it isn't as annoying. Thanks all for the help.

Reading lines with BufferedReader and checking for end of file

If I have something like this in my code:
String line = r.readLine(); //Where r is a bufferedReader
How can I avoid a crash if the next line is the end of the file? (i.e. null)
I need to read the next line because there may be something there that I need to deal with but if there isn't the code just crashes.
If there is something there then all is OK, but I can't be guaranteed that there will be something there.
So if I do something like: (pseudo code):
if (r.readLine is null)
//End code
else {check line again and excecute code depending on what the next line is}
The issue I have with something like this is, that when I check the line against null, it already moves onto the next line, so how can I check it again?
I've not worked out a way to do this - any suggestions would be a great help.
Am... You can simply use such a construction:
String line;
while ((line = r.readLine()) != null) {
// do your stuff...
}
If you want loop through all lines use that:
while((line=br.readLine())!=null){
System.out.println(line);
}
br.close();
You can use the following to check for the end of file.
public bool isEOF(BufferedReader br)
{
boolean result;
try
{
result = br.ready();
}
catch (IOException e)
{
System.err.println(e);
}
return result;
}
In your case you can read the next line because there may be something there.If there isn't anything, your code won't crash.
String line = r.readLine();
while(line!=null){
System.out.println(line);
line = r.readLine();
}
A question in the first place, why don't you use "Functional Programming Approach"? Anyways, A new method lines() has been added since Java 1.8, it lets BufferedReader returns content as Stream. It gets all the lines from the file as a stream, then you can sort the string based on your logic and then collect the same in a list/set and write to the output file. If you use the same approach, there is no need to get worried about NullPointerException. Below is the code snippet for the same:-
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.stream.Collectors;
public class LineOperation {
public static void main(String[] args) throws IOException {
Files.newBufferedReader(Paths.get("C://xyz.txt")).
lines().
collect(Collectors.toSet()). // You can also use list or any other Collection
forEach(System.out::println);
}
}
You can do it via BufferReader. I know this is not relevant to following question. But I would post it for extra fact for a newbie who would not use BufferReader but Scanner for reading file.
A part from BufferReader you could use Java Scanner class to read the file and check the last line.
Buffer Reader
try (BufferedReader br = new BufferedReader(new FileReader(file))) {
String line;
while ((line = br.readLine()) != null) {
// process the line
}
}
Scanner
try {
Scanner scanner = new Scanner(new FileReader(file));
while (scanner.hasNext()) {
// Above checks whether it has or not ....
}
} catch (IOException e) {
e.printStackTrace();
}
If you use this code fragment in a multi threaded environment, go ahead with BufferReader since its synchronized.
In addition, BufferReader is faster than Scanner.
If you would like to do some check like:
if (reader.ready())
stringBuilder.append("#");
You can use ready()
public static void check() throws IOException {
InputStream in = new FileInputStream(new File(filePath));
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
StringBuilder stringBuilder = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
stringBuilder.append(line);
if (reader.ready())
stringBuilder.append("#");
}
String returnedString = stringBuilder.toString();
System.out.println(returnedString);
}
You could purposely have it throw the error inside your loop. i.e.:
String s = "";
while (true) {
try {
s = r.readline();
}catch(NullPointerException e) {
r.close();
break;
}
//Do stuff with line
}
what everyone else has sad should also work.

Categories

Resources