Task 161: .DXF File Format

Task 161: .DXF File Format

File Format Specifications for the .DXF File Format

The .DXF (Drawing Exchange Format) is a CAD data file format developed by Autodesk to facilitate interoperability between AutoCAD and other applications. It supports both ASCII (text-based) and binary variants, though the ASCII version is more common. The format represents drawing data using tagged groups, where each group consists of an integer code followed by a value. The structure is organized into sections, each beginning with group code 0 and "SECTION", followed by group code 2 with the section name, and ending with 0 and "ENDSEC". Key sections include HEADER (drawing settings), CLASSES (application-defined classes), TABLES (symbol tables like layers and styles), BLOCKS (block definitions), ENTITIES (graphical objects), OBJECTS (non-graphical objects), THUMBNAILIMAGE (preview image, optional), and EOF (end of file marker).

Official specifications are documented in Autodesk's DXF Reference, available in versions corresponding to AutoCAD releases. For example, the AutoCAD 2012 DXF Reference PDF provides detailed group codes, entity types, and section structures. More recent versions, such as for AutoCAD 2025, are accessible via Autodesk's online developer help.

1. List of All Properties of the .DXF File Format Intrinsic to Its File System

Based on the specifications, the properties intrinsic to the .DXF format are the header variables stored in the HEADER section. These variables define drawing settings and are represented as system variables prefixed with "$". Each variable is associated with a group code and a value, capturing aspects such as version, units, dimensions, and display options. The following table lists all identified header variables, their associated group codes (where specified in references), and descriptions. Note that group codes may vary by context, but typical codes are provided for reference.

Variable Name Group Code Description
$ACADVER 1 The AutoCAD drawing database version number (e.g., AC1006 = R10, AC1009 = R11 and R12).
$ANGBASE 50 Angle 0 direction.
$ANGDIR 70 1 = clockwise angles, 0 = counterclockwise.
$ATTDIA 70 Attribute entry dialogs, 1 = on, 0 = off.
$ATTMODE 70 Attribute visibility: 0 = none, 1 = normal, 2 = all.
$ATTREQ 70 Attribute prompting during INSERT, 1 = on, 0 = off.
$AUNITS 70 Units format for angles.
$AUPREC 70 Units precision for angles.
$AXISMODE 70 Axis on if nonzero (not functional in Release 12).
$AXISUNIT 10, 20 Axis X and Y tick spacing (not functional in Release 12).
$BLIPMODE 70 Blip mode on if nonzero.
$CECOLOR 62 Entity color number; 0 = BYBLOCK, 256 = BYLAYER.
$CELTYPE 6 Entity linetype name, or BYBLOCK or BYLAYER.
$CHAMFERA 40 First chamfer distance.
$CHAMFERB 40 Second chamfer distance.
$CLAYER 8 Current layer name.
$COORDS 70 0 = static coordinate display, 1 = continuous update, 2 = “d<a” format.
$DIMALT 70 Alternate unit dimensioning performed if nonzero.
$DIMALTD 70 Alternate unit decimal places.
$DIMALTF 40 Alternate unit scale factor.
$DIMAPOST 1 Alternate dimensioning suffix.
$DIMASO 70 1 = create associative dimensioning, 0 = draw individual entities.
$DIMASZ 40 Dimensioning arrow size.
$DIMBLK 1 Arrow block name.
$DIMBLK1 1 First arrow block name.
$DIMBLK2 1 Second arrow block name.
$DIMCEN 40 Size of center mark/lines.
$DIMCLRD 70 Dimension line color, range is 0 = BYBLOCK, 256 = BYLAYER.
$DIMCLRE 70 Dimension extension line color, range is 0 = BYBLOCK, 256 = BYLAYER.
$DIMCLRT 70 Dimension text color, range is 0 = BYBLOCK, 256 = BYLAYER.
$DIMDLE 40 Dimension line extension.
$DIMDLI 40 Dimension line increment.
$DIMEXE 40 Extension line extension.
$DIMEXO 40 Extension line offset.
$DIMGAP 40 Dimension line gap.
$DIMLFAC 40 Linear measurements scale factor.
$DIMLIM 70 Dimension limits generated if nonzero.
$DIMPOST 1 General dimensioning suffix.
$DIMRND 40 Rounding value for dimension distances.
$DIMSAH 70 Use separate arrow blocks if nonzero.
$DIMSCALE 40 Overall dimensioning scale factor.
$DIMSE1 70 First extension line suppressed if nonzero.
$DIMSE2 70 Second extension line suppressed if nonzero.
$DIMSHO 70 1 = Recompute dimensions while dragging, 0 = drag original image.
$DIMSOXD 70 Suppress outside-extensions dimension lines if nonzero.
$DIMSTYLE 2 Dimension style name.
$DIMTAD 70 Text above dimension line if nonzero.
$DIMTFAC 40 Dimension tolerance display scale factor.
$DIMTIH 70 Text inside horizontal if nonzero.
$DIMTIX 70 Force text inside extensions if nonzero.
$DIMTM 40 Minus tolerance.
$DIMTOFL 70 If text outside extensions, force line extensions between extensions if nonzero.
$DIMTOH 70 Text outside horizontal if nonzero.
$DIMTOL 70 Dimension tolerances generated if nonzero.
$DIMTP 40 Plus tolerance.
$DIMTSZ 40 Dimensioning tick size: 0 = no ticks.
$DIMTVP 40 Text vertical position.

