NetTopologySuite / NetTopologySuite.IO.ShapeFile

The ShapeFile IO module for NTS.
33 stars 25 forks source link

System.NotSupportedException : Memory stream is not expandable. #55

Closed kristofdegrave closed 3 years ago

kristofdegrave commented 3 years ago

When writting a shape to a stream, I get the following error:

System.NotSupportedException : Memory stream is not expandable.

After doing some investigation I have found what the cause of this could be:

https://github.com/NetTopologySuite/NetTopologySuite.IO.ShapeFile/blob/c0819c1cfbf8c52146a0004e0e7b3a2b48044d98/src/NetTopologySuite.IO.ShapeFile/Streams/ByteStreamProvider.cs#L188

In here a new MemoryStream instance is created. When it is a user defined MemoryStream, you aren't able to let the stream grow.

See here a private _expandable property being set.

https://referencesource.microsoft.com/#mscorlib/system/io/memorystream.cs,108

When setting the capacity, you will see that this is checked and will result into the exception described in the title.

https://referencesource.microsoft.com/#mscorlib/system/io/memorystream.cs,283

To solve this you could use the default contstructor, or the constructor where you only pass the capacity of the stream.

https://referencesource.microsoft.com/#mscorlib/system/io/memorystream.cs,70

CodeBardian commented 3 years ago

I was facing this exact issue too, trying to write a shapefile to stream. After I almost finished changing the MemoryStream instantiation as suggested above, I came across the ExternallyManagedStreamProvider type which seems to do the trick. In there, there is no underlying MemoryStream with fixed capacity created.

This is how I managed to write a shapefile to stream:

var pt = GeometryFactory.Default.CreatePoint(new Coordinate(2, 3));
var attributes = new AttributesTable { { "Foo", "Bar" } };
Feature[] features = { new Feature(pt, attributes) };

var shpStream = new MemoryStream();
var shxStream = new MemoryStream();
var dbfStream = new MemoryStream();

var shpStreamProvider = new ShapefileStreamProviderRegistry(
   new ExternallyManagedStreamProvider(StreamTypes.Shape, shpStream),
   new ExternallyManagedStreamProvider(StreamTypes.Data, dbfStream),
   new ExternallyManagedStreamProvider(StreamTypes.Index, shxStream)
);

var wr = new ShapefileDataWriter(shpStreamProvider, GeometryFactory.Default, CodePagesEncodingProvider.Instance.GetEncoding(1252));
wr.Header = ShapefileDataWriter.GetHeader(features[0], features.Length);
wr.Write(features);         
kristofdegrave commented 3 years ago

I know, I provided that solution. Didn't see this issue was still open :)

kristofdegrave commented 3 years ago

Fixed by PR #58