Skip to content

Commit 787ab08

Browse files
committed
CSV-85 Allow comments to be returned in CSVRecord
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/csv/trunk@1306947 13f79535-47bb-0310-9956-ffa450edef68
1 parent e940855 commit 787ab08

5 files changed

Lines changed: 36 additions & 11 deletions

File tree

src/main/java/org/apache/commons/csv/CSVLexer.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,8 @@ Token nextToken(Token tkn) throws IOException {
7777
}
7878

7979
if (isStartOfLine(lastChar) && isCommentStart(c)) {
80-
in.readLine();
80+
String comment = in.readLine().trim();
81+
tkn.content.append(comment);
8182
tkn.type = COMMENT;
8283
return tkn;
8384
}

src/main/java/org/apache/commons/csv/CSVParser.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,9 @@ public List<CSVRecord> getRecords() throws IOException {
133133
* @throws IOException on parse error or input read-failure
134134
*/
135135
CSVRecord getRecord() throws IOException {
136-
CSVRecord result = new CSVRecord(null, headerMapping);
136+
CSVRecord result = new CSVRecord(null, headerMapping, null);
137137
record.clear();
138+
StringBuilder sb = null;
138139
do {
139140
reusableToken.reset();
140141
lexer.nextToken(reusableToken);
@@ -155,13 +156,20 @@ CSVRecord getRecord() throws IOException {
155156
case INVALID:
156157
throw new IOException("(line " + getLineNumber() + ") invalid parse sequence");
157158
case COMMENT: // Ignored currently
159+
if (sb == null) { // first comment for this record
160+
sb = new StringBuilder();
161+
} else {
162+
sb.append("\n");
163+
}
164+
sb.append(reusableToken.content);
158165
reusableToken.type = TOKEN; // Read another token
159166
break;
160167
}
161168
} while (reusableToken.type == TOKEN);
162169

163170
if (!record.isEmpty()) {
164-
result = new CSVRecord(record.toArray(new String[record.size()]), headerMapping);
171+
result = new CSVRecord(record.toArray(new String[record.size()]), headerMapping,
172+
sb == null ? null : sb.toString());
165173
}
166174
return result;
167175
}

src/main/java/org/apache/commons/csv/CSVRecord.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,13 @@ public class CSVRecord implements Serializable, Iterable<String> {
3535
/** The column name to index mapping. */
3636
private final Map<String, Integer> mapping;
3737

38-
CSVRecord(String[] values, Map<String, Integer> mapping) {
38+
/** The accumulated comments (if any) */
39+
private final String comment;
40+
41+
CSVRecord(String[] values, Map<String, Integer> mapping, String comment) {
3942
this.values = values != null ? values : EMPTY_STRING_ARRAY;
4043
this.mapping = mapping;
44+
this.comment = comment;
4145
}
4246

4347
/**
@@ -74,6 +78,9 @@ String[] values() {
7478
return values;
7579
}
7680

81+
public String getComment() {
82+
return comment;
83+
}
7784
/**
7885
* Returns the number of values in this record.
7986
*/

src/test/java/org/apache/commons/csv/CSVFileParserTest.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ public void testCSVFile() throws Exception {
8989
// first line starts with csv data file name
9090
BufferedReader csvFile = new BufferedReader(new FileReader(new File(BASE, split[0])));
9191
CSVFormat fmt = CSVFormat.PRISTINE.withDelimiter(',').withEncapsulator('"');
92+
boolean checkComments = false;
9293
for(int i=1; i < split.length; i++) {
9394
final String option = split[i];
9495
String[] option_parts = option.split("=",2);
@@ -98,6 +99,8 @@ public void testCSVFile() throws Exception {
9899
fmt = fmt.withSurroundingSpacesIgnored(Boolean.parseBoolean(option_parts[1]));
99100
} else if ("CommentStart".equalsIgnoreCase(option_parts[0])) {
100101
fmt = fmt.withCommentStart(option_parts[1].charAt(0));
102+
} else if ("CheckComments".equalsIgnoreCase(option_parts[0])) {
103+
checkComments = true;
101104
} else {
102105
fail(testName+" unexpected option: "+option);
103106
}
@@ -108,6 +111,12 @@ public void testCSVFile() throws Exception {
108111
// Now parse the file and compare against the expected results
109112
for(CSVRecord rec : fmt.parse(csvFile)) {
110113
String parsed = rec.toString();
114+
if (checkComments) {
115+
final String comment = rec.getComment().replace("\n", "\\n");
116+
if (comment != null) {
117+
parsed += "#" + comment;
118+
}
119+
}
111120
int count = rec.size();
112121
assertEquals(testName, readTestData(), count+":"+parsed);
113122
}

src/test/java/org/apache/commons/csv/CSVLexerTest.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public void testNextToken2() throws IOException {
6363
"a,b x,c#no-comment\n"+ // 2
6464
"\n"+
6565
"\n"+
66-
"#foo\n"+ // 3
66+
"# foo \n"+ // 3
6767
"\n"+ // 4
6868
"d,e,#no-comment\n"+ // 5
6969
"\n"+
@@ -85,13 +85,13 @@ public void testNextToken2() throws IOException {
8585
assertTokenEquals(TOKEN, "a", parser.nextToken(new Token()));
8686
assertTokenEquals(TOKEN, "b x", parser.nextToken(new Token()));
8787
assertTokenEquals(EORECORD, "c#no-comment", parser.nextToken(new Token())); // 2
88-
assertTokenEquals(COMMENT, "", parser.nextToken(new Token())); // 3
88+
assertTokenEquals(COMMENT, "foo", parser.nextToken(new Token())); // 3
8989
// 4 empty line, ignored // 4
9090
assertTokenEquals(TOKEN, "d", parser.nextToken(new Token()));
9191
assertTokenEquals(TOKEN, "e", parser.nextToken(new Token()));
9292
assertTokenEquals(EORECORD, "#no-comment", parser.nextToken(new Token())); // 5
93-
assertTokenEquals(COMMENT, "", parser.nextToken(new Token())); // 6
94-
assertTokenEquals(COMMENT, "", parser.nextToken(new Token())); // 7
93+
assertTokenEquals(COMMENT, "penultimate comment", parser.nextToken(new Token())); // 6
94+
assertTokenEquals(COMMENT, "Final comment", parser.nextToken(new Token())); // 7
9595
assertTokenEquals(EOF, "", parser.nextToken(new Token()));
9696
assertTokenEquals(EOF, "", parser.nextToken(new Token()));
9797

@@ -130,18 +130,18 @@ public void testNextToken2EmptyLines() throws IOException {
130130
assertTokenEquals(TOKEN, "a", parser.nextToken(new Token()));
131131
assertTokenEquals(TOKEN, "b x", parser.nextToken(new Token()));
132132
assertTokenEquals(EORECORD, "c#no-comment", parser.nextToken(new Token())); // 2
133-
assertTokenEquals(COMMENT, "", parser.nextToken(new Token())); // 3
133+
assertTokenEquals(COMMENT, "foo", parser.nextToken(new Token())); // 3
134134
assertTokenEquals(EORECORD, "", parser.nextToken(new Token())); // 4
135135
assertTokenEquals(EORECORD, "", parser.nextToken(new Token())); // 4b
136136
assertTokenEquals(TOKEN, "d", parser.nextToken(new Token()));
137137
assertTokenEquals(TOKEN, "e", parser.nextToken(new Token()));
138138
assertTokenEquals(EORECORD, "#no-comment", parser.nextToken(new Token())); // 5
139139
assertTokenEquals(EORECORD, "", parser.nextToken(new Token())); // 5b
140140
assertTokenEquals(EORECORD, "", parser.nextToken(new Token())); // 5c
141-
assertTokenEquals(COMMENT, "", parser.nextToken(new Token())); // 6
141+
assertTokenEquals(COMMENT, "penultimate comment", parser.nextToken(new Token())); // 6
142142
assertTokenEquals(EORECORD, "", parser.nextToken(new Token())); // 6b
143143
assertTokenEquals(EORECORD, "", parser.nextToken(new Token())); // 6c
144-
assertTokenEquals(COMMENT, "", parser.nextToken(new Token())); // 7
144+
assertTokenEquals(COMMENT, "Final comment", parser.nextToken(new Token())); // 7
145145
assertTokenEquals(EOF, "", parser.nextToken(new Token()));
146146
assertTokenEquals(EOF, "", parser.nextToken(new Token()));
147147

0 commit comments

Comments
 (0)