Skip to content

Ideas for new API (Writing)

Joe Amenta edited this page Aug 20, 2020 · 9 revisions

Simple usage samples

No .dbf file

// you could pass in a pair of seekable Streams here instead of a file path:
using var writer = Shapefiles.CreateWithoutData(@"C:\path\to\shapefile.shp");
var geoms = BuildMyGeometryInstances(); // must be IReadOnlyList<Geometry>
writer.Write(geoms);

Possible exceptions include, but are not necessarily limited to:

  1. the list is empty
  2. the geometries hold too much data for a single shapefile
  3. the list has geometries of multiple different types
  4. the list has geometries with spatial dimensions > 3 or measures > 1

With a .dbf file

// you could pass in three seekable Streams here instead of a file path:
using var writer = Shapefiles.CreateWithData(@"C:\path\to\shapefile.shp", Encoding.UTF8);
var features = BuildMyFeatureInstances(); // must be IReadOnlyList<IFeature>
writer.Write(features);

Possible exceptions include, but are not necessarily limited to:

  1. all the same exceptions we can throw for the shapefile part on its own
  2. the attributes tables for different features are incompatible with one another
    • e.g., one feature has "ID" as int, but another has "ID" as Guid
  3. some feature has an attribute whose type can't be written to DBF
  4. some feature has an attribute whose name exceeds 255 characters or whatever
  5. some attribute's data would require entirely too much space on its own (and we're not using memos)
  6. the combination of all attributes among all features take up more space than the largest legal record##

More advanced usage samples

Streamed, fully forward-only, no .dbf file

using var writer = Shapefiles.CreateForwardOnly(
    metadata: Shapefiles.CreateMetadataForPoints(geometryCount: 90210, ordinates: Ordinates.XY),
    mainFileStream: OpenSomeForwardOnlyStream(),
    indexFileStream: OpenSomeOtherForwardOnlyStream(),
    leaveStreamsOpen: false);
var geoms = BuildMyGeometryInstances(); // this can be any IEnumerable<Geometry>
foreach (var geom in geoms)
{
    writer.Write(geom);
}

Exceptions are mostly the same as the "simple" case, minus one or two, plus some more if the extra metadata we got ahead of time is inconsistent with the actual data.

Streamed, fully forward-only, .dbf file

using var writer = Shapefiles.CreateForwardOnly(
    metadata: Shapefiles.CreateMetadataForPoints(geometryCount: 90210, ordinates: Ordinates.XY)
                        .AddStringAttribute(name: "NAME", maxEncodedLength: 12)
                        .AddInt32Attribute(name: "POP", maxValue: 35125)
                        .AddBooleanAttribute(name: "BLOCKED")
                        .AddNumericAttribute(name: "TAX_RATE", maxValue: 0.45, precision: 4),
    mainFileStream: OpenSomeForwardOnlyStream(),
    indexFileStream: OpenSomeOtherForwardOnlyStream(),
    dataFileStream: OpenSomeThirdForwardOnlyStream(),
    leaveStreamsOpen: false);
var features = BuildMyFeatureInstances(); // this can be any IEnumerable<IFeature>

foreach (var feature in features)
{
    writer.Write(feature);
}

Miscellaneous other files

.cpg

Shapefiles.EnsureCodepageFile(@"C:\path\to\shapefile.shp", codepageNumber);

Throws if there's already a codepage file that says something different.

.prj

Shapefiles.EnsureProjectionFile(@"C:\path\to\shapefile.shp", someProjectionWkt);

Throws if there's already a projection file with something other than the given WKT (probably just exact equality, since I don't want a ProjNet dependency right now).