line skip 추가
핵심은 기존 interface의 canParse 부분을 재활용하기 위하여 검증로직을 추가함. skip 할 수 있는 라인을 검증하는 부분을 추가
package parserTest;
public class CSVConfig {
private final char[] lineDelimiter;
private final char[] fieldSeparator;
private final char quote;
private final char comment;
private int skipLine = 0;
public CSVConfig(String lineDelimiter, String fieldSeparator, char quote, char comment, int skipLine) {
this.lineDelimiter = lineDelimiter.toCharArray();
this.fieldSeparator = fieldSeparator.toCharArray();
this.quote = quote;
this.comment = comment;
if (skipLine < 0){
throw new IllegalArgumentException(String.format("skipLine cannot be negative. Provided: %d", skipLine));
}
this.skipLine = skipLine;
}
public boolean shouldSkipLine(int lineIndex){
return skipLine == 0 || lineIndex >= skipLine;
}
public int getLineDelimiterLength(){
return lineDelimiter.length;
}
public int getFieldSeparatorLength(){
return fieldSeparator.length;
}
public char[] getLineDelimiter() {
return lineDelimiter;
}
public char[] getFieldSeparator() {
return fieldSeparator;
}
public char getQuote() {
return quote;
}
public char getComment() {
return comment;
}
}
Java
복사
package parserTest;
import org.apache.bcel.generic.IF_ACMPEQ;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;
public class RecordParser implements CSVParser<List<Record>> {
private final InternalBuffer buffer;
private final CSVConfig csvConfig;
private final CSVParser<List<String>> fieldParser;
private int order = 0;
public RecordParser(Reader reader, int bufferCapacity ,CSVConfig csvConfig) {
if (bufferCapacity <= 0) throw new IllegalArgumentException("Buffer capacity cannot be less than 1.");
this.buffer = new InternalBuffer(reader, bufferCapacity);
this.csvConfig = csvConfig;
this.fieldParser = new FieldParser(buffer, new CommentParser(buffer, csvConfig),csvConfig);
}
@Override
public List<Record> parse() {
final List<Record> records = new ArrayList<>();
int matchIndex = 0;
boolean inQuote = false;
while (buffer.fill()) {
int limit = buffer.getLimit();
for (int cursor = 0; cursor < limit; cursor++) {
char c = buffer.charAt(cursor);
if (c == csvConfig.getQuote()) {
inQuote = !inQuote;
continue;
}
if (!inQuote && (matchIndex = incrementIfMatch(csvConfig.getLineDelimiter(), c, matchIndex)) == csvConfig.getLineDelimiterLength()) {
// buffer 의 길이를 넘어서 matchIndex를 발견할 경우 자르는 위치가 애매해짐 그렇기에 제외해서 넘길 수 없음
// 예를 들면 버퍼의 크기가 1024일때 마지막 (\r)문자열 중 일부만 끝날 경우 뒤의 1024 버퍼에서 matchIndex 만큼 빼버리면 음수가 나옴
if (canParse()){
int length = (matchIndex == 1 ? cursor + matchIndex : cursor + matchIndex - 1) - buffer.getPos();
buffer.mergeOrAppendChars(length);
records.add(new Record(order, false, fieldParser.parse()));
}
buffer.setNewPosition(cursor + 1);
matchIndex = 0;
buffer.setRowLimit(0);
}
}
if (buffer.notPosAtLimit()) {
buffer.mergeOrAppendChars(buffer.getLimit() - buffer.getPos());
}
}
if (buffer.getRowLimit() != 0){
records.add(new Record(order, false, fieldParser.parse()));
buffer.setRowLimit(0);
}
return records;
}
@Override
public boolean canParse() {
return csvConfig.shouldSkipLine(order++);
// throw new UnsupportedOperationException("this method is Unsupported method");
}
}
Java
복사