@@ -134,6 +134,7 @@ QStringList QgsDelimitedTextProvider::splitLine( QString line )
134
134
QgsDelimitedTextProvider::QgsDelimitedTextProvider ( QString uri )
135
135
: QgsVectorDataProvider( uri )
136
136
, mHasWktField( false )
137
+ , mFirstDataLine(0 )
137
138
, mFieldCount( 0 )
138
139
, mXFieldIndex( -1 ), mYFieldIndex( -1 )
139
140
, mWktFieldIndex( -1 )
@@ -199,7 +200,7 @@ QgsDelimitedTextProvider::QgsDelimitedTextProvider( QString uri )
199
200
if ( mFileName .isEmpty () || mDelimiter .isEmpty () )
200
201
{
201
202
// uri is invalid so the layer must be too...
202
- QString ( " Data source is invalid" );
203
+ QgsDebugMsg ( " Data source is invalid" );
203
204
return ;
204
205
}
205
206
@@ -238,12 +239,13 @@ QgsDelimitedTextProvider::QgsDelimitedTextProvider( QString uri )
238
239
{
239
240
lineNumber++;
240
241
line = readLine ( mStream ); // line of text excluding '\n', default local 8 bit encoding.
241
- if ( line.isEmpty () )
242
- continue ;
243
242
244
243
if ( lineNumber < mSkipLines + 1 )
245
244
continue ;
246
245
246
+ if ( line.isEmpty () )
247
+ continue ;
248
+
247
249
if ( !hasFields )
248
250
{
249
251
// Get the fields from the header row and store them in the
@@ -297,15 +299,14 @@ QgsDelimitedTextProvider::QgsDelimitedTextProvider( QString uri )
297
299
}
298
300
else // hasFields == true - field names already read
299
301
{
302
+ if ( mFirstDataLine == 0 ) mFirstDataLine = lineNumber;
300
303
301
304
// split the line on the delimiter
302
305
QStringList parts = splitLine ( line );
303
306
304
- // Skip malformed lines silently. Report line number with nextFeature()
305
- if ( parts.size () != mFieldCount )
306
- {
307
- continue ;
308
- }
307
+ // Ensure that the input has at least the required number of fields (mainly to tolerate
308
+ // missed blank strings at end of row)
309
+ while ( parts.size () < mFieldCount ) parts.append (" " );
309
310
310
311
if ( mHasWktField && mWktFieldIndex >= 0 )
311
312
{
@@ -443,13 +444,17 @@ bool QgsDelimitedTextProvider::nextFeature( QgsFeature& feature )
443
444
// lex the tokens from the current data line
444
445
QStringList tokens = splitLine ( line );
445
446
447
+ while ( tokens.size () < mFieldCount ) tokens.append (" " );
448
+
446
449
QgsGeometry *geom = 0 ;
447
450
448
451
if ( mHasWktField && mWktFieldIndex >= 0 )
449
452
{
450
453
try
451
454
{
452
455
QString &sWkt = tokens[mWktFieldIndex ];
456
+ // Remove Z and M coordinates if present, as currently fromWkt doesn't
457
+ // support these.
453
458
if ( mWktHasZM )
454
459
{
455
460
sWkt .remove ( mWktZMRegexp ).replace ( mWktCrdRegexp , " \\ 1" );
@@ -505,6 +510,7 @@ bool QgsDelimitedTextProvider::nextFeature( QgsFeature& feature )
505
510
i != mAttributesToFetch .end ();
506
511
++i )
507
512
{
513
+
508
514
QString &value = tokens[attributeColumns[*i]];
509
515
QVariant val;
510
516
switch ( attributeFields[*i].type () )
@@ -624,11 +630,10 @@ void QgsDelimitedTextProvider::rewind()
624
630
{
625
631
// Reset feature id to 0
626
632
mFid = 0 ;
627
- // Skip ahead one line since first record is always assumed to be
628
- // the header record
633
+ // Skip to first data record
629
634
mStream ->seek ( 0 );
630
- int n = mSkipLines + 1 ;
631
- while ( n-- )
635
+ int n = mFirstDataLine - 1 ;
636
+ while ( n-- > 0 )
632
637
readLine ( mStream );
633
638
}
634
639
0 commit comments