xBimTeam / XbimEssentials

A .NET library to work with data in the IFC format. This is the core component of the Xbim Toolkit
https://xbimteam.github.io/
Other
477 stars 171 forks source link

Open from stream #528

Closed simonedd closed 8 months ago

simonedd commented 8 months ago

Why do I need to specify the schema version? Is it not possible to retrieve this info from the stream?

Thank you

andyward commented 8 months ago

Would be a useful enhancement. I'd guess the reason was that we can't guarantee the stream is seekable, but you're right it should be possible to at least read and buffer a page - enough to read the headers.

Open to PRs if you want a go at it.

martin1cerny commented 8 months ago

As Andy said, it is not straightforward as many streams are not seekable. And .NET doesn't have any out-of-the-box buffering stream implementation.

andyward commented 8 months ago

Now implemented a solution for this in IfcStore.

See also #530

simonedd commented 8 months ago

Thanks for the implementation. Currently, I'm using this code to determine if the Stream is from a ZIP source, maybe it can be helpful to sniff the stream format (STP, Zip, XML )

// Check the first two bytes of the stream to see if it matches the zip signature.
// In theory it's not enough to detect zip files, tools that correctly read ZIP archives must scan for the end of central directory record signature.
byte[] header = new byte[2];
Stream.Read(header, 0, 2);
Stream.Seek(0, SeekOrigin.Begin);

int zipHeaderBytes = 0x4b50;

if ((BitConverter.ToInt16(header, 0) == zipHeaderBytes))
{
    System.IO.Compression.ZipArchive za = new System.IO.Compression.ZipArchive(Stream, System.IO.Compression.ZipArchiveMode.Read);
    if (za.Entries.Count != 1)
    {
        throw Exception("The zip archive must have a single .ifc file in the main directory");

    }
    StreamReader streamReader = new StreamReader(za.Entries[0].Open(), Encoding.ASCII);
}
andyward commented 8 months ago

Cheers - we'd also need to check for ifcXML and potentially zipped XML. One challenge with the ZipArchive code above is it may not meet the assumptions of the Seekable stream I implemented - which only has a limited buffer, so you'd likely have to buffer to memory or a fileStream to do this.

I did think about this implementation and concluded that in the majority of cases that you'd have things like a Content-type you could use to determine the input (and maybe a filename/extension). That's what we do in xbim Flex.