Task 715: .SYLK File Format

Task 715: .SYLK File Format

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

The .SYLK (Symbolic Link) file format is a text-based, ANSI-encoded format primarily used for spreadsheet data interchange. It is not intrinsically tied to specific file system attributes beyond standard text file handling (e.g., no binary headers or magic numbers, as it relies on readable ASCII content). However, the format's core properties include its structural elements, such as record types and associated fields, which define its organization and content. Based on the specifications from reliable sources, including detailed format descriptions, the key properties are the record types and their common parameters. These are intrinsic to the format's parsing and representation on any file system supporting text files.

The list of properties (record types) is as follows:

  • ID (Identification): Specifies the file header, including the program name (e.g., ;P). Optional fields: ;N (protection style), ;E (external references).
  • B (Bounds): Defines spreadsheet dimensions. Fields: ;X (number of columns), ;Y (number of rows).
  • C (Cell Content): Describes cell data at a position. Fields: ;X (column), ;Y (row), ;K (value, numeric or quoted string), ;E (formula/expression), ;G (shared value), ;D (shared expression), ;M (matrix), ;H (hidden), ;N (unprotected), ;P (protected), ;C/;R (references), ;S (shared reference).
  • F (Formatting): Applies display formats to cells, rows, columns, or the sheet. Fields: ;P (format index), ;F (format code, e.g., F for fixed, with digits and alignment like L/R/C), ;W (column width, e.g., ;W   ), ;S (style, e.g., B for bold), ;C/;R/;X/;Y (targets), ;G (gridlines), ;H (headers), ;E (formulas), ;K (commas).
  • P (Format Definition): Defines custom number formats and fonts. Fields: ;P (format string, e.g., for currency or dates), ;F (font), ;M (font size in 1/20 points), ;L (color), ;S (style).
  • O (Options): Sets global behaviors. Fields: ;V (date system, 0 for 1900 or 4 for 1904), ;M (calculation mode), ;L (reference style), ;P (protection).
  • NN (Name Definition): Defines named ranges. Fields: ;N (name), ;E (expression for range).
  • NE (Name External Reference): Links to external spreadsheets. Fields: ;F (filename), ;S (source name/range), ;E (expression).
  • NV (Name Substitution): Maps filenames. Fields: ;L (original), ;F (substitute).
  • W (Window Structure): Defines window properties. Fields: ;N (window number), ;A (coordinates), ;B (border), ;ST (split with title), ;SH (horizontal split), ;SV (vertical split).
  • E (End): Marks the file termination (no fields).

Additional format-level properties:

  • File extension: .slk
  • MIME type: application/x-sylk
  • Encoding: ANSI/ASCII (displayable characters only)
  • Structure: Line-based records separated by CRLF (\r\n), with semicolon-delimited fields (escaped semicolons as ;;)
  • Line length limit: Typically ≤ 260 characters
  • Starting record: Must begin with ID
  • Ending record: Must end with E

These properties ensure compatibility across file systems, as the format is plain text and platform-independent.

The following are direct download links to sample .SYLK (.slk) files hosted on GitHub repositories. These are raw file URLs, which allow immediate download without intermediary pages:

3. Ghost Blog Embedded HTML JavaScript for Drag-and-Drop .SYLK File Parsing

The following is a self-contained HTML snippet with embedded JavaScript suitable for embedding in a Ghost blog post (or any HTML environment). It creates a drag-and-drop area where users can drop a .SYLK file. The script reads the file as text, parses each record according to the format specifications, extracts the properties (record types and fields), and displays them on the screen in a structured, readable format.

Drag and drop a .SYLK file here


This script handles file reading via FileReader, parses records by splitting on semicolons (unescaping embedded semicolons), and outputs the properties in a pre-formatted block.

4. Python Class for .SYLK File Handling

The following Python class implements functionality to open, decode (parse), read, write, and print the properties of a .SYLK file to the console. It parses the file into a list of records and fields, prints them, and can write the parsed structure back to a new file.

import os

