Here is my class to read a csv file and I was wondering if there is any improvements that I should do. I feel there are some performance improvements or in exception handling because I just took IO exceptions.
package com.mypackage.utils;
import com.opencsv.CSVParserBuilder;
import com.opencsv.CSVReader;
import com.opencsv.CSVReaderBuilder;
import com.opencsv.enums.CSVReaderNullFieldIndicator;
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.*;
public class FileReader {
private String path;
private CSVReader reader;
private List<String> linesList;
private Set<List<String>> splitLinesSet;
public FileReader(String path) {
this.path = path;
}
public boolean readFile() {
this.splitLinesSet = new HashSet<>();
try {
File file = Paths.get(path).toFile();
reader = new CSVReaderBuilder(new java.io.FileReader(file))
.withCSVParser(new CSVParserBuilder()
.withSeparator('|')
.withFieldAsNull(CSVReaderNullFieldIndicator.NEITHER).build())
.build();
read();
reader.close();
} catch (IOException e) {
System.err.println("Error in reading CSV: " + e.getMessage());
return false;
}
return true;
}
public Set<List<String>> getSplitLinesSet() {
return splitLinesSet;
}
private void read() throws IOException {
String[] lines;
while ((lines = reader.readNext()) != null) {
linesList = new ArrayList<>();
Collections.addAll(linesList, lines);
splitLinesSet.add(linesList);
}
}
}
2 Answers 2
I tend to advocate not passing things around which need to be closed, thus my advice is:
- inline the read method
- remove the reader field, and
- ... declare the same as a local variable
- perferably, declare that local reader variable in a try-with-resources block and throw out the explicit close()-call
Note that these changes are just about robustness and maintainability and will not affect performance or error handling.
Edit, after the comment asking for code edit. (Note: sorry, I am a newbie in the code review community, I hope this does not break any principle here.)
public class FileReader {
private String path;
private List<String> linesList;
private Set<List<String>> splitLinesSet;
public FileReader(String path) {
this.path = path;
}
public boolean readFile() {
this.splitLinesSet = new HashSet<>();
File file = Paths.get(path).toFile();
try (
CSVReader reader = new CSVReaderBuilder(new java.io.FileReader(file))
.withCSVParser(new CSVParserBuilder()
.withSeparator('|')
.withFieldAsNull(CSVReaderNullFieldIndicator.NEITHER).build())
.build();
) {
String[] lines;
while ((lines = reader.readNext()) != null) {
linesList = new ArrayList<>();
Collections.addAll(linesList, lines);
splitLinesSet.add(linesList);
}
} catch (IOException e) {
System.err.println("Error in reading CSV: " + e.getMessage());
return false;
}
return true;
}
public Set<List<String>> getSplitLinesSet() {
return splitLinesSet;
}
}
Note: this was just syntactic shuffling of lines in a text editor - I have not put this through an IDE or a compiler, but I think it shows the principles.
-
\$\begingroup\$ @PHA : See edit, and good luck :) \$\endgroup\$mtj– mtj2016年12月16日 12:24:47 +00:00Commented Dec 16, 2016 at 12:24
FileReader
should be avoided, because it relies on a default encoding. We should specify explicitly the encoding used.
CSVParser parser = new CSVParserBuilder().withSeparator('|').build();
try (BufferedReader br = Files.newBufferedReader(myPath,
StandardCharsets.UTF_8);
CSVReader reader = new CSVReaderBuilder(br).withCSVParser(parser)
.build()) {
...