Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue #51, Fix the issue with the column length mismatch #52

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,16 @@ namespace NetTopologySuite.IO.Esri.Dbf.Fields
/// </summary>
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";

/// <summary>
/// Initializes a new instance of the field class.
/// </summary>
/// <param name="name">Field name.</param>
public DbfDateField(string name)
: base(name, DbfType.Date, FieldLength, 0)
/// <param name="length">Field length.</param>
public DbfDateField(string name, int length = FieldLength)
: base(name, DbfType.Date, length, 0)
{
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.IO;
using System.Linq;
using System.Text;

namespace NetTopologySuite.IO.Esri.Dbf.Fields
{
Expand All @@ -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";
Expand All @@ -22,8 +23,9 @@ public class DbfLogicalField : DbfField
/// Initializes a new instance of the field class.
/// </summary>
/// <param name="name">Field name.</param>
public DbfLogicalField(string name)
: base(name, DbfType.Logical, FieldLength, 0)
/// <param name="length">Field length.</param>
public DbfLogicalField(string name, int length = FieldLength)
: base(name, DbfType.Logical, length, 0)
{
}

Expand All @@ -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;
}
Expand Down Expand Up @@ -78,7 +89,4 @@ internal override void WriteValue(Stream stream)
}

}



}
46 changes: 46 additions & 0 deletions test/NetTopologySuite.IO.Esri.Test/Issues/Issue051.cs
Original file line number Diff line number Diff line change
@@ -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
{
/// <summary>
/// https://github.com/NetTopologySuite/NetTopologySuite.IO.Esri/issues/51
/// </summary>
internal class Issue051
{
[Test]
public void Read_When_ColumnLengthMissmatch()
{
var shpPath = TestShapefiles.PathTo("#51-columnLengthMissmatch.dbf");
List<IAttributesTable> 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"]);
}
}
}
Binary file not shown.
Loading