class SylkHandler:
    def __init__(self, filename):
        self.filename = filename
        self.properties = []  # List of dicts: {'record_type': str, 'fields': list[str]}

    def read_and_decode(self):
        if not os.path.exists(self.filename):
            raise FileNotFoundError(f"File {self.filename} not found.")
        with open(self.filename, 'r', encoding='ansi') as file:
            content = file.read()
        lines = content.splitlines()
        for line in lines:
            if line.strip():
                parts = line.split(';')
                parts = [part.replace(';;', ';') for part in parts]
                record_type = parts[0]
                fields = [field.strip() for field in parts[1:]]
                self.properties.append({'record_type': record_type, 'fields': fields})

    def print_properties(self):
        if not self.properties:
            print("No properties loaded. Call read_and_decode() first.")
            return
        print("SYLK Properties:")
        for idx, prop in enumerate(self.properties, 1):
            print(f"Record {idx}: Type = {prop['record_type']}")
            for f_idx, field in enumerate(prop['fields'], 1):
                print(f"  Field {f_idx}: {field}")
            print()

    def write(self, output_filename):
        if not self.properties:
            raise ValueError("No properties to write. Call read_and_decode() first.")
        with open(output_filename, 'w', encoding='ansi') as file:
            for prop in self.properties:
                fields_str = ';'.join([field.replace(';', ';;') for field in prop['fields']])
                line = f"{prop['record_type']};{fields_str}\n"
                file.write(line)

# Example usage:
# handler = SylkHandler('example.slk')
# handler.read_and_decode()
# handler.print_properties()
# handler.write('output.slk')

5. Java Class for .SYLK File Handling

The following Java class provides methods to open, decode, read, write, and print .SYLK properties to the console. It uses BufferedReader for reading and BufferedWriter for writing.

import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class SylkHandler {
    private String filename;
    private List<Record> properties = new ArrayList<>();

    private static class Record {
        String recordType;
        List<String> fields;

        Record(String type, List<String> fields) {
            this.recordType = type;
            this.fields = fields;
        }
    }

    public SylkHandler(String filename) {
        this.filename = filename;
    }

    public void readAndDecode() throws IOException {
        File file = new File(filename);
        if (!file.exists()) {
            throw new FileNotFoundException("File " + filename + " not found.");
        }
        try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
            String line;
            while ((line = reader.readLine()) != null) {
                if (!line.trim().isEmpty()) {
                    String[] parts = line.split(";");
                    for (int i = 0; i < parts.length; i++) {
                        parts[i] = parts[i].replace(";;", ";");
                    }
                    String recordType = parts[0];
                    List<String> fields = new ArrayList<>();
                    for (int i = 1; i < parts.length; i++) {
                        fields.add(parts[i].trim());
                    }
                    properties.add(new Record(recordType, fields));
                }
            }
        }
    }

    public void printProperties() {
        if (properties.isEmpty()) {
            System.out.println("No properties loaded. Call readAndDecode() first.");
            return;
        }
        System.out.println("SYLK Properties:");
        for (int idx = 0; idx < properties.size(); idx++) {
            Record prop = properties.get(idx);
            System.out.println("Record " + (idx + 1) + ": Type = " + prop.recordType);
            for (int fIdx = 0; fIdx < prop.fields.size(); fIdx++) {
                System.out.println("  Field " + (fIdx + 1) + ": " + prop.fields.get(fIdx));
            }
            System.out.println();
        }
    }

    public void write(String outputFilename) throws IOException {
        if (properties.isEmpty()) {
            throw new IllegalStateException("No properties to write. Call readAndDecode() first.");
        }
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(outputFilename))) {
            for (Record prop : properties) {
                StringBuilder line = new StringBuilder(prop.recordType);
                for (String field : prop.fields) {
                    line.append(";").append(field.replace(";", ";;"));
                }
                writer.write(line.toString());
                writer.newLine();
            }
        }
    }

    // Example usage:
    // public static void main(String[] args) throws IOException {
    //     SylkHandler handler = new SylkHandler("example.slk");
    //     handler.readAndDecode();
    //     handler.printProperties();
    //     handler.write("output.slk");
    // }
}

6. JavaScript Class for .SYLK File Handling

The following JavaScript (ES6) class handles .SYLK files in a Node.js environment (requires 'fs' module). It reads, decodes, prints properties to console, and writes to a new file.

const fs = require('fs');

class SylkHandler {
  constructor(filename) {
    this.filename = filename;
    this.properties = []; // Array of {recordType: string, fields: array<string>}
  }

  readAndDecode() {
    if (!fs.existsSync(this.filename)) {
      throw new Error(`File ${this.filename} not found.`);
    }
    const content = fs.readFileSync(this.filename, 'utf8');
    const lines = content.split(/\r?\n/).filter(line => line.trim() !== '');
    lines.forEach(line => {
      let parts = line.split(';');
      parts = parts.map(part => part.replace(';;', ';'));
      const recordType = parts[0];
      const fields = parts.slice(1).map(field => field.trim());
      this.properties.push({ recordType, fields });
    });
  }

