• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

DomCR / ACadSharp / 30620456288

31 Jul 2026 09:34AM UTC coverage: 76.801% (+1.0%) from 75.789%
30620456288

Pull #1151

github

web-flow
Merge 0ffbbdb89 into 25e85fe17
Pull Request #1151: Dynamic parameters

9806 of 13766 branches covered (71.23%)

Branch coverage included in aggregate %.

2995 of 3452 new or added lines in 70 files covered. (86.76%)

74 existing lines in 12 files now uncovered.

34910 of 44457 relevant lines covered (78.53%)

142256.06 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

81.71
/src/ACadSharp/IO/DxfReader.cs
1
using ACadSharp.Classes;
2
using ACadSharp.Entities;
3
using ACadSharp.Exceptions;
4
using ACadSharp.Header;
5
using ACadSharp.IO.DXF;
6
using ACadSharp.IO.DXF.DxfStreamReader;
7
using CSUtilities.IO;
8
using CSUtilities.Text;
9
using System;
10
using System.Collections.Generic;
11
using System.Diagnostics;
12
using System.IO;
13
using System.Linq;
14
using System.Text;
15

16
namespace ACadSharp.IO
17
{
18
        /// <summary>
19
        /// Class for reading a DXF file into a <see cref="CadDocument"></see>.
20
        /// </summary>
21
        public class DxfReader : CadReaderBase<DxfReaderConfiguration>
22
        {
23
                private ACadVersion _version;
24
                private DxfDocumentBuilder _builder;
25
                private IDxfStreamReader _reader;
26

27
                /// <summary>
28
                /// Initializes a new instance of the <see cref="DxfReader"/> class
29
                /// </summary>
30
                /// <param name="filename">The file to open.</param>
31
                /// <param name="notification">Notification handler, sends any message or notification about the reading process.</param>
32
                public DxfReader(string filename, NotificationEventHandler notification = null) : base(filename, notification) { }
837✔
33

34
                /// <summary>
35
                /// Initializes a new instance of the <see cref="DxfReader"/> class
36
                /// </summary>
37
                /// <param name="stream">The stream to read from.</param>
38
                /// <param name="notification">Notification handler, sends any message or notification about the reading process.</param>
39
                public DxfReader(Stream stream, NotificationEventHandler notification = null) : base(stream, notification) { }
114✔
40

41
                /// <summary>
42
                /// Check if the file format is in binary.
43
                /// </summary>
44
                /// <returns></returns>
45
                public bool IsBinary()
46
                {
14✔
47
                        return IsBinary(this._fileStream.Stream);
14✔
48
                }
14✔
49

50
                /// <summary>
51
                /// Check if the file format is in binary.
52
                /// </summary>
53
                /// <param name="filename">Path to the dxf file.</param>
54
                /// <returns></returns>
55
                public static bool IsBinary(string filename)
56
                {
14✔
57
                        Stream stream = File.OpenRead(filename);
14✔
58
                        bool result = IsBinary(stream);
14✔
59

60
                        stream.Close();
14✔
61

62
                        return result;
14✔
63
                }
14✔
64

65
                /// <summary>
66
                /// Check if the file format is in binary.
67
                /// </summary>
68
                /// <param name="stream"></param>
69
                /// <param name="resetPos"></param>
70
                /// <returns></returns>
71
                public static bool IsBinary(Stream stream, bool resetPos = false)
72
                {
331✔
73
                        StreamIO sio = new StreamIO(stream);
331✔
74
                        sio.Position = 0;
331✔
75
                        string sn = sio.ReadString(DxfBinaryReader.Sentinel.Length);
331✔
76

77
                        bool isBinary = sn == DxfBinaryReader.Sentinel;
331✔
78

79
                        if (resetPos)
331!
80
                        {
×
81
                                stream.Position = 0;
×
82
                        }
×
83

84
                        return isBinary;
331✔
85
                }
331✔
86

87
                public static CadDocument Read(string filename, DxfReaderConfiguration configuration, NotificationEventHandler notification = null)
UNCOV
88
                {
×
UNCOV
89
                        CadDocument doc = null;
×
90

UNCOV
91
                        using (DxfReader reader = new DxfReader(filename, notification))
×
UNCOV
92
                        {
×
UNCOV
93
                                reader.Configuration = configuration;
×
UNCOV
94
                                doc = reader.Read();
×
UNCOV
95
                        }
×
96

UNCOV
97
                        return doc;
×
UNCOV
98
                }
×
99

100
                /// <summary>
101
                /// Read a dxf document in a stream
102
                /// </summary>
103
                /// <param name="stream"></param>
104
                /// <param name="notification">Notification handler, sends any message or notification about the reading process.</param>
105
                /// <returns></returns>
106
                public static CadDocument Read(Stream stream, NotificationEventHandler notification = null)
107
                {
35✔
108
                        CadDocument doc = null;
35✔
109

110
                        using (DxfReader reader = new DxfReader(stream, notification))
35✔
111
                        {
35✔
112
                                doc = reader.Read();
35✔
113
                        }
35✔
114

115
                        return doc;
35✔
116
                }
35✔
117

118
                /// <summary>
119
                /// Read a dxf document from a file
120
                /// </summary>
121
                /// <param name="filename"></param>
122
                /// <param name="notification">Notification handler, sends any message or notification about the reading process.</param>
123
                /// <returns></returns>
124
                public static CadDocument Read(string filename, NotificationEventHandler notification = null)
125
                {
35✔
126
                        return Read(File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite), notification);
35✔
127
                }
35✔
128

129
                /// <inheritdoc/>
130
                public override CadDocument Read()
131
                {
261✔
132
                        this._document.SummaryInfo = new CadSummaryInfo();
261✔
133

134
                        this._reader = this._reader ?? this.getReader();
261✔
135

136
                        this._builder = new DxfDocumentBuilder(this._version, this._document, this.Configuration);
261✔
137
                        this._builder.OnNotification += this.onNotificationEvent;
261✔
138

139
                        while (this._reader.ValueAsString != DxfFileToken.EndOfFile)
2,095✔
140
                        {
1,834✔
141
                                if (this._reader.ValueAsString != DxfFileToken.BeginSection)
1,834✔
142
                                {
261✔
143
                                        this._reader.ReadNext();
261✔
144
                                        continue;
261✔
145
                                }
146
                                else
147
                                {
1,573✔
148
                                        this._reader.ReadNext();
1,573✔
149
                                }
1,573✔
150

151
                                switch (this._reader.ValueAsString)
1,573!
152
                                {
153
                                        case DxfFileToken.HeaderSection:
154
                                                this._document.Header = this.ReadHeader();
258✔
155
                                                this._document.Header.Document = this._document;
258✔
156
                                                this._builder.InitialHandSeed = this._document.Header.HandleSeed;
258✔
157
                                                break;
258✔
158
                                        case DxfFileToken.ClassesSection:
159
                                                this.readClasses();
226✔
160
                                                break;
226✔
161
                                        case DxfFileToken.TablesSection:
162
                                                this.readTables();
258✔
163
                                                break;
258✔
164
                                        case DxfFileToken.BlocksSection:
165
                                                this.readBlocks();
258✔
166
                                                break;
258✔
167
                                        case DxfFileToken.EntitiesSection:
168
                                                this.readEntities();
261✔
169
                                                break;
261✔
170
                                        case DxfFileToken.ObjectsSection:
171
                                                this.readObjects();
226✔
172
                                                break;
226✔
173
                                        case DxfFileToken.AcdsDataSection:
174
                                                this.readAcdsData();
86✔
175
                                                break;
86✔
176
                                        default:
177
                                                this.triggerNotification(($"Section not implemented {this._reader.ValueAsString}"), NotificationType.NotImplemented);
×
178
                                                break;
×
179
                                }
180

181
                                this._reader.ReadNext();
1,573✔
182
                        }
1,573✔
183

184
                        if (this._document.Header == null)
261✔
185
                        {
3✔
186
                                this._document.Header = new CadHeader(this._document);
3✔
187
                        }
3✔
188

189
                        this._builder.BuildDocument();
261✔
190

191
                        return this._document;
261✔
192
                }
261✔
193

194
                /// <inheritdoc/>
195
                public override CadHeader ReadHeader()
196
                {
272✔
197
                        this._reader = this.goToSection(DxfFileToken.HeaderSection);
272✔
198

199
                        CadHeader header = new CadHeader();
272✔
200

201
                        Dictionary<string, CadSystemVariable> headerMap = CadHeader.GetHeaderMap();
272✔
202

203
                        this._reader.ReadNext();
272✔
204

205
                        //Loop until the section ends
206
                        while (this._reader.ValueAsString != DxfFileToken.EndSection)
61,942✔
207
                        {
61,670✔
208
                                //Get the current header variable
209
                                string currVar = this._reader.ValueAsString;
61,670✔
210

211
                                if (this._reader.ValueAsString == null || !headerMap.TryGetValue(currVar, out CadSystemVariable data))
61,670!
212
                                {
5,716✔
213
#if TEST
214
                                        this.triggerNotification($"Header variable not implemented {currVar}", NotificationType.NotImplemented);
215
#endif
216
                                        this._reader.ReadNext();
5,716✔
217
                                        continue;
5,716✔
218
                                }
219

220
                                object[] parameters = new object[data.DxfCodes.Length];
55,954✔
221
                                for (int i = 0; i < data.DxfCodes.Length; i++)
249,136✔
222
                                {
68,614✔
223
                                        this._reader.ReadNext();
68,614✔
224

225
                                        if (this._reader.DxfCode == DxfCode.CLShapeText || this._reader.DxfCode == DxfCode.Start)
68,614!
226
                                        {
×
227
                                                //Irregular dxf files may not follow the header type
228
                                                int c = data.DxfCodes[i];
×
229
                                                GroupCodeValueType g = GroupCodeValue.TransformValue(c);
×
230
                                                switch (g)
×
231
                                                {
232
                                                        case GroupCodeValueType.Bool:
233
                                                                parameters[i] = false;
×
234
                                                                break;
×
235
                                                        case GroupCodeValueType.Byte:
236
                                                        case GroupCodeValueType.Int16:
237
                                                        case GroupCodeValueType.Int32:
238
                                                        case GroupCodeValueType.Int64:
239
                                                        case GroupCodeValueType.Double:
240
                                                        case GroupCodeValueType.Point3D:
241
                                                                parameters[i] = 0;
×
242
                                                                break;
×
243
                                                        case GroupCodeValueType.None:
244
                                                        case GroupCodeValueType.String:
245
                                                        default:
246
                                                                parameters[i] = default;
×
247
                                                                break;
×
248
                                                }
249

250
                                                break;
×
251
                                        }
252

253
                                        parameters[i] = this._reader.Value;
68,614✔
254
                                }
68,614✔
255

256
                                try
257
                                {
55,954✔
258
                                        //Set the header value by name
259
                                        header.SetValue(currVar, parameters);
55,954✔
260
                                }
55,954✔
261
                                catch (Exception ex)
×
262
                                {
×
263
                                        this.triggerNotification($"Invalid value for header variable {currVar} | {parameters.FirstOrDefault()}", NotificationType.Warning, ex);
×
264
                                }
×
265

266
                                if (this._reader.DxfCode != DxfCode.CLShapeText && this._reader.DxfCode != DxfCode.Start)
55,954!
267
                                {
55,954✔
268
                                        this._reader.ReadNext();
55,954✔
269
                                }
55,954✔
270
                        }
55,954✔
271

272
                        return header;
272✔
273
                }
272✔
274

275
                /// <summary>
276
                /// Read only the tables section in the dxf document
277
                /// </summary>
278
                /// <remarks>
279
                /// The <see cref="CadDocument"/> will not contain any entity, only the tables and it's records
280
                /// </remarks>
281
                /// <returns></returns>
282
                public CadDocument ReadTables()
283
                {
14✔
284
                        this._reader = this._reader ?? this.getReader();
14✔
285

286
                        this._builder = new DxfDocumentBuilder(this._version, this._document, this.Configuration);
14✔
287
                        this._builder.OnNotification += this.onNotificationEvent;
14✔
288

289
                        this.readTables();
14✔
290

291
                        this._document.Header = new CadHeader(this._document);
14✔
292

293
                        this._builder.RegisterTables();
14✔
294

295
                        this._builder.BuildTables();
14✔
296

297
                        return this._document;
14✔
298
                }
14✔
299

300
                /// <summary>
301
                /// Read only the entities section in the dxf document
302
                /// </summary>
303
                /// <remarks>
304
                /// The entities will be completely independent from each other and linetypes and layers will only have it's name set, all the other properties will be set as default
305
                /// </remarks>
306
                /// <returns></returns>
307
                public List<Entity> ReadEntities()
308
                {
14✔
309
                        this._reader = this._reader ?? this.getReader();
14✔
310

311
                        this._builder = new DxfDocumentBuilder(this._version, this._document, this.Configuration);
14✔
312
                        this._builder.OnNotification += this.onNotificationEvent;
14✔
313

314
                        this.readEntities();
14✔
315

316
                        return this._builder.BuildEntities();
14✔
317
                }
14✔
318

319
                /// <inheritdoc/>
320
                public override void Dispose()
321
                {
317✔
322
                        base.Dispose();
317✔
323

324
                        if (this.Configuration.ClearCache)
317✔
325
                        {
317✔
326
                                DxfMap.ClearCache();
317✔
327
                        }
317✔
328
                }
317✔
329

330
                #region DxfClasses
331

332
                /// <summary>
333
                /// Read the CLASSES section of the DXF file.
334
                /// </summary>
335
                /// <returns></returns>
336
                private DxfClassCollection readClasses()
337
                {
226✔
338
                        //Get the needed handler
339
                        this._reader = this.goToSection(DxfFileToken.ClassesSection);
226✔
340

341
                        DxfClassCollection classes = this._document.Classes;
226✔
342

343
                        //Advance to the first value in the section
344
                        this._reader.ReadNext();
226✔
345
                        //Loop until the section ends
346
                        while (this._reader.ValueAsString != DxfFileToken.EndSection)
10,788✔
347
                        {
10,562✔
348
                                if (this._reader.ValueAsString == DxfFileToken.ClassEntry)
10,562!
349
                                {
10,562✔
350
                                        var dxfClass = this.readClass();
10,562✔
351

352
                                        if (dxfClass.ClassNumber < 500)
10,562✔
353
                                        {
10,562✔
354
                                                dxfClass.ClassNumber = (short)(500 + classes.Count);
10,562✔
355
                                        }
10,562✔
356

357
                                        classes.AddOrUpdate(dxfClass);
10,562✔
358
                                }
10,562✔
359
                                else
360
                                        this._reader.ReadNext();
×
361
                        }
10,562✔
362

363
                        return classes;
226✔
364
                }
226✔
365

366
                private DxfClass readClass()
367
                {
10,562✔
368
                        DxfClass curr = new DxfClass();
10,562✔
369

370
                        Debug.Assert(this._reader.ValueAsString == DxfFileToken.ClassEntry);
10,562✔
371

372
                        this._reader.ReadNext();
10,562✔
373
                        //Loop until the next class or the end of the section
374
                        while (this._reader.DxfCode != DxfCode.Start)
82,778✔
375
                        {
72,216✔
376
                                switch (this._reader.Code)
72,216✔
377
                                {
378
                                        //Class DXF record name; always unique
379
                                        case 1:
380
                                                curr.DxfName = this._reader.ValueAsString;
10,562✔
381
                                                break;
10,562✔
382
                                        //C++ class name. Used to bind with software that defines object class behavior; always unique
383
                                        case 2:
384
                                                curr.CppClassName = this._reader.ValueAsString;
10,562✔
385
                                                break;
10,562✔
386
                                        //Application name. Posted in Alert box when a class definition listed in this section is not currently loaded
387
                                        case 3:
388
                                                curr.ApplicationName = this._reader.ValueAsString;
10,562✔
389
                                                break;
10,562✔
390
                                        //Proxy capabilities flag.
391
                                        case 90:
392
                                                curr.ProxyFlags = (ProxyFlags)(ushort)this._reader.ValueAsInt;
10,562✔
393
                                                break;
10,562✔
394
                                        //Instance count for a custom class
395
                                        case 91:
396
                                                curr.InstanceCount = this._reader.ValueAsInt;
8,844✔
397
                                                break;
8,844✔
398
                                        //Was-a-proxy flag. Set to 1 if class was not loaded when this DXF file was created, and 0 otherwise
399
                                        case 280:
400
                                                curr.WasZombie = this._reader.ValueAsBool;
10,562✔
401
                                                break;
10,562✔
402
                                        //Is - an - entity flag.
403
                                        case 281:
404
                                                curr.IsAnEntity = this._reader.ValueAsBool;
10,562✔
405
                                                break;
10,562✔
406
                                        default:
407
                                                break;
×
408
                                }
409

410
                                this._reader.ReadNext();
72,216✔
411
                        }
72,216✔
412

413
                        return curr;
10,562✔
414
                }
10,562✔
415

416
                #endregion
417

418
                #region Tables
419

420
                private void readTables()
421
                {
272✔
422
                        //Get the needed handler
423
                        this._reader = this.goToSection(DxfFileToken.TablesSection);
272✔
424

425
                        DxfTablesSectionReader reader = new DxfTablesSectionReader(this._reader, this._builder);
272✔
426

427
                        reader.Read();
272✔
428
                }
272✔
429

430
                #endregion
431

432
                /// <summary>
433
                /// Read the BLOCKS section of the DXF file.
434
                /// </summary>
435
                private void readBlocks()
436
                {
258✔
437
                        //Get the needed handler
438
                        this._reader = this.goToSection(DxfFileToken.BlocksSection);
258✔
439

440
                        DxfBlockSectionReader reader = new DxfBlockSectionReader(this._reader, this._builder);
258✔
441

442
                        reader.Read();
258✔
443
                }
258✔
444

445
                /// <summary>
446
                /// Read the ENTITIES section of the DXF file.
447
                /// </summary>
448
                private void readEntities()
449
                {
275✔
450
                        //Get the needed handler
451
                        this._reader = this.goToSection(DxfFileToken.EntitiesSection);
275✔
452

453
                        DxfEntitiesSectionReader reader = new DxfEntitiesSectionReader(this._reader, this._builder);
275✔
454

455
                        reader.Read();
275✔
456
                }
275✔
457

458
                /// <summary>
459
                /// Read the OBJECTS section of the DXF file.
460
                /// </summary>
461
                private void readObjects()
462
                {
226✔
463
                        //Get the needed handler
464
                        this._reader = this.goToSection(DxfFileToken.ObjectsSection);
226✔
465

466
                        DxfObjectsSectionReader reader = new DxfObjectsSectionReader(this._reader, this._builder);
226✔
467

468
                        reader.Read();
226✔
469
                }
226✔
470

471
                /// <summary>
472
                /// Read the ACDSDATA section of the DXF file.
473
                /// </summary>
474
                /// <remarks>
475
                /// R2013+ files store the ACIS payload of the modeler geometry entities
476
                /// (3DSOLID, REGION, BODY) in this section instead of embedding it in the
477
                /// entity codes.
478
                /// </remarks>
479
                private void readAcdsData()
480
                {
86✔
481
                        //Get the needed handler
482
                        this._reader = this.goToSection(DxfFileToken.AcdsDataSection);
86✔
483

484
                        DxfAcdsDataSectionReader reader = new DxfAcdsDataSectionReader(this._reader, this._builder);
86✔
485

486
                        reader.Read();
86✔
487
                }
86✔
488

489
                /// <summary>
490
                /// Read the THUMBNAILIMAGE section of the DXF file.
491
                /// </summary>
492
                private void readThumbnailImage()
493
                {
×
494
                        throw new NotImplementedException();
×
495
                }
496

497
                private IDxfStreamReader getReader()
498
                {
303✔
499
                        IDxfStreamReader tmpReader = null;
303✔
500
                        this._version = ACadVersion.Unknown;
303✔
501

502
                        bool isBinary = IsBinary(this._fileStream.Stream, false);
303✔
503
                        bool isAC1009Format = false;
303✔
504

505
                        if (isBinary && this._fileStream.Stream.ReadByte() != -1)
303✔
506
                        {
125✔
507
                                int flag = this._fileStream.ReadByte();
125✔
508
                                if (flag != -1 && flag != 0)
125!
509
                                {
17✔
510
                                        isAC1009Format = true;
17✔
511
                                }
17✔
512
                        }
125✔
513

514
                        tmpReader = this.createReader(isBinary, isAC1009Format);
303✔
515

516
                        if (!tmpReader.Find(DxfFileToken.HeaderSection))
303✔
517
                        {
3✔
518
                                this.triggerNotification($"Header section not found, using a generic reader.", NotificationType.Warning);
3✔
519

520
                                this._version = ACadVersion.Unknown;
3✔
521
                                tmpReader.Start();
3✔
522
                                return tmpReader;
3✔
523
                        }
524

525
                        while (tmpReader.ValueAsString != DxfFileToken.EndSection)
47,570✔
526
                        {
47,452✔
527
                                if (tmpReader.ValueAsString == "$ACADVER")
47,452✔
528
                                {
300✔
529
                                        tmpReader.ReadNext();
300✔
530
                                        this._version = CadUtils.GetVersionFromName(tmpReader.ValueAsString);
300✔
531
                                        if (this._version >= ACadVersion.AC1021)
300✔
532
                                        {
182✔
533
                                                this._encoding = Encoding.UTF8;
182✔
534
                                                break;
182✔
535
                                        }
536

537
                                        if (this._version < ACadVersion.AC1002)
118!
538
                                        {
×
539
                                                if (this._version == ACadVersion.Unknown)
×
540
                                                {
×
541
                                                        throw new CadNotSupportedException();
×
542
                                                }
543
                                                else
544
                                                {
×
545
                                                        throw new CadNotSupportedException(this._version);
×
546
                                                }
547
                                        }
548
                                }
118✔
549
                                else if (tmpReader.ValueAsString == "$DWGCODEPAGE")
47,152✔
550
                                {
88✔
551
                                        tmpReader.ReadNext();
88✔
552

553
                                        string encoding = tmpReader.ValueAsString;
88✔
554

555
                                        CodePage code = CadUtils.GetCodePage(encoding.ToLower());
88✔
556
                                        this._encoding = this.getListedEncoding((int)code);
88✔
557
                                }
88✔
558

559
                                tmpReader.ReadNext();
47,270✔
560
                        }
47,270✔
561

562
                        if (this._version == ACadVersion.Unknown)
300!
563
                        {
×
564
                                this.triggerNotification($"Dxf version not found, using a generic reader.", NotificationType.Warning);
×
565
                        }
×
566

567
                        return this.createReader(isBinary, isAC1009Format);
300✔
568
                }
303✔
569

570
                private IDxfStreamReader goToSection(string sectionName)
571
                {
1,615✔
572
                        //Get the needed handler
573
                        this._reader = this._reader ?? this.getReader();
1,615✔
574

575
                        if (this._reader.ValueAsString == sectionName)
1,615✔
576
                                return this._reader;
1,573✔
577

578
                        //Go to the start of header section
579
                        this._reader.Find(sectionName);
42✔
580

581
                        return this._reader;
42✔
582
                }
1,615✔
583

584
                private IDxfStreamReader createReader(bool isBinary, bool isAC1009Format)
585
                {
603✔
586
                        Encoding encoding = this._encoding;
603✔
587
                        if (encoding == null)
603!
588
                        {
×
589
                                encoding = Encoding.ASCII;
×
590
                        }
×
591

592
                        if (isBinary)
603✔
593
                        {
250✔
594
                                if (isAC1009Format)
250✔
595
                                {
34✔
596
                                        return new DxfBinaryReaderAC1009(this._fileStream.Stream, encoding);
34✔
597
                                }
598
                                else
599
                                {
216✔
600
                                        return new DxfBinaryReader(this._fileStream.Stream, encoding);
216✔
601
                                }
602
                        }
603
                        else
604
                        {
353✔
605
                                return new DxfTextReader(this._fileStream.Stream, encoding);
353✔
606
                        }
607
                }
603✔
608
        }
609
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc