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.
Related
I am taking data from a text file and putting it into an ArrayList. However the first line of the text file is not being printed out.
public static void secondMain() {
BufferedReader reader;
var lines = new ArrayList<String>();
var rooms = new ArrayList<Room>();
try {
reader = new BufferedReader(new FileReader("rooms.txt"));
String line = reader.readLine();
while (line != null) {
line = reader.readLine();
lines.add(line);
}
reader.close();
for (int i = 0; i < lines.size() - 1; i++) {
String[] words = lines.get(i).split(" ");
var room = new Room();
room.RoomNumber = Integer.parseInt(words[0]);
room.Type = (words[1]);
room.Price = Double.parseDouble(words[2]);
room.Bool1 = Boolean.parseBoolean(words[3]);
room.Bool2 = Boolean.parseBoolean(words[4]);
room.Availability = (words[5]);
rooms.add(room);
}
for(int i = 0; i < rooms.size(); i++) {
System.out.println(rooms.get(i).RoomNumber);
System.out.println(rooms.get(i).Type);
System.out.println(rooms.get(i).Price);
System.out.println(rooms.get(i).Bool1);
System.out.println(rooms.get(i).Bool2);
System.out.println(rooms.get(i).Availability);
}
Apologies for the Image, it was the only way i could figure out how to show the formatting of the text file.
The current output is displaying room number 102 as the first room which obviously isn't correct.
If anyone could also help me figure out how to format my console output the same way as the text file that'd also be great. currently it is displaying each individual string/int etc. on a different line.
Thanks.
If you need any more information please just ask!
This has nothing to do with the ArrayList. You can reproduce the problem by replacing the lines.add(line) call with System.out.println(line) and you'll see that the first line is missing from the output. Look at your first call to readLine(), before the while loop. You test that the value is non-null... and that's all you do with it (comments mine):
String line = reader.readLine(); // Read the value...
while (line != null) { // Test for it being non-null
line = reader.readLine(); // Then ignore the value you've just tested,
// by reading the next line.
lines.add(line);
}
You then call readLine() again. Note that your list will always end with a null value (unless it's the first line read) because your loop effectively says "while the last entry I added to the list isn't null". The simplest fix is to swap the order of the statements within your loop:
String line = reader.readLine();
while (line != null) {
lines.add(line);
line = reader.readLine();
}
Now you're adding a line immediately after checking whether it's non-null, before reading the next line.
The problem is here:
String line = reader.readLine(); // you read the first line
while (line != null) {
line = reader.readLine(); // read second line
lines.add(line); // add second line
}
You read the first line, check if it's not null, and then read the second line right away, before you add it to the list. All you need to do is switch the order.
String line = reader.readLine();
while (line != null) {
lines.add(line);
line = reader.readLine();
}
I am entering values to Bidimap. In each loop I am put(ing) values into the Bidimap and I am also printing the size of the Bidimap. It is always 1. I have also checked value of map through debbugger and it shows only one value which is the present value being put in the most recent iteration in the map. What is going wrong here? How am I suppose to save key-value in the Bidimap.
Please find below the complete code.
public static void main(String args[])
{
//Read file
BufferedReader br = null;
int wordCount=0;
String wordArray[] = null;
BidiMap<String, Integer> map = new DualHashBidiMap<String, Integer>();
try {
String sCurrentLine;
br = new BufferedReader(new InputStreamReader(new FileInputStream("C:\\IASTATE\\test.txt"), StandardCharsets.UTF_16));
while ((sCurrentLine = br.readLine()) != null) {
System.out.println(sCurrentLine);
wordArray = sCurrentLine.split("\\s+");
wordCount += wordArray.length;
}
//Read word 1,word 2,word 3
int count;
String key;
for(int i=0;i<wordArray.length;i++)
{
key=wordArray[i]+wordArray[i+1]+wordArray[i+2];
//Compare Hashmap if the String {'word 1','word 2','word 3'}
//exists
if(map.containsKey(key))
{
//If exists increment counter
count=(Integer) map.get(key);
count++;
map.put(key, count);
}
else
{
//If doesnot exist push String {'word 1','word 2','word 3'}
//in the Hashmap and initialize counter to 1
map.put(key, 1);
}
key=null;
System.out.println("Size of Map"+map.size());
}
} catch (IOException e) {
e.printStackTrace();
}
}
test.txt content is
This is line one
This is line two
This is line three
This is line four
You're reading every single line of the file but you're not processing any of those lines until after you've finished:
while ((sCurrentLine = br.readLine()) != null) {
System.out.println(sCurrentLine);
wordArray = sCurrentLine.split("\\s+");
wordCount += wordArray.length;
}
// Now you're messing about with wordArray, which is the _last_ line.
It's possible that your intent is to append all the words of each line to the wordArray array but that's not what you're doing.
That means you're only processing the last line of your file. If the last line is truly "this is line four", I'd still expect two entries, one for "this is line" and another for "is line four". But I'd fix up the problem described above before you start worrying about that.
By fixing it, I mean not overwriting wordArray every time a line is read in but instead appending to that array.
I have this program that reads a text file. I need to get some data out of it.
The text files look like this:
No. Ret.Time Peak Name Height Area Rel.Area Amount Type
min µS µS*min % mG/L
1 2.98 Fluoride 0.161 0.028 0.72 15.370 BMB
2 3.77 Chloride 28.678 3.784 99.28 2348.830 BMB
Total: 28.839 3.812 100.00 2364.201
I need to start reading from line #29 and from there get the Peak Name and the Amount of each element like Fluoride, Chloride and so on. The example only shows those two elements, but other text files will have more. I know I will need some sort of loop to iterate through those lines starting on line #29 which is where the "1" starts then the "2" which will be the 30th line and so on.
I have tried to make this work, but I am missing something I think and I`m not sure what. Here is my Code.
int lines = 0;
BufferedReader br = new BufferedReader(new FileReader(selectFile.getSelectedFile()));
Scanner sc = new Scanner(new FileReader(selectFile.getSelectedFile()));
String word = null;
while((word =br.readLine()) != null){
lines++;
/*if(lines == 29)
System.out.println(word);*/
if ((lines == 29) && sc.hasNext())
count++;
String value = sc.next();
if (count == 2)
System.out.println(value + ",");
}
Here's some code for you:
int linesToSkip = 28;
try (BufferedReader br = new BufferedReader(new FileReader(file))) {
String line;
while ( (line = br.readLine()) != null) {
if (linesToSkip-- > 0) {
continue;
}
String[] values = line.split(" +");
int index = 0;
for (String value : values) {
System.out.println("values[" + index + "] = " + value);
index++;
}
}
}
Note that I've surrounded it in a try(expr) {} block to ensure that the reader is closed at the end, otherwise you'll consume resources and possibly lock the file from other processes.
I've also renamed the variable you called word as line to make it clearer what it contains (i.e. a string representing a line in the file).
The line.split(" +") uses a regular expression to split a String into its constituent values. In this case your values have spaces between, so we're using " +" which means 'one or more spaces'. I've just looped through the values and printed them out; obviously, you will need to do whatever it is you need to do with them.
I replaced the line count with a linesToSkip variable that decrements. It's less code and explains better what you're trying to achieve. However, if you need the line number for some reason then use that instead, as follows:
if (++lineCount <= 28) {
continue;
}
If I'm reading it correctly, you are mixing two different readers with the BufferedReader and the Scanner, so you are not going to get the results right changing from one to the other (one is not pointing to the same position than the other). You already have the line in word and you can parse it, no need of using the Scanner. Just skip until line 29 (lines > 29) and then parse the values you want, line by line.
You are reading the file twice... try something like this
int lines = 0;
BufferedReader br = new BufferedReader(new FileReader(selectFile.getSelectedFile()));
String line = null;
while ((line = br.readLine()) != null) {
if (++lines < 29)
continue; //this ignores the line
for(String word : line.split("separator here")) {
// this will iterate over every word on that line
// I think you can take it from here
System.out.println(word);
}
}
I have a csv file that currently has 20 lines of data.
The data contains employee info and is in the following format:
first name, last name, Employee ID
So one line would like this: Emma, Nolan, 2
I know how to write to the file in java and have all 20 lines print to the console, but what I'm not sure how to do is how to get Java to print one specific line to the console.
I also want to take the last employee id number in the last entry and have java add 1 to it one I add new employees. I thinking this needs to be done with a counter just not sure how.
You can do something like this:
BufferedReader reader = new BufferedReader(new FileReader(<<your file>>));
List<String> lines = new ArrayList<>();
String line = null;
while ((line = reader.readLine()) != null) {
lines.add(line);
}
System.out.println(lines.get(0));
With BufferedReader you are able to read lines directly. This example reads the file line by line and stores the lines in an array list. You can access the lines after that by using lines.get(lineNumber).
You can read text from a file one line at a time and then do whatever you want to with that line, print it, compare it, etc...
// Construct a BufferedReader object from the input file
BufferedReader r = new BufferedReader(new FileReader("employeeData.txt"));
int i = 1;
try {
// "Prime" the while loop
String line = r.readLine();
while (line != null) {
// Print a single line of input file to console
System.out.print("Line "+i+": "+line);
// Prepare for next loop iteration
line = r.readLine();
i++;
}
} finally {
// Free up file descriptor resources
r.close();
}
// Remember the next available employee number in a one-up scheme
int nextEmployeeId = i;
BufferedReader reader =new BufferedReader(new FileReader("yourfile.csv"));
String line = "";
while((line=reader.readLine())!=null){
String [] employee =line.trim().split(",");
// if you want to check either it contains some name
//index 0 is first name, index 1 is last name, index 2 is ID
}
Alternatively, If you want more control over read CSV files then u can think about CsvBeanReader that will give you more access over files contents..
Here is an algorithm which I use for reading csv files. The most effective way is to read all the data in the csv file into a 2D array first. It just makes it a lot more flexible to manipulate the data.
That way you can specify which line of the file to print to the console by specifying it in the index of the array and using a for. I.e: System.out.println(employee_Data[1][y]); for record 1. y is the index variable for fields. You would need to use a For Loop of course, to print every element for each line.
By the way, if you want to use the employee data in a larger program, in which it may for example store the data in a database or write to another file, I'd recommend encapsulating this entire code block into a function named Read_CSV_File(), which will return a 2D String array.
My Code
// The return type of this function is a String.
// The CSVFile_path can be for example "employeeData.csv".
public static String[][] Read_CSV_File(String CSVFile_path){
String employee_Data[][];
int x;
int y;
int noofFields;
try{
String line;
BufferedReader in = new BufferedReader(new FileReader(CSVFile_path));
// reading files in specified directory
// This assigns the data to the 2D array
// The program keeps looping through until the line read in by the console contains no data in it i.e. the end of the file.
while ( (( line = in.readLine()) != null ){
String[] current_Record = line.split(",");
if(x == 0) {
// Counts the number of fields in the csv file.
noofFields = current_Record.length();
}
for (String str : values) {
employee_Data[x][y] = str;
System.out.print(", "+employee_Data[x][y]);
// The field index variable, y is incremented in every loop.
y = y + 1;
}
// The record index variable, x is incremented in every loop.
x = x + 1;
}
// This frees up the BufferedReader file descriptor resources
in.close();
/* If an error occurs, it is caught by the catch statement and an error message
* is generated and displayed to the user.
*/
}catch( IOException ioException ) {
System.out.println("Exception: "+ioException);
}
// This prints to console the specific line of your choice
System.out.println(("Employee 1:);
for(y = 0; y < noofFields ; y++){
// Prints out all fields of record 1
System.out.print(employee_Data[1][y]+", ");
}
return employee_Data;
}
For reading large file,
log.debug("****************Start Reading CSV File*******");
copyFile(inputCSVFile);
StringBuilder stringBuilder = new StringBuilder();
String line= "";
BufferedReader brOldFile = null;
try {
String inputfile = inputCSVFile;
log.info("inputfile:" + inputfile);
brOldFile = new BufferedReader(new FileReader(inputfile));
while ((line = brOldFile.readLine()) != null) {
//line = replaceSpecialChar(line);
/*do your stuff here*/
stringBuilder.append(line);
stringBuilder.append("\n");
}
log.debug("****************End reading CSV File**************");
} catch (Exception e) {
log.error(" exception in readStaffInfoCSVFile ", e);
}finally {
if(null != brOldFile) {
try {
brOldFile.close();
} catch (IOException e) {
}
}
}
return stringBuilder.toString();
I have a Code where I am scanning the lines using Scanner Class and looping till there are no lines left.
My code looks like this:
File file = new File(filePath);
if (file.exists()) {
Scanner s = new Scanner(file);
String tmp = null;
int result = 0;
try {
while (true) {
tmp = s.nextLine();
if (tmp != null && tmp.equals("")) {
result += Integer.parseInt(tmp);
}
System.out.println(runSequence(Integer.parseInt(tokens[0])));
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(result);
}
It gives the error at
tmp = s.nextLine();
java.util.NoSuchElementException: No line found
Which is odd because earlier the same code was working fine.
Why is this line giving an error?
Edit:
My mistake i did not state the question correctly, i particularly left the try catch block out of the while loop so that i could make an exit when the lines ended...My question is why am i not able to read any of the lines...i have about 3-4 lines to read in the txt file and it is not reading any and giving exception at the first line read itself...
I think the better way to code is to have a condition in your while loop using Scanner#hasNextLine(). Scanner#hasNextLine() would make sure that code inside while would only run if it has a line in the file=.
while (s.hasNextLine()) {
tmp = s.nextLine();
if (tmp != null && tmp.equals("")) {
result += Integer.parseInt(tmp);
}
if (tmp != null && tmp.equals(""))
should be (if you are trying to check given string is not empty string)
if (tmp != null && !tmp.isEmpty())
I think you reach at the end of file where there is no remaining line and your condition is while(true) so it tries to read that time also . So you getting NoSuchElementException(if no line was found )
So better to change your while loop as
while (s.hasNextLine()){
tmp = s.nextLine();
// then do something
}
while (s.hasNextLine())
{
//...
}