  printProperties() {
    if (this.properties.length === 0) {
      console.log('No properties loaded. Call readAndDecode() first.');
      return;
    }
    console.log('SYLK Properties:');
    this.properties.forEach((prop, idx) => {
      console.log(`Record ${idx + 1}: Type = ${prop.recordType}`);
      prop.fields.forEach((field, fIdx) => {
        console.log(`  Field ${fIdx + 1}: ${field}`);
      });
      console.log('');
    });
  }

  write(outputFilename) {
    if (this.properties.length === 0) {
      throw new Error('No properties to write. Call readAndDecode() first.');
    }
    let content = '';
    this.properties.forEach(prop => {
      const fieldsStr = prop.fields.map(field => field.replace(';', ';;')).join(';');
      content += `${prop.recordType};${fieldsStr}\n`;
    });
    fs.writeFileSync(outputFilename, content, 'utf8');
  }
}

// Example usage:
// const handler = new SylkHandler('example.slk');
// handler.readAndDecode();
// handler.printProperties();
// handler.write('output.slk');

7. C++ Class for .SYLK File Handling

The following C++ class implements .SYLK handling, including reading, decoding, printing to console, and writing. It uses  and  for data management.

#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <sstream>

class SylkHandler {
private:
    std::string filename;
    struct Record {
        std::string recordType;
        std::vector<std::string> fields;
    };
    std::vector<Record> properties;

public:
    SylkHandler(const std::string& fn) : filename(fn) {}

    void readAndDecode() {
        std::ifstream file(filename);
        if (!file.is_open()) {
            throw std::runtime_error("File " + filename + " not found.");
        }
        std::string line;
        while (std::getline(file, line)) {
            if (line.empty()) continue;
            std::stringstream ss(line);
            std::string part;
            std::vector<std::string> parts;
            while (std::getline(ss, part, ';')) {
                size_t pos = 0;
                while ((pos = part.find(";;", pos)) != std::string::npos) {
                    part.replace(pos, 2, ";");
                    pos += 1;
                }
                parts.push_back(part);
            }
            std::string recordType = parts[0];
            std::vector<std::string> fields;
            for (size_t i = 1; i < parts.size(); ++i) {
                // Trim whitespace
                size_t start = parts[i].find_first_not_of(" \t");
                size_t end = parts[i].find_last_not_of(" \t");
                if (start != std::string::npos) {
                    fields.push_back(parts[i].substr(start, end - start + 1));
                } else {
                    fields.push_back("");
                }
            }
            properties.push_back({recordType, fields});
        }
        file.close();
    }

    void printProperties() const {
        if (properties.empty()) {
            std::cout << "No properties loaded. Call readAndDecode() first." << std::endl;
            return;
        }
        std::cout << "SYLK Properties:" << std::endl;
        for (size_t idx = 0; idx < properties.size(); ++idx) {
            const auto& prop = properties[idx];
            std::cout << "Record " << (idx + 1) << ": Type = " << prop.recordType << std::endl;
            for (size_t fIdx = 0; fIdx < prop.fields.size(); ++fIdx) {
                std::cout << "  Field " << (fIdx + 1) << ": " << prop.fields[fIdx] << std::endl;
            }
            std::cout << std::endl;
        }
    }

    void write(const std::string& outputFilename) const {
        if (properties.empty()) {
            throw std::runtime_error("No properties to write. Call readAndDecode() first.");
        }
        std::ofstream file(outputFilename);
        if (!file.is_open()) {
            throw std::runtime_error("Unable to open output file " + outputFilename);
        }
        for (const auto& prop : properties) {
            file << prop.recordType;
            for (const auto& field : prop.fields) {
                std::string escaped = field;
                size_t pos = 0;
                while ((pos = escaped.find(';', pos)) != std::string::npos) {
                    escaped.replace(pos, 1, ";;");
                    pos += 2;
                }
                file << ";" << escaped;
            }
            file << "\n";
        }
        file.close();
    }
};

// Example usage:
// int main() {
//     try {
//         SylkHandler handler("example.slk");
//         handler.readAndDecode();
//         handler.printProperties();
//         handler.write("output.slk");
//     } catch (const std::exception& e) {
//         std::cerr << e.what() << std::endl;
//     }
//     return 0;
// }