This list is derived from established references and represents properties extractable from the file's HEADER section.

3. Ghost Blog Embedded HTML JavaScript for Drag-and-Drop .DXF File Processing

The following is a standalone HTML page with embedded JavaScript that can be embedded in a Ghost blog post or used independently. It allows users to drag and drop a .DXF file, parses the HEADER section to extract the properties (header variables), and displays them on the screen in a structured list.

DXF Header Properties Viewer

Drag and Drop .DXF File to View Header Properties

Drop .DXF file here

4. Python Class for .DXF File Handling

The following Python class can open a .DXF file, decode and read the header properties, print them to the console, and write the file (with optional modifications to properties).

import os

class DXFHandler:
    def __init__(self, filepath):
        self.filepath = filepath
        self.properties = {}
        self.content = None

    def read(self):
        with open(self.filepath, 'r') as f:
            self.content = f.read()
        lines = self.content.split('\n')
        in_header = False
        current_var = None
        i = 0
        while i < len(lines):
            line = lines[i].strip()
            if line == '0' and i+1 < len(lines) and lines[i+1].strip() == 'SECTION' and \
               i+3 < len(lines) and lines[i+3].strip() == 'HEADER':
                in_header = True
                i += 4
                continue
            if in_header and line == '0' and i+1 < len(lines) and lines[i+1].strip() == 'ENDSEC':
                break
            if in_header and line == '9':
                if i+1 < len(lines):
                    current_var = lines[i+1].strip()
                i += 2
            elif current_var:
                if i < len(lines):
                    self.properties[current_var] = lines[i].strip()
                current_var = None
                i += 1
            else:
                i += 1

    def print_properties(self):
        if not self.properties:
            print("No properties found. Call read() first.")
            return
        for key, value in self.properties.items():
            print(f"{key}: {value}")

    def write(self, output_path=None, modify=None):
        if not self.content:
            print("No content to write. Call read() first.")
            return
        if output_path is None:
            output_path = self.filepath
        content_lines = self.content.split('\n')
        if modify:
            for key, new_value in modify.items():
                if key in self.properties:
                    self.properties[key] = new_value
                    # Update in content (simple replace for demo; full parser for production)
                    for i in range(len(content_lines)):
                        if content_lines[i].strip() == '9' and i+1 < len(content_lines) and content_lines[i+1].strip() == key:
                            # Next is code, then value
                            i += 2
                            if i+1 < len(content_lines):
                                content_lines[i+1] = str(new_value)
        with open(output_path, 'w') as f:
            f.write('\n'.join(content_lines))

# Example usage:
# handler = DXFHandler('sample.dxf')
# handler.read()
# handler.print_properties()
# handler.write('output.dxf', modify={'$ACADVER': 'AC1027'})

5. Java Class for .DXF File Handling

The following Java class can open a .DXF file, decode and read the header properties, print them to the console, and write the file (with optional modifications).

import java.io.*;
import java.util.HashMap;
import java.util.Map;

public class DXFHandler {
    private String filepath;
    private Map<String, String> properties = new HashMap<>();
    private String content;

    public DXFHandler(String filepath) {
        this.filepath = filepath;
    }

    public void read() throws IOException {
        BufferedReader reader = new BufferedReader(new FileReader(filepath));
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            sb.append(line).append("\n");
        }
        content = sb.toString();
        reader.close();

