Issue during reading a CSV file has me stumped - java

I'm trying to write a method that simply reads in a CSV file and stores the data from the file. Here is a link to a screenshot of the CSV file I am trying to read in, and the code for this method:
http://i.imgur.com/jsGTg.png
public static void correctPrices(String correctfile) {
String data;
Date date;
SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy");
File correctedfile = new File(correctfile);
Scanner correct;
try {
correct = new Scanner(correctedfile);
correct.nextLine(); //to avoid reading the heading
ArrayList<Date> correctdate = new ArrayList<Date>();
ArrayList<String> correctdata = new ArrayList<String>();
while (correct.hasNext()) {
correctdata.add(correct.nextLine());
//data = correct.nextLine();
//String[] corrected = correct.nextLine().split(",");
//date = formatter.parse(corrected[0]);
//correctdate.add(date);
}
for (int i = 0; i < correctdata.size(); i++) {
System.out.println(correctdata.get(i));
}
}
catch (FileNotFoundException ex) {
Logger.getLogger(DataHandler.class.getName()).log(Level.SEVERE, null, ex);
}
}
As expected, this code would output the last 2 lines of the file. However, when I un-comment data = correct.nextLine(); in the while loop, the output will only return the second line of the CSV, and not the last line. I'm a little baffled by this? All I've tried to do was to store the line into another variable, why would the last line be omitted? Thanks for your help and time, let me know if you need any additional info!

The problem is, when you call correct.nextLine(), it reads in a line and then increments a pointer in the file to where you are reading. Since you call that multiple times in the loop, it increments the pointer multiple times, skipping lines. What you should do is just read the line once, in the beginning of the while loop using
data = correct.nextLine();
and then replace correct.nextLine() everywhere else it appears in the loop with data.
In other words, your while loop would look like
while (correct.hasNext())
{
data = correct.nextLine();
correctdata.add(data);
String[] corrected = data.split(",");
date = formatter.parse(corrected[0]);
correctdate.add(date);
}

Related

Importing two CSV files into Java and then parsing them. The first one works the second doesnt

Im working on my code where I am importing two csv files and then parsing them
//Importing CSV File for betreuen
String filename = "betreuen_4.csv";
File file = new File(filename);
//Importing CSV File for lieferant
String filename1 = "lieferant.csv";
File file1 = new File(filename1);
I then proceed to parse them. For the first csv file everything works fine. The code is
try {
Scanner inputStream = new Scanner(file);
while(inputStream.hasNext()) {
String data = inputStream.next();
String[] values = data.split(",");
int PInummer = Integer.parseInt(values[1]);
String MNummer = values[0];
String KundenID = values[2];
//System.out.println(MNummer);
//create the caring object with the required paramaters
//Caring caring = new Caring(MNummer,PInummer,KundenID);
//betreuen.add(caring);
}
inputStream.close();
}catch(FileNotFoundException d) {
d.printStackTrace();
}
I then proceed to parse the other csv file the code is
// parsing csv file lieferant
try {
Scanner inputStream1 = new Scanner(file1);
while(inputStream1.hasNext()) {
String data1 = inputStream1.next();
String[] values1 = data1.split(",");
int LIDnummer = Integer.parseInt(values1[0]);
String citynames = values1[1];
System.out.println(LIDnummer);
String firmanames = values1[2];
//create the suppliers object with the required paramaters
//Suppliers suppliers = new
//Suppliers(LIDnummer,citynames,firmanames);
//lieferant.add(suppliers);
}
inputStream1.close();
}catch(FileNotFoundException d) {
d.printStackTrace();
}
the first error I get is
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 2
at Verbindung.main(Verbindung.java:61)
So I look at my array which is firmaname at line 61 and I think, well it's impossible that its out of range since in my CSV file there are three columns and at index 2 (which I know is the third column in the CSV file) is my list of company names. I know the array is not empty because when i wrote
`System.out.println(firmanames)`
it would print out three of the first company names. So in order to see if there is something else causing the problem I commented line 61 out and I ran the code again. I get the following error
`Exception in thread "main" java.lang.NumberFormatException: For input
string: "Ridge"
at java.lang.NumberFormatException.forInputString(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at Verbindung.main(Verbindung.java:58)`
I google these errors and you know it was saying im trying to parse something into an Integer which cannot be an integer, but the only thing that I am trying to parse into an Integer is the code
int LIDnummer = Integer.parseInt(values1[0]);
Which indeed is a column containing only Integers.
My second column is also indeed just a column of city names in the USA. The only thing with that column is that there are spaces in some town names like Middle brook but I don't think that would cause problems for a String type. Also in my company columns there are names like AT&T but i would think that the & symbol would also not cause problems for a string. I don't know where I am going wrong here.
I cant include the csv file but here is a pic of a part of it. The length of each column is a 1000.
A pic of the csv file
Scanner by default splits its input by whitespace (docs). Whitespace means spaces, tabs and newlines.
So your code will, I think, split the whole input file at every space and every newline, which is not what you want.
So, the first three elements your code will read are
5416499,Prairie
Ridge,NIKE
1765368,Edison,Cartier
I suggest using method readLine of BufferedReader then calling split on that.
The alternative is to explicitly tell Scanner how you want it to split the input
Scanner inputStream1 = new Scanner(file1).useDelimiter("\n");
but I think this is not the best use of Scanner when a simpler class (BufferedReader) will do.
First of all, I would highly suggest you try and use an existing CSV parser, for example this one.
But if you really want to use your own, you are going to need to do some simple debugging. I don't know how large your file is, but the symptoms you are describing lead me to believe that somewhere in the csv there may be a missing comma or an accidental escape character. You need to find out what line it is. So run this code and check its output before it crashes:
int line = 1;
try {
Scanner inputStream1 = new Scanner(file1);
while(inputStream1.hasNext()) {
String data1 = inputStream1.next();
String[] values1 = data1.split(",");
int LIDnummer = Integer.parseInt(values1[0]);
String citynames = values1[1];
System.out.println(LIDnummer);
String firmanames = values1[2];
line++;
}
} catch (ArrayIndexOutOfBoundsException e){
System.err.println("The issue in the csv is at line:" + line);
}
Once you find what line it is, the answer should be obvious. If not, post a picture of that line and we'll see...

