@@ -66,7 +66,7 @@ public class CsvReader implements Closeable {
66
66
// private String rawRecord = "";
67
67
68
68
/** The headers holder. */
69
- final HeadersHolder headersHolder = new HeadersHolder () ;
69
+ HeadersHolder headersHolder ;
70
70
71
71
// these are all more or less global loop variables
72
72
// to keep from needing to pass them all into various
@@ -399,7 +399,7 @@ public void setSkipEmptyRecords(final boolean skipEmptyRecords) {
399
399
* @return The count of headers read in by a previous call to
400
400
* {@link msi.gama.util.file.csv.csvreader.CsvReader#readHeaders readHeaders()}.
401
401
*/
402
- public int getHeaderCount () { return headersHolder .Length ; }
402
+ public int getHeaderCount () { return headersHolder == null ? 0 : headersHolder .Length () ; }
403
403
404
404
/**
405
405
* Returns the header values as a string array.
@@ -411,35 +411,15 @@ public void setSkipEmptyRecords(final boolean skipEmptyRecords) {
411
411
public String [] getHeaders () throws IOException {
412
412
checkClosed ();
413
413
414
- if (headersHolder .Headers == null ) return null ;
414
+ if (headersHolder == null || headersHolder .Headers () == null ) return null ;
415
415
// use clone here to prevent the outside code from
416
416
// setting values on the array directly, which would
417
417
// throw off the index lookup based on header name
418
- final String [] clone = new String [headersHolder .Length ];
419
- System .arraycopy (headersHolder .Headers , 0 , clone , 0 , headersHolder .Length );
418
+ final String [] clone = new String [headersHolder .Length () ];
419
+ System .arraycopy (headersHolder .Headers , 0 , clone , 0 , headersHolder .Length () );
420
420
return clone ;
421
421
}
422
422
423
- /**
424
- * Sets the headers.
425
- *
426
- * @param headers
427
- * the new headers
428
- */
429
- public void setHeaders (final String [] headers ) {
430
- headersHolder .Headers = headers ;
431
-
432
- headersHolder .IndexByName .clear ();
433
-
434
- if (headers != null ) {
435
- headersHolder .Length = headers .length ;
436
- for (int i = 0 ; i < headersHolder .Length ; i ++) { headersHolder .IndexByName .put (headers [i ], i ); }
437
- } else {
438
- headersHolder .Length = 0 ;
439
- }
440
-
441
- }
442
-
443
423
/**
444
424
* Gets the values.
445
425
*
@@ -514,12 +494,14 @@ public static class Stats {
514
494
* the CS vsep
515
495
*/
516
496
Stats (final CsvReader reader , final String CSVsep ) {
497
+ // By default now (see #3786)
498
+ reader .setTextQualifier ('"' );
517
499
boolean firstLineHasNumber = false ;
518
- String [] possibleHeaders = null ;
500
+ // String[] possibleHeaders = null;
519
501
try {
520
502
// firstLine
521
503
final String s = reader .skipLine ();
522
- possibleHeaders = processFirstLine (s , CSVsep );
504
+ headers = processFirstLine (s , CSVsep );
523
505
firstLineHasNumber = atLeastOneNumber ;
524
506
atLeastOneNumber = false ;
525
507
reader .setDelimiter (delimiter );
@@ -535,9 +517,12 @@ public static class Stats {
535
517
}
536
518
while (reader .readRecord ()) { if (reader .columnsCount > cols ) { cols = reader .columnsCount ; } }
537
519
} catch (final IOException e ) {}
538
- if (!type .equals (firstLineType ) || !firstLineHasNumber && atLeastOneNumber ) { header = true ; }
520
+ if (!type .equals (firstLineType ) || !firstLineHasNumber && atLeastOneNumber ) {
521
+ header = true ;
522
+ cols = headers .length ;
523
+ }
539
524
// if ( header ) {
540
- headers = possibleHeaders ;
525
+ // headers = possibleHeaders;
541
526
// }
542
527
rows = (int ) reader .currentRecord + 1 ;
543
528
reader .close ();
@@ -1281,19 +1266,18 @@ public boolean readHeaders() throws IOException {
1281
1266
// copy the header data from the column array
1282
1267
// to the header string array
1283
1268
1284
- headersHolder .Length = columnsCount ;
1285
-
1286
- headersHolder .Headers = new String [columnsCount ];
1269
+ String [] headers = new String [columnsCount ];
1270
+ HashMap indexByName = new HashMap ();
1287
1271
1288
- for (int i = 0 ; i < headersHolder . Length ; i ++) {
1272
+ for (int i = 0 ; i < columnsCount ; i ++) {
1289
1273
final String columnValue = get (i );
1290
1274
1291
- headersHolder . Headers [i ] = columnValue ;
1275
+ headers [i ] = columnValue ;
1292
1276
1293
1277
// if there are duplicate header names, we will save the last one
1294
- headersHolder . IndexByName .put (columnValue , i );
1278
+ indexByName .put (columnValue , i );
1295
1279
}
1296
-
1280
+ headersHolder = new HeadersHolder ( headers , columnsCount , indexByName );
1297
1281
if (result ) { currentRecord --; }
1298
1282
1299
1283
columnsCount = 0 ;
@@ -1453,7 +1437,7 @@ private void endRecord() throws IOException {
1453
1437
*/
1454
1438
public int getIndex (final String headerName ) throws IOException {
1455
1439
checkClosed ();
1456
-
1440
+ if ( headersHolder == null ) return - 1 ;
1457
1441
final Object indexValue = headersHolder .IndexByName .get (headerName );
1458
1442
1459
1443
if (indexValue != null ) return (Integer ) indexValue ;
@@ -1519,6 +1503,7 @@ public String skipLine() throws IOException {
1519
1503
/**
1520
1504
* Closes and releases all related resources.
1521
1505
*/
1506
+ @ Override
1522
1507
public void close () {
1523
1508
if (!closed ) {
1524
1509
close (true );
@@ -1534,8 +1519,6 @@ private void close(final boolean closing) {
1534
1519
if (!closed ) {
1535
1520
if (closing ) {
1536
1521
charset = null ;
1537
- headersHolder .Headers = null ;
1538
- headersHolder .IndexByName = null ;
1539
1522
dataBuffer .Buffer = null ;
1540
1523
columnBuffer .Buffer = null ;
1541
1524
// rawBuffer.Buffer = null;
@@ -1782,26 +1765,7 @@ public UserSettings() {
1782
1765
/**
1783
1766
* The Class HeadersHolder.
1784
1767
*/
1785
- private static class HeadersHolder {
1786
-
1787
- /** The Headers. */
1788
- public String [] Headers ;
1789
-
1790
- /** The Length. */
1791
- public int Length ;
1792
-
1793
- /** The Index by name. */
1794
- public HashMap IndexByName ;
1795
-
1796
- /**
1797
- * Instantiates a new headers holder.
1798
- */
1799
- public HeadersHolder () {
1800
- Headers = null ;
1801
- Length = 0 ;
1802
- IndexByName = new HashMap ();
1803
- }
1804
- }
1768
+ private static record HeadersHolder (String [] Headers , int Length , HashMap IndexByName ) {}
1805
1769
1806
1770
/**
1807
1771
* The Class StaticSettings.
0 commit comments