For AutoCad 2000 drawings
The easy way:
Imports System
Imports System.IO
Imports System.Text
Public NotInheritable Class SMI2000Easy
Public Shared Sub read2000B(ByVal filename As String)
Using fs As FileStream = New FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
Using br As binreader = New binreader(fs)
Dim versionId As String = br.ReadChars(6)
If Not versionId.Equals("AC1015", StringComparison.InvariantCultureIgnoreCase) Then
Return
End If
' six bytes of 0 (in R14, 5 0’s and the ACADMAINTVER variable) and a byte of 1
br.ReadBytes(7)
' Image seeker
Dim imageSeeker As Integer = br.ReadInt32
' Unknown section
br.ReadBytes(2)
' Dwgcodepage
br.ReadBytes(2)
Dim objectmapSeeker As Integer
' Section-locator records:
Dim count As Integer = br.ReadInt32
For i As Integer = 0 To count - 1
Dim recnum As Byte = br.ReadByte
Dim seeker As Integer = br.ReadInt32
Dim size As Integer = br.ReadInt32
Select Case recnum
Case 0
'System.Diagnostics.Debug.Print("Header variables")
Case 1
'System.Diagnostics.Debug.Print("Class section")
Case 2
'System.Diagnostics.Debug.Print("Object map")
objectmapSeeker = seeker
Case 3
'System.Diagnostics.Debug.Print("Unknown")
Case 4
'System.Diagnostics.Debug.Print("R14DATA")
Case 5
'System.Diagnostics.Debug.Print("R14REC5")
Case Else
Return
End Select
Next
fs.Seek(imageSeeker, SeekOrigin.Begin)
Dim mask() As Byte = New Byte() {87, 71, 80, 82, 79, 80, 83, 32, 67, 79, 79, 75, 73, 69}
While fs.Position < objectmapSeeker
' Search DWGPROPS COOKIE
Dim d As Byte = br.ReadByte
If d <> 68 Then
Continue While
End If
Dim test() As Byte = br.ReadBytes(mask.Length)
For i As Integer = 0 To mask.Length - 1
If test(i) <> mask(i) Then
fs.Seek(-mask.Length, SeekOrigin.Current)
Continue While
End If
Next
'------------------------------------------------------------
' Predefined properties, in this order:
' title, subject, author, comments, keywords,
' lastSavedBy, revisionNumber
' DXF codes : 2, 3, 4, 6, 7, 8, 9
For i As Integer = 0 To 6
Dim code As Short = br.ReadInt16 ' DXF code
Dim len As Short = br.ReadInt16 ' String lenght
br.ReadByte() ' ?
Dim bytes() As Byte = br.ReadBytes(len)
Dim value As String = Encoding.ASCII.GetString(bytes)
System.Diagnostics.Debug.Print(value)
Next
'------------------------------------------------------------
'------------------------------------------------------------
' 10 custom properties in the format:
' <name=value>
' DXF codes : 300, 301, 302, 303, 304, 305, 306, 307, 308, 309
For i As Integer = 0 To 9
Dim code As Short = br.ReadInt16 ' DXF code
Dim len As Short = br.ReadInt16 ' String lenght
br.ReadByte() ' ?
Dim bytes() As Byte = br.ReadBytes(len)
Dim value As String = Encoding.ASCII.GetString(bytes)
'Dim pairs() As String = value.Split(New Char() {"="c})
System.Diagnostics.Debug.Print(value)
Next
' Total editing time, Create date time and Modified
' date time in the format:
' <Julian day number>.<Decimal fraction of a day>
' DXF codes: 40, 41 ,42
For i As Integer = 0 To 2
Dim code As Short = br.ReadInt16 ' DXF code
Dim value As Double = br.ReadDouble ' Value
System.Diagnostics.Debug.Print(value.ToString)
Next
'------------------------------------------------------------
'------------------------------------------------------------
' hyperlinkBase
' DXF code: 1
Dim c As Short = br.ReadInt16 ' DXF code
Dim l As Short = br.ReadInt16 ' String lenght
br.ReadByte() ' ? Unknow
Dim b() As Byte = br.ReadBytes(l)
Dim v As String = Encoding.ASCII.GetString(b)
System.Diagnostics.Debug.Print(v)
'------------------------------------------------------------
Return
End While
End Using
End Using
End Sub
End Class
The Hard way: Creating a small dwg reader
The code is not complete, still do not know how to decode an xrecord object. but if someone is interested:
Imports System
Imports System.Text
Imports System.IO
Imports System.Collections
Imports System.Globalization
Public NotInheritable Class SMI2000Hard
Public Shared Sub read2000(ByVal filename As String)
Using fs As FileStream = New FileStream(filename, _
FileMode.Open, _
FileAccess.Read, _
FileShare.ReadWrite)
Using br As binreader = New binreader(fs)
Dim versionId As String = br.ReadChars(6)
If Not versionId.Equals("AC1015", StringComparison.InvariantCultureIgnoreCase) Then
Return
End If
' six bytes of 0 (in R14, 5 0’s and the ACADMAINTVER variable) and a byte of 1
br.ReadBytes(7)
' Image seeker
Dim imageSeeker As Integer = br.ReadInt32
' Unknown section
br.ReadBytes(2)
' Dwgcodepage
br.ReadBytes(2)
Dim objectmapSeeker As Integer
' Section-locator records:
Dim count As Integer = br.ReadInt32
For i As Integer = 0 To count - 1
Dim recnum As Byte = br.ReadByte
Dim seeker As Integer = br.ReadInt32
Dim size As Integer = br.ReadInt32
Select Case recnum
Case 0
'System.Diagnostics.Debug.Print("Header variables")
Case 1
'System.Diagnostics.Debug.Print("Class section")
Case 2
'System.Diagnostics.Debug.Print("Object map")
objectmapSeeker = seeker
Case 3
'System.Diagnostics.Debug.Print("Unknown")
Case 4
'System.Diagnostics.Debug.Print("R14DATA")
Case 5
'System.Diagnostics.Debug.Print("R14REC5")
Case Else
Return
End Select
Next
fs.Seek(objectmapSeeker, SeekOrigin.Begin)
Dim loc As Long
Do
'-------------------------------------------------
' BIG ENDIAN
Dim b() As Byte = br.ReadBytes(2)
Array.Reverse(b)
Dim size As Short = BitConverter.ToInt16(b, 0)
'-------------------------------------------------
If size = 2 Then
Exit Do
End If
Dim dataBytes(size - 1) As Byte
For i As Integer = 0 To dataBytes.Length - 1
dataBytes(i) = br.ReadByte
Next i
Dim lastHandle As Integer = 0
Dim lastLoc As Integer = 0
Dim bitPos As Integer = 0
Dim bitMax As Integer = (size - 2) * 8
loc = fs.Position
Do While bitPos < bitMax
Dim v As ArrayList = GetModularChar(dataBytes, bitPos)
bitPos = CInt(v(0))
lastHandle = lastHandle + CInt(v(1))
v = GetModularChar(dataBytes, bitPos)
bitPos = (CInt(v(0)))
lastLoc = lastLoc + CInt(v(1))
' Search for XRecord
'If TestDwgObject(br, lastLoc) Then
' Return
'End If
TestDwgObject(br, lastLoc)
Loop
fs.Seek(loc, SeekOrigin.Begin)
Loop
End Using
End Using
End Sub
Private Shared Function TestDwgObject(ByVal br As binreader, _
ByVal offset As Integer) As Boolean
br.BaseStream.Seek(offset, SeekOrigin.Begin)
Dim size As Integer = GetModularShort(br)
Dim dataBytes(size - 1) As Byte
Dim data(size - 1) As Integer
For i As Integer = 0 To size - 1
dataBytes(i) = br.ReadByte
Next
Dim bitPos As Integer = 0
Dim v As ArrayList = GetBitShort(dataBytes, bitPos)
bitPos = CInt(v(0))
' Object Type
Dim type As Integer = CInt(v(1))
' If type = &H2A then
' object = DICCTIONAY
' If type <> XRecord
If type <> &H4F Then
Return Nothing
End If
' Object Size
v = GetRawLong(dataBytes, bitPos)
bitPos = CInt(v(0))
' Handle (¿?no parece correcto)
Dim entityHandle As New ArrayList()
v = GetHandle(dataBytes, bitPos)
bitPos = CInt(v(0))
' Extended data
v = ReadExtendedData(dataBytes, bitPos)
bitPos = CInt(v(0))
' Number of persistent reactors
v = GetBitLong(dataBytes, bitPos)
bitPos = CInt(v(0))
Dim nr As Integer = CInt(v(1))
' Number of databytes
v = GetBitLong(dataBytes, bitPos)
bitPos = CInt(v(0))
' OOOOPS
' AND NOW????????????????????????????
End Function
'.......
'...More functions
'See SMI2000Hard.vb
End Class