Best way to populate a user defined object using the values of string array

I am reading two different csv files and populating data into two different objects. I am splitting each line of csv file based on regex(regex is different for two csv files) and populating the object using each data of that array which is obtained by splitting each line using regex as shown below:
public static <T> List<T> readCsv(String filePath, String type) {
List<T> list = new ArrayList<T>();
try {
File file = new File(filePath);
FileInputStream fileInputStream = new FileInputStream(file);
InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader)
list = bufferedReader.lines().skip(1).map(line -> {
T obj = null;
String[] data = null;
if (type.equalsIgnoreCase("Student")) {
data = line.split(",");
ABC abc = new ABC();
abc.setName(data[0]);
abc.setRollNo(data[1]);
abc.setMobileNo(data[2]);
obj = (T)abc;
} else if (type.equalsIgnoreCase("Employee")) {
data = line.split("\\|");
XYZ xyz = new XYZ();s
xyz.setName(Integer.parseInt(data[0]));
xyz.setCity(data[1]);
xyz.setEmployer(data[2]);
xyz.setDesignation(data[3]);
obj = (T)xyz;
}
return obj;
}).collect(Collectors.toList());} catch(Exception e) {
}}
csv files are as below:
i. csv file to populate ABC object:
Name,rollNo,mobileNo
Test1,1000,8888888888
Test2,1001,9999999990
ii. csv file to populate XYZ object
Name|City|Employer|Designation
Test1|City1|Emp1|SSE
Test2|City2|Emp2|
The issue is there can be a missing data for any of the above columns in the csv file as shown in the second csv file. In that case, I will get ArrayIndexOutOfBounds exception.
Can anyone let me know what is the best way to populate the object using the data of the string array?
Thanks in advance.
In addition to the other mistakes you made and that were pointed out to you in the comments your actual problem is caused by line.split("\\|") calling line.split("\\|", 0) which discards the trailing empty String. You need to call it with line.split("\\|", -1) instead and it will work.
The problem appears to be that one or more of the last values on any given CSV line may be empty. In that case, you run into the fact that String.split(String) suppresses trailing empty strings.
Supposing that you can rely on all the fields in fact being present, even if empty, you can simply use the two-arg form of split():
data = line.split(",", -1);
You can find details in that method's API docs.
If you cannot be confident that the fields will be present at all, then you can force them to be by adding delimiters to the end of the input string:
data = (line + ",,").split(",", -1);
Since you only use the first values few values, any extra trailing values introduced by the extra delimiters would be ignored.

Need help creating a program to read in entries and replace existing entry if there is one for that date