        String[] lines = content.split("\n");
        boolean inHeader = false;
        String currentVar = null;
        for (int i = 0; i < lines.length; i++) {
            String trimmed = lines[i].trim();
            if (trimmed.equals("0") && i + 3 < lines.length && lines[i + 3].trim().equals("HEADER")) {
                inHeader = true;
                i += 3;
                continue;
            }
            if (inHeader && trimmed.equals("0") && i + 1 < lines.length && lines[i + 1].trim().equals("ENDSEC")) {
                break;
            }
            if (inHeader && trimmed.equals("9")) {
                if (i + 1 < lines.length) {
                    currentVar = lines[i + 1].trim();
                }
                i++;
            } else if (currentVar != null) {
                if (i + 1 < lines.length) {
                    properties.put(currentVar, lines[i + 1].trim());
                }
                currentVar = null;
                i++;
            }
        }
    }

    public void printProperties() {
        if (properties.isEmpty()) {
            System.out.println("No properties found. Call read() first.");
            return;
        }
        for (Map.Entry<String, String> entry : properties.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }
    }

    public void write(String outputPath, Map<String, String> modify) throws IOException {
        if (content == null) {
            System.out.println("No content to write. Call read() first.");
            return;
        }
        if (outputPath == null) {
            outputPath = filepath;
        }
        String[] lines = content.split("\n");
        if (modify != null) {
            for (Map.Entry<String, String> mod : modify.entrySet()) {
                String key = mod.getKey();
                String newValue = mod.getValue();
                if (properties.containsKey(key)) {
                    properties.put(key, newValue);
                    for (int i = 0; i < lines.length; i++) {
                        if (lines[i].trim().equals("9") && i + 1 < lines.length && lines[i + 1].trim().equals(key)) {
                            i += 2;
                            if (i + 1 < lines.length) {
                                lines[i + 1] = newValue;
                            }
                        }
                    }
                }
            }
        }
        BufferedWriter writer = new BufferedWriter(new FileWriter(outputPath));
        for (String l : lines) {
            writer.write(l + "\n");
        }
        writer.close();
    }

    // Example usage:
    // public static void main(String[] args) throws IOException {
    //     DXFHandler handler = new DXFHandler("sample.dxf");
    //     handler.read();
    //     handler.printProperties();
    //     Map<String, String> modify = new HashMap<>();
    //     modify.put("$ACADVER", "AC1027");
    //     handler.write("output.dxf", modify);
    // }
}

6. JavaScript Class for .DXF File Handling

The following JavaScript class (Node.js compatible, requiring 'fs' module) can open a .DXF file, decode and read the header properties, print them to the console, and write the file (with optional modifications).

const fs = require('fs');

class DXFHandler {
    constructor(filepath) {
        this.filepath = filepath;
        this.properties = {};
        this.content = null;
    }

    read() {
        this.content = fs.readFileSync(this.filepath, 'utf8');
        const lines = this.content.split('\n').map(line => line.trim());
        let inHeader = false;
        let currentVar = null;
        for (let i = 0; i < lines.length; i++) {
            if (lines[i] === '0' && lines[i+1] === 'SECTION' && lines[i+3] === 'HEADER') {
                inHeader = true;
                i += 3;
                continue;
            }
            if (inHeader && lines[i] === '0' && lines[i+1] === 'ENDSEC') {
                break;
            }
            if (inHeader && lines[i] === '9') {
                currentVar = lines[i+1];
                i++;
            } else if (currentVar) {
                this.properties[currentVar] = lines[i+1] || 'undefined';
                currentVar = null;
                i++;
            }
        }
    }

    printProperties() {
        if (Object.keys(this.properties).length === 0) {
            console.log('No properties found. Call read() first.');
            return;
        }
        for (const [key, value] of Object.entries(this.properties)) {
            console.log(`${key}: ${value}`);
        }
    }

    write(outputPath = null, modify = null) {
        if (!this.content) {
            console.log('No content to write. Call read() first.');
            return;
        }
        if (!outputPath) {
            outputPath = this.filepath;
        }
        let lines = this.content.split('\n');
        if (modify) {
            for (const [key, newValue] of Object.entries(modify)) {
                if (key in this.properties) {
                    this.properties[key] = newValue;
                    for (let i = 0; i < lines.length; i++) {
                        if (lines[i].trim() === '9' && lines[i+1].trim() === key) {
                            i += 2;
                            if (i+1 < lines.length) {
                                lines[i+1] = newValue;
                            }
                        }
                    }
                }
            }
        }
        fs.writeFileSync(outputPath, lines.join('\n'));
    }
}

