Reading from csv adds whitespace that can't be removed Java - java

I am reading from a csv file of people, starting with their id, name, and date they joined the application. When reading the first row, the first index adds a whitespace to the string. I am unable to remove this whitespace, as I want to parse it to an integer.
File nameOfFile = fileName;
BufferedReader br = null;
String line = "";
String cvsSplitBy = ",";
try {
br = new BufferedReader(new FileReader(nameOfFile));
while ((line = br.readLine()) != null) {
String[] row = line.split(cvsSplitBy);
temp = row[0].trim();
temp.replaceAll("^\\s", "");
// temp.replaceAll(" ", "");
// String.format("%03d", temp);
System.out.println(temp.length() + " " + temp + " " + temp.charAt(0));
age = Integer.parseInt(temp);
name = row[1];
dateJoined = row[2];
}
} catch (FileNotFoundException | ArrayIndexOutOfBoundsException exception) {
System.out.println("File is not found, please try again.");
System.out.println(exception);
}
if (br != null) {
br.close(); //close buffered reader
}
My csv file:
4 John 10/10/2010
5 Charles 24/08/2010
6 Andrew 09/01/2011
The System.out.println(temp.length() + " " + temp + " " + temp.charAt(0)); prints this:
2 4
1 5 5
1 6 6
where this System.out.println(temp.length() + " " + temp + " " + temp.charAt(1)); prints out:
2 4 4

Don't reinvent the wheel. I would use the Univocity parser and then map.
More info at: https://www.univocity.com/pages/parsers-documentation
Something along this (did not test it);
CsvParserSettings settings = new CsvParserSettings();
CsvParser parser = new CsvParser(settings);
List<String[]> allRows = parser.parseAll(new FileReader(yourfile));
List<Person> persons = allRows.stream().map(p->new Person(p[0],p[1],p[2])).collect(Collectors.toList())
In the Person bean I would make specific setMethods, such as:
public void setAge(String age2parse){
try{
this.age = Integer.parse(age2parse.replaceAll("[^\\d.]",""))
}catch(Exception e){
}
}
public void setName(String name2parse){
this.name = name; // You could divide name here, if wanted.
}
public void setDate(String date2parse){
this.date = date2parse // I would parse it and store it as Date object.
}
Finnaly, a constructor in the bean;
public Person(String a, String n, String d){
setAge(a);
setName(n);
setDate(d);
}
To print:
persons.stream().forEachOrdered(p->System.out.println(p.getAge()+" "+p.getName()+" "+p.getDate()))
Note: There is even way to use BeanRowProcessors, which seem to fit well when you have more fields in the bean, so please, check the documentation on Univocity.

Related

I have a problem in file handling in java

any help will be appreciated.
print some details about fines on it, but the code is not giving me an output.
my code is :
class BookLib{
String userName ;
String bookName;
int noOfDays;
int fine;
#Override
public String toString() {
return "BookLib{" +
"userName='" + userName + '\'' +
", bookName='" + bookName + '\'' +
", noOfDays=" + noOfDays + '}';
}
}
class Library{
List<BookLib> books = new ArrayList<>();
void readDetails() throws IOException{
FileReader fr = new FileReader("fineDetails.txt");
BufferedReader br = new BufferedReader(fr);
String thisLine;
List<String> lines = new ArrayList<>();
while ((thisLine = br.readLine()) != null) {
lines.add(thisLine);
}
for(String readLine: lines){
StringTokenizer stringTokenizer = new StringTokenizer(readLine, ",");
BookLib tempBook = new BookLib();
tempBook.userName = stringTokenizer.nextToken().trim();
tempBook.bookName = stringTokenizer.nextToken().trim();
tempBook.noOfDays = Integer.parseInt(stringTokenizer.nextToken().trim());
System.out.println("BookLib = " + tempBook);
books.add(tempBook)
}
br.close();
fr.close();
}
I Hope, Above code, is helping you for handling NumberFormatException and future ArrayIndexOutOfBoundException handling. you may also use try-catch {} for handling these errors.
The problem is that you can't parse the String "25 " to an Integer because of the whitespace.
You can remove the whitespace using the trim method of String like this:
//...
book[i].userName = stringTokenizer.nextToken();
book[i].bookName = stringTokenizer.nextToken();
book[i].noOfDays = Integer.parseInt(stringTokenizer.nextToken().trim()); // trim here
//...
I think there is another problem that didn't cause any errors yet, because the NumberFormatException occured earlier: You do close the readers br and fr in the for loop, but they will still be used there. You should move the lines br.close() and fr.close() down to the end of the method.

Java: print csv on different columns?

I want to print the query table results on a CSV file.
I tried using this code:
PrintWriter csvWriter = new PrintWriter(new File(path + "SqlClient_" + date + ".csv")) ;
ResultSetMetaData meta = rs.getMetaData() ;
int numberOfColumns = meta.getColumnCount() ;
String dataHeaders = "\"" + meta.getColumnName(1) + "\"" ;
for (int i = 2 ; i < numberOfColumns + 1 ; i ++ ) {
dataHeaders += ",\"" + meta.getColumnName(i) + "\"" ;
}
csvWriter.println(dataHeaders) ;
while (rs.next()) {
String row = "\"" + rs.getString(1) + "\"" ;
for (int i = 2 ; i < numberOfColumns + 1 ; i ++ ) {
row += ",\"" + rs.getString(i) + "\"" ;
}
csvWriter.println(row) ;
}
csvWriter.close();
This is what i obtain:
title1","title2","title3"
"date1","date2","date3"
....
This is write inside a single column, instead i want to write on different column, something like:
title1 | title2 | title3
data1| data2 | data3 |
There is a special command to split the string into different columns?
why don't you use a StringBuilder for this. Lets say you obtain a result set with a list of type YourClass from database call. Call the following utility and pass writer to it.
Pseudo code:
public void writeToCSV(FileWriter writer){
StringBuilder sb=new StringBuilder();
for (YourClass data: yourresultSet){
sb.append("\"");
sb.append(data.getColumn1);
sb.append"\"";
sb.append(",\"")
sb.append(data.getColumn2);
sb.append("\"");
sb.append('\n'); //new line after the column
writer.write(sb.toString());
sb.delete(0,sb.length());
}
}
And to test your result
public class ReadCSV{
public static void main(String[] args) {
String csvFile = "your.csv";
BufferedReader br = null;
String line = "";
String cvsSplitBy = ",";
try {
br = new BufferedReader(new FileReader(csvFile));
while ((line = br.readLine()) != null) {
// use comma as separator
String[] title= line.split(cvsSplitBy);
System.out.println("Columns [Column1= " + title[0] + " , Column2=" + title[1] + "]");
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
The CSV files use a delimiter in order to separate the columns, so I'm guessing that your delimiter will be , (comma).
What you should do is print the value of the headers separated by comma and then append a new line separator (\n) in order to create a new column. And the same with the row values.
See this example for further information about that.

Java - NumberFormatException at linear search

I am having this issue with the NumberFormatException in my program. Basically, I am asked to read a .csv file separated by ; and it looks like this:
// Column Explanation (not in .csv file)
id; Summary; Number; Employee1; Employee2; ....... Employee7;
"1";"Sony";"1600";"Markos";"Nikos";"Antonis";"Nikolas";"Vaggelis";"Markos";"Thanasis";
"2";"HP";"1000";"Marios";"Dimitra";"Nikolia";"Spiros";"Thomas";"Kostas";"Manolis";
"3";"Dell";"1100";"Antonis";"Aggelos";"Baggelis";"Nikos";"Kuriakos";"Panagiotis";"Rafail";
"4";"Acer";"2000";"Marina";"Aggelos";"Spiros";"Marinos";"Xristos";"Antreas";"Basilis";
What I have already done is create a String 2-d array or the .csv file called temp_arr and I am asked to write a method that will run a linear search by id and return that company. So here is the thing.
At first, I thought I should convert the input key from int -> String since my temp_arr is a String and compares the strings (which at that time they would be int but read as Strings) using temp_arr[value][value2].equals(string_key). But I had a NullPointerException.
Then I thought I should better convert my Id's from the temp_arr from String -> Int and then compare with the integer key using == operand. This action returned me a NumberFormatException.
The process is this:
System.out.println("Enter id :");
Scanner input = new Scanner(System.in);
int item = input.nextInt(); // read the key which is an Integer
int id_int; // temp_arr is String and item is int, must convert ids from String -> int
for (int i = 0; i < temp_arr.length; i++)
{
id_int = Integer.parseInt(temp_arr[i][0]); // Convert from String to int
if (id_int == item) // If the Array's Id's are == item
{
System.out.println(item+" is present at location " + (i+1) );
break;
}
if (i == temp_arr.length)
System.out.println(item + " does not exist");
}
My error appears at line 7 and I do not know why.
Read File process:
String csvFile = "sam.csv"; // .csv file to be placed in the project file!
BufferedReader br = null; // ini
String line = "",cvsSplitBy = ";"; // columns asked to be split by ";"
String[] arr = null;
String[][] temp_arr = new String[1000][10];
int temp = 0;
try
{
br = new BufferedReader(new FileReader(csvFile)); //start reading the file
while ((line = br.readLine()) != null) // while the line has words
{
arr = line.split(cvsSplitBy); // creating the array
System.out.println(arr[0] + "\t" + arr[1] + "\t" + arr[2] + "\t" + arr[3] + "\t" + arr[4] + "\t" + arr[5] + "\t" + arr[6] + "\t" + arr[7] + "\t" + arr[8] + "\t" + arr[9] );
for (int i = 0; i<=9; i++)
{
temp_arr[temp][i] = arr[i]; // temp_arr represents (is a copy of) the .csv file
}
temp++;
}
} catch (FileNotFoundException e)
{
e.printStackTrace();
} catch (IOException e)
{
e.printStackTrace();
} finally
{
if (br != null)
{
try
{
br.close();
} catch (IOException e)
{
e.printStackTrace();
}
}
}
System.out.println("Done!\n");
Output (Image) :
Line 106 which is causing the issue is :
id_int = Integer.parseInt(temp_arr[i][0]); // Convert from String to int
Your issue is that your Integer.parseInt() is trying to parse a "2" WITH QUOTATION MARKS. That's the problem.
A quick solution would be to replace this line:
temp_arr[temp][i] = arr[i];
To this:
temp_arr[temp][i] = arr[i].replaceAll("\"", "");
Anyway, I'd like to suggest using a different data structure for your case, because I've done something like this before for a client. Have you ever heard of HashMaps? You can do something like a HashMap with an int key and String[] values to store your data in, and the key can be your id_int. Maybe you can try this implementation next time. It's a lot more elegant.
Hope I was able to help!
Cheers,
Justin
Would help if you also posted some of your data file and how you are reading it in.
But, my guess from what is presented is if you add System.out.println(temp_arr[i][0]) prior to the 7th line or run this code through a debugger you will see that temp_arr[i][0] is not an integer value as that is what the error is telling you.

Read CSV file column by column

I want to read specific columns from a multi column csv file and print those columns in other csv file using Java. Any help please? Following is my code to print each token line by line..But I am looking to print only few columns out of the multi column csv.
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.StringTokenizer;
public class ParseCSV {
public static void main(String[] args) {
try
{
//csv file containing data
String strFile = "C:\\Users\\rsaluja\\CMS_Evaluation\\Drupal_12_08_27.csv";
//create BufferedReader to read csv file
BufferedReader br = new BufferedReader( new FileReader(strFile));
String strLine = "";
StringTokenizer st = null;
int lineNumber = 0, tokenNumber = 0;
//read comma separated file line by line
while( (strLine = br.readLine()) != null)
{
lineNumber++;
//break comma separated line using ","
st = new StringTokenizer(strLine, ",");
while(st.hasMoreTokens())
{
//display csv values
tokenNumber++;
System.out.println("Line # " + lineNumber +
", Token # " + tokenNumber
+ ", Token : "+ st.nextToken());
System.out.println(cols[4]);
You should use the excellent OpenCSV for reading and writing CSV files. To adapt your example to use the library it would look like this:
public class ParseCSV {
public static void main(String[] args) {
try {
//csv file containing data
String strFile = "C:/Users/rsaluja/CMS_Evaluation/Drupal_12_08_27.csv";
CSVReader reader = new CSVReader(new FileReader(strFile));
String [] nextLine;
int lineNumber = 0;
while ((nextLine = reader.readNext()) != null) {
lineNumber++;
System.out.println("Line # " + lineNumber);
// nextLine[] is an array of values from the line
System.out.println(nextLine[4] + "etc...");
}
}
}
}
Reading a CSV file in very simple and common in Java. You actually don't require to load any extra third party library to do this for you. CSV (comma separated value) file is just a normal plain-text file, store data in column by column, and split it by a separator (e.g comma ",").
In order to read specific columns from the CSV file, there are several ways. Simplest of all is as below:
Code to read CSV without any 3rd party library
BufferedReader br = new BufferedReader(new FileReader(csvFile));
while ((line = br.readLine()) != null) {
// use comma as separator
String[] cols = line.split(cvsSplitBy);
System.out.println("Coulmn 4= " + cols[4] + " , Column 5=" + cols[5]);
}
If you notice, nothing special is performed here. It is just reading a text file, and spitting it by a separator – ",".
Consider an extract from legacy country CSV data at GeoLite Free Downloadable Databases
"1.0.0.0","1.0.0.255","16777216","16777471","AU","Australia"
"1.0.1.0","1.0.3.255","16777472","16778239","CN","China"
"1.0.4.0","1.0.7.255","16778240","16779263","AU","Australia"
"1.0.8.0","1.0.15.255","16779264","16781311","CN","China"
"1.0.16.0","1.0.31.255","16781312","16785407","JP","Japan"
"1.0.32.0","1.0.63.255","16785408","16793599","CN","China"
"1.0.64.0","1.0.127.255","16793600","16809983","JP","Japan"
"1.0.128.0","1.0.255.255","16809984","16842751","TH","Thailand"
Above code will output as below:
Column 4= "AU" , Column 5="Australia"
Column 4= "CN" , Column 5="China"
Column 4= "AU" , Column 5="Australia"
Column 4= "CN" , Column 5="China"
Column 4= "JP" , Column 5="Japan"
Column 4= "CN" , Column 5="China"
Column 4= "JP" , Column 5="Japan"
Column 4= "TH" , Column 5="Thailand"
You can, in fact, put the columns in a Map and then get the values simply by using the key.
Shishir
I am sorry, but none of these answers provide an optimal solution. If you use a library such as OpenCSV you will have to write a lot of code to handle special cases to extract information from specific columns.
For example, if you have rows with less columns than what you're after, you'll have to write a lot of code to handle it. Using the OpenCSV example:
CSVReader reader = new CSVReader(new FileReader(strFile));
String [] nextLine;
while ((nextLine = reader.readNext()) != null) {
//let's say you are interested in getting columns 20, 30, and 40
String[] outputRow = new String[3];
if(parsedRow.length < 40){
outputRow[2] = null;
} else {
outputRow[2] = parsedRow[40]
}
if(parsedRow.length < 30){
outputRow[1] = null;
} else {
outputRow[1] = parsedRow[30]
}
if(parsedRow.length < 20){
outputRow[0] = null;
} else {
outputRow[0] = parsedRow[20]
}
}
This is a lot of code for a simple requirement. It gets worse if you are trying to get values of columns by name. You should use a more modern parser such as the one provided by uniVocity-parsers.
To reliably and easily get the columns you want, simply write:
CsvParserSettings settings = new CsvParserSettings();
parserSettings.selectIndexes(20, 30, 40);
CsvParser parser = new CsvParser(settings);
List<String[]> allRows = parser.parseAll(new FileReader(yourFile));
Disclosure: I am the author of this library. It's open-source and free (Apache V2.0 license).
To read some specific column
I did something like this:
dpkcs.csv content:
FN,LN,EMAIL,CC
Name1,Lname1,email1#gmail.com,CC1
Nmae2,Lname2,email2r#gmail.com,CC2
The function to read it:
private void getEMailRecepientList() {
List<EmailRecepientData> emailList = null;// Blank list of POJO class
Scanner scanner = null;
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader("dpkcs.csv"));
Map<String, Integer> mailHeader = new HashMap<String, Integer>();
// read file line by line
String line = null;
int index = 0;
line = reader.readLine();
// Get header from 1st row of csv
if (line != null) {
StringTokenizer str = new StringTokenizer(line, ",");
int headerCount = str.countTokens();
for (int i = 0; i < headerCount; i++) {
String headerKey = str.nextToken();
mailHeader.put(headerKey.toUpperCase(), new Integer(i));
}
}
emailList = new ArrayList<EmailRecepientData>();
while ((line = reader.readLine()) != null) {
// POJO class for getter and setters
EmailRecepientData email = new EmailRecepientData();
scanner = new Scanner(line);
scanner.useDelimiter(",");
//Use Specific key to get value what u want
while (scanner.hasNext()) {
String data = scanner.next();
if (index == mailHeader.get("EMAIL"))
email.setEmailId(data);
else if (index == mailHeader.get("FN"))
email.setFirstName(data);
else if (index == mailHeader.get("LN"))
email.setLastName(data);
else if (index == mailHeader.get("CC"))
email.setCouponCode(data);
index++;
}
index = 0;
emailList.add(email);
}
reader.close();
} catch (Exception e) {
StringWriter stack = new StringWriter();
e.printStackTrace(new PrintWriter(stack));
} finally {
scanner.close();
}
System.out.println("list--" + emailList);
}
The POJO Class:
public class EmailRecepientData {
private String emailId;
private String firstName;
private String lastName;
private String couponCode;
public String getEmailId() {
return emailId;
}
public void setEmailId(String emailId) {
this.emailId = emailId;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getCouponCode() {
return couponCode;
}
public void setCouponCode(String couponCode) {
this.couponCode = couponCode;
}
#Override
public String toString() {
return "Email Id=" + emailId + ", First Name=" + firstName + " ,"
+ " Last Name=" + lastName + ", Coupon Code=" + couponCode + "";
}
}
I sugges to use the Apache Commons CSV https://commons.apache.org/proper/commons-csv/
Here is one example:
Path currentRelativePath = Paths.get("");
String currentPath = currentRelativePath.toAbsolutePath().toString();
String csvFile = currentPath + "/pathInYourProject/test.csv";
Reader in;
Iterable<CSVRecord> records = null;
try
{
in = new FileReader(csvFile);
records = CSVFormat.EXCEL.withHeader().parse(in); // header will be ignored
}
catch (IOException e)
{
e.printStackTrace();
}
for (CSVRecord record : records) {
String line = "";
for ( int i=0; i < record.size(); i++)
{
if ( line == "" )
line = line.concat(record.get(i));
else
line = line.concat("," + record.get(i));
}
System.out.println("read line: " + line);
}
It automaticly recognize , and " but not ; (maybe it can be configured...).
My example file is:
col1,col2,col3
val1,"val2",val3
"val4",val5
val6;val7;"val8"
And output is:
read line: val1,val2,val3
read line: val4,val5
read line: val6;val7;"val8"
Last line is considered like one value.
We can use the core java stuff alone to read the CVS file column by column. Here is the sample code I have wrote for my requirement. I believe that it will help for some one.
BufferedReader br = new BufferedReader(new FileReader(csvFile));
String line = EMPTY;
int lineNumber = 0;
int productURIIndex = -1;
int marketURIIndex = -1;
int ingredientURIIndex = -1;
int companyURIIndex = -1;
// read comma separated file line by line
while ((line = br.readLine()) != null) {
lineNumber++;
// use comma as line separator
String[] splitStr = line.split(COMMA);
int splittedStringLen = splitStr.length;
// get the product title and uri column index by reading csv header
// line
if (lineNumber == 1) {
for (int i = 0; i < splittedStringLen; i++) {
if (splitStr[i].equals(PRODUCTURI_TITLE)) {
productURIIndex = i;
System.out.println("product_uri index:" + productURIIndex);
}
if (splitStr[i].equals(MARKETURI_TITLE)) {
marketURIIndex = i;
System.out.println("marketURIIndex:" + marketURIIndex);
}
if (splitStr[i].equals(COMPANYURI_TITLE)) {
companyURIIndex = i;
System.out.println("companyURIIndex:" + companyURIIndex);
}
if (splitStr[i].equals(INGREDIENTURI_TITLE)) {
ingredientURIIndex = i;
System.out.println("ingredientURIIndex:" + ingredientURIIndex);
}
}
} else {
if (splitStr != null) {
String conditionString = EMPTY;
// avoiding arrayindexoutboundexception when the line
// contains only ,,,,,,,,,,,,,
for (String s : splitStr) {
conditionString = s;
}
if (!conditionString.equals(EMPTY)) {
if (productURIIndex != -1) {
productCVSUriList.add(splitStr[productURIIndex]);
}
if (companyURIIndex != -1) {
companyCVSUriList.add(splitStr[companyURIIndex]);
}
if (marketURIIndex != -1) {
marketCVSUriList.add(splitStr[marketURIIndex]);
}
if (ingredientURIIndex != -1) {
ingredientCVSUriList.add(splitStr[ingredientURIIndex]);
}
}
}
}
Finds all files in folder and write that data to ArrayList row.
Initialize
ArrayList<ArrayList<String>> row=new ArrayList<ArrayList<String>>();
BufferedReader br=null;
For Accessing row
for(ArrayList<String> data:row){
data.get(col no);
}
or row.get(0).get(0) // getting first row first col
Functions that reads all files from folders and concatenate them row.
static void readData(){
String path="C:\\Users\\Galaxy Computers\\Desktop\\Java project\\Nasdaq\\";
File files=new File(path);
String[] list=files.list();
try {
String sCurrentLine;
char check;
for(String filename:list){
br = new BufferedReader(new FileReader(path+filename));
br.readLine();//If file contains uneccessary first line.
while ((sCurrentLine = br.readLine()) != null) {
row.add(splitLine(sCurrentLine));
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (br != null)br.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
static ArrayList<String> splitLine(String line){
String[] ar=line.split(",");
ArrayList<String> d=new ArrayList<String>();
for(String data:ar){
d.add(data);
}
return d;
}
Well, how about this !!
This code calculates both row and column count in a csv file. Try this out !!
static int[] getRowsColsNo() {
Scanner scanIn = null;
int rows = 0;
int cols = 0;
String InputLine = "";
try {
scanIn = new Scanner(new BufferedReader(
new FileReader("filename.csv")));
scanIn.useDelimiter(",");
while (scanIn.hasNextLine()) {
InputLine = scanIn.nextLine();
String[] InArray = InputLine.split(",");
rows++;
cols = InArray.length;
}
} catch (Exception e) {
System.out.println(e);
}
return new int[] { rows, cols };
}

I need help understanding a error message

Here is an error message that keeps coming up as I try to disply results on my program.
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
at AddressBookIO.getEntriesString(AddressBookIO.java:38)
at AddressBookEntryApp.main(AddressBookEntryApp.java:42)
I am almost certain my code is correct. My program does everything it is suppose to do except display my results. The ""main" java.lang.ArrayIndexOutOfBoundsException: 0" is the part that confuses me.
Heres the code for AddressBookIO.java, and AddressBookEntryApp
import java.io.*;
public class AddressBookIO
{
private static File addressBookFile = new File("address_book.txt");
private static final String FIELD_SEP = "\t";
private static final int COL_WIDTH = 20;
// use this method to return a string that displays
// all entries in the address_book.txt file
public static String getEntriesString()
{
BufferedReader in = null;
try
{
checkFile();
in = new BufferedReader(
new FileReader(addressBookFile));
// define the string and set a header
String entriesString = "";
entriesString = padWithSpaces("Name", COL_WIDTH)
+ padWithSpaces("Email", COL_WIDTH)
+ padWithSpaces("Phone", COL_WIDTH)
+ "\n";
entriesString += padWithSpaces("------------------", COL_WIDTH)
+ padWithSpaces("------------------", COL_WIDTH)
+ padWithSpaces("------------------", COL_WIDTH)
+ "\n";
// append each line in the file to the entriesString
String line = in.readLine();
while(line != null)
{
String[] columns = line.split(FIELD_SEP);
String name = columns[0];
String emailAddress = columns[1];
String phoneNumber = columns[2];
entriesString +=
padWithSpaces(name, COL_WIDTH) +
padWithSpaces(emailAddress, COL_WIDTH) +
padWithSpaces(phoneNumber, COL_WIDTH) +
"\n";
line = in.readLine();
}
return entriesString;
}
catch(IOException ioe)
{
ioe.printStackTrace();
return null;
}
finally
{
close(in);
}
}
// use this method to append an address book entry
// to the end of the address_book.txt file
public static boolean saveEntry(AddressBookEntry entry)
{
PrintWriter out = null;
try
{
checkFile();
// open output stream for appending
out = new PrintWriter(
new BufferedWriter(
new FileWriter(addressBookFile, true)));
// write all entry to the end of the file
out.print(entry.getName() + FIELD_SEP);
out.print(entry.getEmailAddress() + FIELD_SEP);
out.print(entry.getPhoneNumber() + FIELD_SEP);
out.println();
}
catch(IOException ioe)
{
ioe.printStackTrace();
return false;
}
finally
{
close(out);
}
return true;
}
// a private method that creates a blank file if the file doesn't already exist
private static void checkFile() throws IOException
{
// if the file doesn't exist, create it
if (!addressBookFile.exists())
addressBookFile.createNewFile();
}
// a private method that closes the I/O stream
private static void close(Closeable stream)
{
try
{
if (stream != null)
stream.close();
}
catch(IOException ioe)
{
ioe.printStackTrace();
}
}
// a private method that is used to set the width of a column
private static String padWithSpaces(String s, int length)
{
if (s.length() < length)
{
StringBuilder sb = new StringBuilder(s);
while(sb.length() < length)
{
sb.append(" ");
}
return sb.toString();
}
else
{
return s.substring(0, length);
}
}
}
And
import java.util.Scanner;
public class AddressBookEntryApp
{
public static void main(String args[])
{
// display a welcome message
System.out.println("Welcome to the Address Book application");
System.out.println();
Scanner sc = new Scanner(System.in);
int menuNumber = 0;
while (menuNumber != 3)
{
// display menu
System.out.println("1 - List entries");
System.out.println("2 - Add entry");
System.out.println("3 - Exit\n");
// get input from user
menuNumber = Validator.getIntWithinRange(sc, "Enter menu number: ", 0, 4);
System.out.println();
switch (menuNumber)
{
case 1:
{
String entriesString = AddressBookIO.getEntriesString();
System.out.println(entriesString);
break;
}
case 2:
{
// get data from user
String name = Validator.getRequiredString(sc, "Enter name: ");
String emailAddress = Validator.getRequiredString(sc, "Enter email address: ");
String phoneNumber = Validator.getRequiredString(sc, "Enter phone number: ");
// create AddressBookEntry object and fill with data
AddressBookEntry entry = new AddressBookEntry();
entry.setName(name);
entry.setEmailAddress(emailAddress);
entry.setPhoneNumber(phoneNumber);
AddressBookIO.saveEntry(entry);
System.out.println();
System.out.println("This entry has been saved.\n");
break;
}
case 3:
{
System.out.println("Goodbye.\n");
break;
}
}
}
}
}
The exception means that you are accessing an array's element beyond the size of the array. So, you need to provide the details of your code to be able to let you know the cause of the issue.
It indicates that an array has been accessed with an illegal index. The index is either negative or greater than or equal to the size of the array.
As per your error logs..code at line no:38 in AddressBookIO.java is throwing this exception.
Could be here..
String name = columns[0];
String emailAddress = columns[1];
String phoneNumber = columns[2];
if there is no element at either 0, 1 or 2..
The error message is pretty clear: The 1st element (index 0) of an array with no elements has been incorrectly accessed.
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: [index is] 0
For instance, this would throw that exception:
int bad = (new int[0])[0]; // no elements :(
While the following is okay:
int ok = (new int[1])[0]; // one element, can access it!
I suspect it is this:
String[] columns = line.split(FIELD_SEP); // empty array?
String name = columns[0]; // KABOOM!
In any case, check the code on the line reported in the exception.
at AddressBookIO.getEntriesString(AddressBookIO.java:38)
A blank line in 'address_book.txt' perhaps?
You are trying to access the first element of an empty array. It doesn't exist, so you get an exception from the run time.
The array that you are trying to access is the result of the split() method. This will only return an empty array if you pass a string of delimiters: "\t"
So, there must be some lines that contain only tabs with nothing between them.
Instead of using split(), you should consider applying regular expression to each line. This way, you can validate the format of the line and apply "capture groups" at the same time to easily extract values for each field, even if they are empty strings.
Pattern p = Pattern.compile("([^\t]*)\t([^\t]*)\t([^\t]*)");
...
Matcher m = p.matcher(line);
if (!m.matches()) {
/* The line is invalid; skip it or throw an exception. */
...
}
String name = m.group(1);
String emailAddress = m.group(2);
String phoneNumber = m.group(3);
ArrayIndexOutOfBoundsException is thrown when you try to access an Index, which is more than the size of the specified array.
Try to change this :
while(line != null)
{
String[] columns = line.split(FIELD_SEP);
String name = columns[0];
String emailAddress = columns[1];
String phoneNumber = columns[2];
entriesString += padWithSpaces(name, COL_WIDTH) +
padWithSpaces(emailAddress, COL_WIDTH) +
padWithSpaces(phoneNumber, COL_WIDTH) +
"\n";
line = in.readLine();
}
to this :
while(line != null)
{
String[] columns = line.split(FIELD_SEP);
if (columns.length > 2)
{
String name = columns[0];
String emailAddress = columns[1];
String phoneNumber = columns[2];
entriesString += padWithSpaces(name, COL_WIDTH) +
padWithSpaces(emailAddress, COL_WIDTH) +
padWithSpaces(phoneNumber, COL_WIDTH) +
"\n";
}
line = in.readLine();
}

Categories