Skip to content

Commit

Permalink
Merge pull request #59 from NetTopologySuite/fix/issue046
Browse files Browse the repository at this point in the history
Prevent duplicate field names. Fix #46.
  • Loading branch information
KubaSzostak authored Sep 19, 2024
2 parents 552d743 + e777ba5 commit 72637b1
Show file tree
Hide file tree
Showing 8 changed files with 48 additions and 13 deletions.
2 changes: 1 addition & 1 deletion src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@

<ItemGroup>
<!-- SourceLink adds stuff to let debuggers step into our code. -->
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All" />
</ItemGroup>

</Project>
5 changes: 5 additions & 0 deletions src/NetTopologySuite.IO.Esri.Shapefile/Dbf/DbfReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,15 @@ private void Initialize(Stream stream, Encoding encoding = null)

Buffer.AssignFrom(DbfStream, fieldsHeaderSize);
Fields = new DbfFieldCollection(fieldCount);
var duplicates = new Dictionary<string, int>();
for (int i = 0; i < fieldCount; i++)
{
var field = Buffer.ReadDbaseFieldDescriptor(Encoding);
string originalName = field.Name;
duplicates.TryGetValue(originalName, out int duplicateCount);
field.DuplicateCount = duplicateCount;
Fields.Add(field);
duplicates[originalName] = ++duplicateCount;
//Binary.TraceToConsole("Field Header: " + Fields[Fields.Count -1].Name, i * Dbf.FieldDescriptorSize, Dbf.FieldDescriptorSize);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,7 @@ public static Encoding ReadDbfEncoding(this Stream stream)
public static void WriteDbaseFieldDescriptor(this Stream stream, DbfField field, Encoding encoding)
{
encoding = encoding ?? Dbf.DefaultEncoding;
var name = field.Name.PadRight(Dbf.MaxFieldNameLength, char.MinValue); // Field name must have empty space zero-filled

var name = field.OriginalName.PadRight(Dbf.MaxFieldNameLength, char.MinValue); // Field name must have empty space zero-filled

stream.WriteString(name, Dbf.MaxFieldNameLength, encoding);
stream.WriteNullBytes(1);
Expand Down
23 changes: 15 additions & 8 deletions src/NetTopologySuite.IO.Esri.Shapefile/Dbf/Fields/DbfField.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,22 @@ public abstract class DbfField
{
// TODO: Spit DbfField into DbfFieldDefinition (Without Value property) and DbfFieldValue

/// <summary>
/// Original field name
/// </summary>
internal string OriginalName { get; }

/// <summary>
/// Field Name.
/// </summary>
public string Name { get; }
public string Name
{
get
{
string suffix = DuplicateCount > 0 ? $"_{DuplicateCount}" : string.Empty;
return $"{OriginalName}{suffix}";
}
}

/// <summary>
/// Field Type.
Expand Down Expand Up @@ -75,17 +87,12 @@ internal DbfField(string name, DbfType type, int length, int precision)
throw new ArgumentException($"Ivalid dBASE field precision: {precision}.", nameof(precision));
}

Name = name;
OriginalName = name;
FieldType = type;
Length = length;
NumericScale = precision;
}

private bool IsValidFieldNameChar(char c)
{
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || (c >= '0' && c <= '9');
}

/// <inheritdoc/>
public override string ToString()
{
Expand Down Expand Up @@ -113,7 +120,7 @@ internal Exception GetFieldValueError(object value, string additionalDescription
/// </summary>
public virtual bool IsNull => Value == null;


internal int DuplicateCount { get; set; }

internal static readonly IAttributesTable EmptyFieldValues = new AttributesTable();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ IEnumerator IEnumerable.GetEnumerator()

internal void Add(DbfField field)
{
if (FieldDictionary.ContainsKey(field.Name))
throw new ArgumentException($"Field with name '{field.Name}' already defined.");
Fields.Add(field);
FieldDictionary.Add(field.Name, field);
}
Expand Down
4 changes: 2 additions & 2 deletions test/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@

<ItemGroup>
<PackageReference Include="nunit" Version="3.12.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.16.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
<PackageReference Include="NUnit3TestAdapter" Version="4.6.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.11.1" />
</ItemGroup>

</Project>
22 changes: 22 additions & 0 deletions test/NetTopologySuite.IO.Esri.Test/Issues/Issue046.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using NetTopologySuite.IO.Esri.Dbf;
using NUnit.Framework;
using System.Collections.Generic;

namespace NetTopologySuite.IO.Esri.Test.Issues
{
internal class Issue046
{
[Test]
public void TestNoDuplicateColumnName()
{
using var dbfReader = new DbfReader(TestShapefiles.PathTo("Issues/046/Antragsschläge 2024_POLYGONE.dbf"));
var dbfFields = dbfReader.Fields;
var fieldNames = new HashSet<string>();
for (int i = 0; i < dbfFields.Count; i++)
{
Assert.That(fieldNames.Contains(dbfFields[i].Name), Is.False);
fieldNames.Add(dbfFields[i].Name);
}
}
}
}
Binary file not shown.

0 comments on commit 72637b1

Please sign in to comment.