I have a CSV file, format as follows:
City,Job,Salary
Delhi,Doctors,500
Delhi,Lawyers,400
Delhi,Plumbers,100
London,Doctors,800
London,Lawyers,700
London,Plumbers,
The first line contains the word "Salary" in the third spot. Put br.readLine()
before the loop and everything should be fine.
You have:
br = new BufferedReader(new FileReader(csv));
try {
while ((line = br.readLine()) != null) {
Change it to:
br = new BufferedReader(new FileReader(csv));
br.readLine()
try {
while ((line = br.readLine()) != null) {
First, use a CSV parser - I will use OpenCSV in this example. I have no affiliation with OpenCSV, it's just what I have in my POM at the moment.
First, create a class
:
public class Salary {
private String city;
private String job;
private long salary;
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getJob() {
return job;
}
public void setJob(String job) {
this.job = job;
}
public long getSalary() {
return salary;
}
public void setSalary(long salary) {
this.salary = salary;
}
}
Now your CSV has three columns, and the header of the CSV matches the property names of our bean, so we can simply use a HeaderColumnNameMappingStrategy
to determine which properties to set on the bean:
final HeaderColumnNameMappingStrategy<Salary> mappingStrategy = new HeaderColumnNameMappingStrategy<>();
mappingStrategy.setType(Salary.class);
Now we just need to parse the CSV file into a List
of our beans:
final CsvToBean<Salary> csvToBean = new CsvToBean<>();
try (final Reader reader = ...) {
final List<Salary> salaries = csvToBean.parse(mappingStrategy, reader);
}
Okay.
Now, how do you get an average salary from this mess? Just use a Java 8 Stream
on the result:
final LongSummaryStatistics statistics = salaries.stream()
.mapToLong(Salary::getSalary)
.summaryStatistics();
Now we can get all sorts of useful information:
final long min = statistics.getMin();
final double average = statistics.getAverage();
final long max = statistics.getMax();
br.readLine()
before the while-loop
will avoid header line problem, but if your data is not correct you will get same Exception
again, so, in order to make a safer method you can change this line:
int sal=Integer.parseInt(country[2]);
With a try-catch
block to iterate through entire file even if a value is not a valid number
int sal;
try {
sal=Integer.parseInt(country[2]);
} catch (NumberFormatException e) {
// if you want here you can show an error message
// to give feedback to the user there is not a valid number
}
Skip the first line of the CSV file. Do an additional
br.readLine()
before the while.
You might also want to add some format checks to be sure the file you are reading is in the correct format.