// Example usage:
// const handler = new DXFHandler('sample.dxf');
// handler.read();
// handler.printProperties();
// handler.write('output.dxf', { '$ACADVER': 'AC1027' });

7. C++ Class for .DXF File Handling

The following C++ class can open a .DXF file, decode and read the header properties, print them to the console, and write the file (with optional modifications). Compile with a C++ compiler (e.g., g++).

#include <iostream>
#include <fstream>
#include <string>
#include <map>
#include <vector>
#include <algorithm>

class DXFHandler {
private:
    std::string filepath;
    std::map<std::string, std::string> properties;
    std::string content;

public:
    DXFHandler(const std::string& fp) : filepath(fp) {}

    void read() {
        std::ifstream file(filepath);
        if (!file.is_open()) {
            std::cerr << "Error opening file." << std::endl;
            return;
        }
        std::string line;
        while (std::getline(file, line)) {
            content += line + "\n";
        }
        file.close();

        std::vector<std::string> lines;
        size_t pos = 0;
        std::string token;
        while ((pos = content.find("\n")) != std::string::npos) {
            token = content.substr(0, pos);
            lines.push_back(token.erase(token.find_last_not_of("\r\n") + 1));
            content.erase(0, pos + 1);
        }

        bool inHeader = false;
        std::string currentVar;
        for (size_t i = 0; i < lines.size(); ++i) {
            std::string trimmed = lines[i];
            trimmed.erase(std::remove_if(trimmed.begin(), trimmed.end(), isspace), trimmed.end());
            if (trimmed == "0" && i + 3 < lines.size() && lines[i + 3] == "HEADER") {
                inHeader = true;
                i += 3;
                continue;
            }
            if (inHeader && trimmed == "0" && i + 1 < lines.size() && lines[i + 1] == "ENDSEC") {
                break;
            }
            if (inHeader && trimmed == "9") {
                if (i + 1 < lines.size()) {
                    currentVar = lines[i + 1];
                    currentVar.erase(std::remove_if(currentVar.begin(), currentVar.end(), isspace), currentVar.end());
                }
                ++i;
            } else if (!currentVar.empty()) {
                if (i + 1 < lines.size()) {
                    std::string value = lines[i + 1];
                    value.erase(std::remove_if(value.begin(), value.end(), isspace), value.end());
                    properties[currentVar] = value;
                }
                currentVar.clear();
                ++i;
            }
        }
    }

    void printProperties() const {
        if (properties.empty()) {
            std::cout << "No properties found. Call read() first." << std::endl;
            return;
        }
        for (const auto& pair : properties) {
            std::cout << pair.first << ": " << pair.second << std::endl;
        }
    }

    void write(const std::string& outputPath = "", const std::map<std::string, std::string>& modify = {}) {
        std::string out = outputPath.empty() ? filepath : outputPath;
        if (content.empty()) {
            std::cout << "No content to write. Call read() first." << std::endl;
            return;
        }
        std::vector<std::string> lines;
        std::string tempContent = content;
        size_t pos;
        while ((pos = tempContent.find("\n")) != std::string::npos) {
            lines.push_back(tempContent.substr(0, pos));
            tempContent.erase(0, pos + 1);
        }

        for (const auto& mod : modify) {
            std::string key = mod.first;
            std::string newValue = mod.second;
            if (properties.find(key) != properties.end()) {
                properties[key] = newValue;
                for (size_t i = 0; i < lines.size(); ++i) {
                    std::string trimmed = lines[i];
                    trimmed.erase(std::remove_if(trimmed.begin(), trimmed.end(), isspace), trimmed.end());
                    if (trimmed == "9" && i + 1 < lines.size() && lines[i + 1] == key) {
                        i += 2;
                        if (i + 1 < lines.size()) {
                            lines[i + 1] = newValue;
                        }
                    }
                }
            }
        }

        std::ofstream outfile(out);
        if (!outfile.is_open()) {
            std::cerr << "Error writing file." << std::endl;
            return;
        }
        for (const auto& l : lines) {
            outfile << l << "\n";
        }
        outfile.close();
    }
};

// Example usage:
// int main() {
//     DXFHandler handler("sample.dxf");
//     handler.read();
//     handler.printProperties();
//     std::map<std::string, std::string> modify = {{"$ACADVER", "AC1027"}};
//     handler.write("output.dxf", modify);
//     return 0;
// }