Reputation: 11
I have to take a CSVReader IBM created and make changes that fit my requirements. I am new to java and not sure how to do any except for #1, my requirements are:
Ex. Input
Jordan, Michael, J, ", 23
Ex. Output
"Jordan, Michael, J, "", 23"
Background information: this program will be added into a shell script, the functionality is being added because the csv is corrupted if a single double quote is entered
Here is the code:
package Scripts;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;
public class CSVReader
{
private BufferedReader br;
private boolean hasNext = true;
private static char separator = ' ';
private static char quotechar = ' ';
public static final char DEFAULT_SEPARATOR = ',';
public static final char DEFAULT_QUOTE_CHARACTER = '"';
public static void main(final String[] args) throws IOException {
final String csvFile = args[0];
final ArrayList<String[]> allElements = new ArrayList<String[]>();
final CSVReader csvReader = new CSVReader(br, separator, quotechar, csvFile);
csvTransformer.readAll();
csvTransformer.close();
}
public CSVReader(final Reader reader) throws FileNotFoundException {
this(reader, DEFAULT_SEPARATOR);
}
public CSVReader(final Reader reader, final char separator) throws FileNotFoundException {
this(reader, separator, DEFAULT_QUOTE_CHARACTER, null);
}
public CSVReader(final Reader reader, final char separator, final char quotechar, final String csvFile) throws FileNotFoundException {
CSVTransformer.br = new BufferedReader(new FileReader(csvFile));
this.separator = separator;
this.quotechar = quotechar;
}
/**
* Reads the entire file into a List with each element being a String[] of tokens.
*
* return a List of String[], with each String[] representing a line of the file.
*/
public List readAll() throws IOException
{
List allElements = new ArrayList();
while (hasNext)
{
String[] nextLineAsTokens = readNext();
if (nextLineAsTokens != null)
allElements.add(nextLineAsTokens);
}
return allElements;
}
/**
* Reads the next line from the buffer and converts to a string array.
*
* return a string array with each comma-separated element as a separate entry.
*/
public String[] readNext() throws IOException {
String nextLine = getNextLine();
return hasNext ? parseLine(nextLine) : null;
}
/**
* Reads the next line from the file.
*
* return the next line from the file without trailing newline
*/
private String getNextLine() throws IOException {
String nextLine = br.readLine();
if (nextLine == null) {
hasNext = false;
}
return hasNext ? nextLine : null;
}
/**
* Parses an incoming String and returns an array of elements.
*
* @param nextLine
* the string to parse
* @return the comma-tokenized list of elements, or null if nextLine is null
* @throws IOException if bad things happen during the read
*/
private String[] parseLine(String nextLine) throws IOException {
if (nextLine == null) {
return null;
}
List tokensOnThisLine = new ArrayList();
StringBuffer sb = new StringBuffer();
boolean inQuotes = false;
do {
if (inQuotes) {
// continuing a quoted section, reappend newline
sb.append("\n");
nextLine = getNextLine();
if (nextLine == null)
break;
}
for (int i = 0; i < nextLine.length(); i++) {
char c = nextLine.charAt(i);
if (c == quotechar) {
// this gets complex... the quote may end a quoted block, or escape another quote.
// do a 1-char lookahead:
if(inQuotes) // we are in quotes, therefore there can be escaped quotes in here.
&& nextLine.length() > (i+1) // there is indeed another character to check.
&& nextLine.charAt(i+1) == quotechar )
{ // ..and that char. is a quote also.
// we have two quote chars in a row == one quote char, so consume them both and
// put one on the token. we do *not* exit the quoted text.
sb.append(nextLine.charAt(i+1));
i++;
}
else
{
inQuotes = !inQuotes;
}
}
else if (c == separator && !inQuotes) {
tokensOnThisLine.add(sb.toString());
sb = new StringBuffer(); // start work on next token
}
else {
sb.append(c);
}
}
} while (inQuotes);
tokensOnThisLine.add(sb.toString());
return (String[]) tokensOnThisLine.toArray(new String[0]);
}
public void close() throws IOException {
br.close();
}
}
on
Upvotes: 1
Views: 1266
Reputation: 11
Here is the full code, with all requirements met:
package Scripts;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;
public class CSVReader {
private static BufferedReader br;
private static BufferedWriter writer;
private static FileWriter fileWriter;
private boolean hasNext = true;
private static char separator = ' ';
private static char quotechar = ' ';
static List<String[]> allElements;
public static final char DEFAULT_SEPARATOR = ',';
public static final char DEFAULT_QUOTE_CHARACTER = '"';
public static void main(final String[] args) throws IOException {
final String csvFile = args[0];
final File newCSV = new File("newCSV.csv");
final CSVReader csvTransformer = new CSVReader(br, separator, quotechar, csvFile, newCSV);
csvTransformer.readAll();
csvTransformer.close();
}
public CSVReader(final Reader reader) throws IOException {
this(reader, DEFAULT_SEPARATOR);
}
public CSVReader(final Reader reader, final char separator) throws IOException {
this(reader, separator, DEFAULT_QUOTE_CHARACTER, null, null);
}
public CSVReader(final Reader reader, final char separator, final char quotechar, final String csvFile,
final File newCSV) throws IOException {
CSVReader.br = new BufferedReader(new FileReader(csvFile));
CSVReader.separator = separator;
CSVReader.quotechar = quotechar;
CSVReader.fileWriter = new FileWriter(newCSV.getAbsoluteFile());
CSVReader.writer = new BufferedWriter(fileWriter);
}
/**
* Reads the entire file into a List with each element being a String[] of tokens.
*
* return a List of String[], with each String[] representing a line of the file.
*/
public List<String[]> readAll() throws IOException {
final List<String[]> allElements = new ArrayList<String[]>();
while (hasNext) {
final String[] nextLineAsTokens = readNext();
if (nextLineAsTokens != null) {
allElements.add(nextLineAsTokens);
}
}
return allElements;
}
/**
* Reads the next line from the buffer and converts to a string array.
*
* return a string array with each comma-separated element as a separate entry.
*/
public String[] readNext() throws IOException {
final String nextLine = getNextLine();
return hasNext ? parseLine(nextLine) : null;
}
/**
* Reads the next line from the file.
*
* return the next line from the file without trailing newline
*/
private String getNextLine() throws IOException {
final String nextLine = br.readLine();
if (nextLine == null) {
hasNext = false;
}
return hasNext ? nextLine : null;
}
/**
* Parses an incoming String and returns an array of elements & adds results to CSV.
*
* @param nextLine
* the string to parse
* @return the comma-tokenized list of elements, or null if nextLine is null
* @throws IOException
* if bad things happen during the read
*/
private String[] parseLine(final String nextLine) throws IOException {
if (nextLine == null) {
return null;
}
final List<String> tokensOnThisLine = new ArrayList<String>();
String result = nextLine.replaceAll("\"", "\"\"");
result = "\"" + result + "\"";
tokensOnThisLine.add(result.toString());
writer.write(result);
writer.write("\n");
return tokensOnThisLine.toArray(new String[0]);
}
public void close() throws IOException {
br.close();
writer.close();
}
} // end
Upvotes: 0
Reputation: 858
If your only need is about escaping double quotes, a simple way to do it is not considering the CSV file as a CSV but as a simple text file.
first thing first: the main method in Java is quite simple. use this declaration:
public static void main(String... args){
//do your stuff
// args is a String array containing parameters passed to your script, like your file. to get the first param, use args[0] , for the second it's args[1] ...
}
the main method will be automatically used by java if one is found in the called java class.
important point: main method MUST be public static and returning nothing as you can see here : Java spec, chapter 12
about your need, read each line from the file and replace it with the result of this function in a new file:
/**
*
* replace quotes in a line and append/prepend quotes to the line and return it
*
*/
private static String correctQuotesInLine(String nextLine) {
if (nextLine == null) {
return null;
}
//replace any single " in line
String result = nextLine.replaceAll("\"", "\"\"");
//prepend and append line with quotes
result = "\"" + result + "\"";
return result;
}
to write your resulting file, you can use those informations :
how to write files line by line using java
Upvotes: 1