I am very new to coding and learning java, I can picture what the program needs to do however implementing to code has proven tough for me. I am trying to create a constructor. The constructor needs to do the following-
Constructor: When reading in and storing the individual quiz data, you will need to watch out for repeated quizzes. If a quiz is read in with a date that already has an entry stored, you will need to replace the earlier entry with the new one. I have been provided a java doc for this, however I will need to create the code. I have attached an image of the javadoc as well as the code that I currently have.
Javadoc for Constructor
public QuizList(String filename)
{
this.quizzesList = 0;
this.quizList = new ArrayList<Quiz>();
try {
Scanner infile = new Scanner(new File(filename));
while (infile.hasNextLine()){
String quizDate = infile.next();
String pointsEarned = infile.next();
String possiblePoints = infile.nextLine().trim();
Quiz quiz = new Quiz(quizDate, points, possible);
this.quizzes.add(quiz);
}
infile.close();
}
catch (java.io.FileNotFoundException e) {
System.out.println("No such file: " + filename);
}
File has lastModified method: https://docs.oracle.com/javase/8/docs/api/java/io/File.html.
I recommend you to iterate the files on the directory and check their last modified date.

Why does Scanner read every other line of CSV file? Java

I am reading in a CSV file and putting each delimited element into a two-dimensional array. The code looks like this:
public DataProcess(String filename, String[][] contents, int n) {//n is 6 for contents, 5 for fiveMinContents
Scanner fileReader = null;
try {
fileReader = new Scanner(new File(filename));
} catch (FileNotFoundException ex) {
System.out.println(ex + " FILE NOT FOUND ");
}
fileReader.useDelimiter(",");
int rowIndex = 0;
while (fileReader.hasNext()) {
for (int j = 0; j < n; j++) {
contents[rowIndex][j] = fileReader.next();
System.out.println("At (" + rowIndex +", "+j+"): " +
contents[rowIndex][j]);
}
rowIndex++;
fileReader.nextLine();
}
}
I am not sure why it reads every other line of this particular CSV file because this is file 2/2 that is being read in this manner. The first one reads fine, but now this one skips every other line. Why would it work for one but not the other? I am running this on Eclipse's latest update.
I also checked out this answer and it did not help.
Because the last line of your loop reads a line and discards it. You need something like,
while (fileReader.hasNextLine()) {
String line = fileReader.nextLine();
contents[rowIndex] = fileReader.split(",\\s*");
System.out.println("At (" + rowIndex + "): "
+ Arrays.toString(contents[rowIndex]));
rowIndex++;
}
You could also print the multi-dimensional array with one call like
System.out.println(Arrays.deepToString(contents));
While the approach may work for you, it's not optimal. There are premade CSV readers for Java. One example is commons-csv:
Reader in = new FileReader("path/to/file.csv");
Iterable<CSVRecord> records = CSVFormat.EXCEL.parse(in);
for (CSVRecord record : records) {
String date = record.get(1);
String time = record.get(2);
// and so on, so forth
}
There are a small number of dependencies that have to be on your classpath. Hope that helps.
I found the issue to this problem.
First, I recommend using the external library that was suggested.
The issue was that since this second file was reading the entire row, whereas the first CSV file was reading what I wanted it to, but there was a column at the end of the file that I was ignoring. There must be a way that a CSV file is structured where the end of a row has a different delimiter or something along those lines--not sure. To fix this issue, I just added an extra column to the second file and I am not reading it in; it is just there.
In short, use an external CSV-reader library. If you don't want to do that, then just add a column directly after the last column in the file and do not read it.

JAVA: ArrayIndexOutOFBoundException while reading imported txt

I'm a beginner, I have got a txt file that user will imported into java, I'm going to read txt file line be line then set variable base on each line and add them to the current record
public void importTXT() {
JFileChooser fc = new JFileChooser();
fc.setAcceptAllFileFilterUsed(false);
fc.setMultiSelectionEnabled(false);
FileNameExtensionFilter filter = new FileNameExtensionFilter(
"TEXT FILES", "txt", "text");
fc.setFileFilter(filter);
int returnVal = fc.showOpenDialog(CollectionFrame.this);
String[] numstrs = null;
if (returnVal == JFileChooser.APPROVE_OPTION) {
File importedFile = fc.getSelectedFile();
try {
Scanner sc = new Scanner(importedFile);
while (sc.hasNextLine()) {
numstrs = sc.nextLine().split("\\s+"); // split by white
// space
}
} catch (IOException e) {
}
// add new collection
Collection newCollection = new Collection(numstrs[0]);
allRecord.addCollection(newCollection);
// add art consignment information
String consignmentName = numstrs[3];
String description = numstrs[4];
I received a ArrayIndexOutOfBoundsException at the second last line
String consignmentName = numstrs[3];
The content of the text file is like:
Richman’s Estate Collection
5
ART
Water Lilies
A superb piece in great condition
Can someone tell me what's wrong?
EDIT:
you are currently reading all lines and replacing each time the value of numstrs
so when you leave the loop, you just got the value of the last line in it.
i think you want to save ALL lines - see below.
END EDIT
you should use an arraylist.
like this:
ArrayList<String[]> numstrsList = new ArrayList<String[]>();
if (returnVal == JFileChooser.APPROVE_OPTION) {
File importedFile = fc.getSelectedFile();
try {
Scanner sc = new Scanner(importedFile);
while (sc.hasNextLine()) {
numstrsList.add(sc.nextLine().split("\\s+")); // split by white
// space
}
} catch (IOException e) {
}
}
you can catch the values of your arraylist with:
for(int i=0:i<numstrsList.size();i++){
String[] oneLineStrArray = numstrsList.get(index)
//do something
}
you should post the text data, otherwise we cant help you about the OutOfBounds error.
Also, i am wondering how you can instantiate a Collection.
As previous comments already has suggested, the file obviously does not contain the information in the form you expect.
I suggest that you add som error handling to it after the scanner read.
if (numstrs.length < 5){
///TODO: add some handling here, exception or error dialog
}
Here, first go through ArrayIndexOutOfBoundsException
Check numstrs length before you try to access index value(s). You can do
String consignmentName = null, description = null;
if (numstrs.length >= 4) {
consignmentName = numstrs[3];
}
if (numstrs.length >= 5) {
description = numstrs[4];
}
Also, as pointed out by one of the comment - numstrs will always have the values returned by the last line.

Categories