diff --git a/src/NetTopologySuite.IO.Esri.Shapefile/Dbf/DbfStreamExtensions.cs b/src/NetTopologySuite.IO.Esri.Shapefile/Dbf/DbfStreamExtensions.cs
index bdb6ebd..c444268 100644
--- a/src/NetTopologySuite.IO.Esri.Shapefile/Dbf/DbfStreamExtensions.cs
+++ b/src/NetTopologySuite.IO.Esri.Shapefile/Dbf/DbfStreamExtensions.cs
@@ -115,7 +115,7 @@ public static DbfField ReadDbaseFieldDescriptor(this Stream stream, Encoding enc
}
else if (type == DbfType.Date)
{
- return new DbfDateField(name);
+ return new DbfDateField(name, length);
}
else if (type == DbfType.Numeric)
{
@@ -127,7 +127,7 @@ public static DbfField ReadDbaseFieldDescriptor(this Stream stream, Encoding enc
}
else if (type == DbfType.Logical)
{
- return new DbfLogicalField(name);
+ return new DbfLogicalField(name, length);
}
else
{
diff --git a/src/NetTopologySuite.IO.Esri.Shapefile/Dbf/Fields/DbfDateField.cs b/src/NetTopologySuite.IO.Esri.Shapefile/Dbf/Fields/DbfDateField.cs
index 3f4dd03..9e6aacf 100644
--- a/src/NetTopologySuite.IO.Esri.Shapefile/Dbf/Fields/DbfDateField.cs
+++ b/src/NetTopologySuite.IO.Esri.Shapefile/Dbf/Fields/DbfDateField.cs
@@ -11,15 +11,16 @@ namespace NetTopologySuite.IO.Esri.Dbf.Fields
///
public class DbfDateField : DbfField
{
- private static readonly int FieldLength = 8; // This width is fixed and cannot be changed
+ private const int FieldLength = 8; // This width is fixed and cannot be changed
private static readonly string DateFormat = "yyyyMMdd";
///
/// Initializes a new instance of the field class.
///
/// Field name.
- public DbfDateField(string name)
- : base(name, DbfType.Date, FieldLength, 0)
+ /// Field length.
+ public DbfDateField(string name, int length = FieldLength)
+ : base(name, DbfType.Date, length, 0)
{
}
diff --git a/src/NetTopologySuite.IO.Esri.Shapefile/Dbf/Fields/DbfLogicalField.cs b/src/NetTopologySuite.IO.Esri.Shapefile/Dbf/Fields/DbfLogicalField.cs
index 36c9610..5e5f752 100644
--- a/src/NetTopologySuite.IO.Esri.Shapefile/Dbf/Fields/DbfLogicalField.cs
+++ b/src/NetTopologySuite.IO.Esri.Shapefile/Dbf/Fields/DbfLogicalField.cs
@@ -1,6 +1,7 @@
using System;
using System.IO;
using System.Linq;
+using System.Text;
namespace NetTopologySuite.IO.Esri.Dbf.Fields
{
@@ -12,7 +13,7 @@ public class DbfLogicalField : DbfField
private readonly static byte DefaultValue = (byte)' '; // (byte)'?'; Initialized to 0x20 (space) otherwise T or F (http://www.dbase.com/KnowledgeBase/int/db7_file_fmt.htm)
private readonly static byte TrueValue = (byte)'T';
private readonly static byte FalseValue = (byte)'F';
- private readonly static int FieldLength = 1; // This width is fixed and cannot be changed
+ private const int FieldLength = 1; // This width is fixed and cannot be changed
private readonly static string TrueValues = "TtYy";
private readonly static string FalseValues = "FfNn";
@@ -22,8 +23,9 @@ public class DbfLogicalField : DbfField
/// Initializes a new instance of the field class.
///
/// Field name.
- public DbfLogicalField(string name)
- : base(name, DbfType.Logical, FieldLength, 0)
+ /// Field length.
+ public DbfLogicalField(string name, int length = FieldLength)
+ : base(name, DbfType.Logical, length, 0)
{
}
@@ -44,13 +46,22 @@ public override object Value
internal override void ReadValue(Stream stream)
{
- var logicalValue = stream.ReadByteChar();
+ // Logic column should have a Length of 1. However, some data providers produce shapfiles with a length greater than 1.
+ // Handle also those not specification compliant cases.
+ var logicalValueString = stream.ReadString(Length, Encoding.ASCII)?.Trim();
+ if (string.IsNullOrEmpty(logicalValueString))
+ {
+ LogicalValue = null;
+ return;
+ }
+
+ var logicalValueChar = logicalValueString[0];
- if (TrueValues.Contains(logicalValue))
+ if (TrueValues.Contains(logicalValueChar))
{
LogicalValue = true;
}
- else if (FalseValues.Contains(logicalValue))
+ else if (FalseValues.Contains(logicalValueChar))
{
LogicalValue = false;
}
@@ -78,7 +89,4 @@ internal override void WriteValue(Stream stream)
}
}
-
-
-
}
diff --git a/test/NetTopologySuite.IO.Esri.Test/Issues/Issue051.cs b/test/NetTopologySuite.IO.Esri.Test/Issues/Issue051.cs
new file mode 100644
index 0000000..25da8ab
--- /dev/null
+++ b/test/NetTopologySuite.IO.Esri.Test/Issues/Issue051.cs
@@ -0,0 +1,46 @@
+using System.Collections.Generic;
+using System.Linq;
+using NetTopologySuite.Features;
+using NetTopologySuite.IO.Esri.Dbf;
+using NUnit.Framework;
+
+namespace NetTopologySuite.IO.Esri.Test.Issues
+{
+ ///
+ /// https://github.com/NetTopologySuite/NetTopologySuite.IO.Esri/issues/51
+ ///
+ internal class Issue051
+ {
+ [Test]
+ public void Read_When_ColumnLengthMissmatch()
+ {
+ var shpPath = TestShapefiles.PathTo("#51-columnLengthMissmatch.dbf");
+ List attributes = null;
+ Assert.DoesNotThrow(() =>
+ {
+ var dbfReader = new DbfReader(shpPath);
+ attributes = dbfReader.ToList();
+ });
+
+ Assert.NotNull(attributes);
+
+ //First row is null and empty
+ Assert.AreEqual(string.Empty, attributes[0]["RoadLinkId"]);
+ Assert.AreEqual(null, attributes[0]["Tunnel"]);
+ Assert.AreEqual(null, attributes[0]["Bridge"]);
+ Assert.AreEqual(null, attributes[0]["CarAccess"]);
+ Assert.AreEqual(null, attributes[0]["Walk"]);
+ Assert.AreEqual(null, attributes[0]["MF_4_7"]);
+ Assert.AreEqual(null, attributes[0]["COREID"]);
+
+ //Second row has value but length is missmatch in each column
+ Assert.AreEqual("osgb4000000080908489", attributes[1]["RoadLinkId"]);
+ Assert.AreEqual(true, attributes[1]["Tunnel"]);
+ Assert.AreEqual(false, attributes[1]["Bridge"]);
+ Assert.AreEqual(true, attributes[1]["CarAccess"]);
+ Assert.AreEqual(4.8, attributes[1]["Walk"]);
+ Assert.AreEqual(50, attributes[1]["MF_4_7"]);
+ Assert.AreEqual(55483, attributes[1]["COREID"]);
+ }
+ }
+}
diff --git a/test/TestData/TestShapefiles/#51-columnLengthMissmatch.dbf b/test/TestData/TestShapefiles/#51-columnLengthMissmatch.dbf
new file mode 100644
index 0000000..46e8086
Binary files /dev/null and b/test/TestData/TestShapefiles/#51-columnLengthMissmatch.dbf differ