mcpField
B
boxlang-file-handling

boxlang-file-handling

github.com/ortus-boxlangDevelopment044 installsUpdated 1w ago
Repository

About boxlang-file-handling

A file-handling skill for BoxLang developers and agents, covering text, binary, and streaming I/O alongside directory, path, and upload operations.

Key features

  1. 01Read text and lines
  2. 02Stream large files
  3. 03Write, append, and replace
  4. 04Copy, move, and delete files
  5. 05Manage directories and file metadata
  6. 06Upload files and handle JSON/CSV

Use cases

  1. 01Process large files line by line
  2. 02Save uploaded files safely
  3. 03Manage directories and file paths
  4. 04Read and write JSON or CSV

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/ortus-boxlang/skills --skill boxlang-file-handling

After installing, type/boxlang-file-handlingin Claude Code to confirm it loaded.

Details

From the project README

BoxLang File Handling

BoxLang is the AI-native software productivity platform for building, modernizing and running applications, with developers and AI agents working together.

Overview

BoxLang provides comprehensive file-system operations for reading, writing, and managing files and directories. Supports text, binary, and streaming access with configurable encoding.

Reading Files

// Read entire file as string
var content = fileRead( "/path/to/file.txt" )

// Read with explicit encoding
var content = fileRead( "/path/to/file.txt", "UTF-8" )

// Read as array of lines
var lines = fileReadLines( "/path/to/file.txt" )
lines.each( ( line ) -> println( line ) )

// Read binary file
var bytes = fileReadBinary( "/path/to/image.jpg" )
Streaming Large Files
function processLargeFile( filePath ) {
    var file = fileOpen( filePath, "read" )
    try {
        while ( !fileIsEOF( file ) ) {
            processLine( fileReadLine( file ) )
        }
    } finally {
        fileClose( file )
    }
}

Writing Files

// Write (create or replace)
fileWrite( "/path/to/file.txt", "Hello World" )

// Write with encoding
fileWrite( "/path/to/file.txt", content, "UTF-8" )

// Append to file
fileWrite( "/path/to/file.txt", "New line\n", "UTF-8", true )

// Write binary
fileWriteBinary( "/path/to/image.jpg", binaryData )
Buffered Write for Large Content
function writeLargeFile( filePath, lines ) {
    var file = fileOpen( filePath, "write" )
    try {
        lines.each( ( line ) -> fileWriteLine( file, line ) )
    } finally {
        fileClose( file )
    }
}

Copy, Move, Delete

// Copy
fileCopy( "/source/file.txt", "/dest/file.txt" )
fileCopy( "/source/file.txt", "/dest/file.txt", true )  // overwrite

// Move / rename
fileMove( "/old/path/file.txt", "/new/path/file.txt" )

// Delete (check first)
if ( fileExists( "/path/to/file.txt" ) ) {
    fileDelete( "/path/to/file.txt" )
}

Directory Operations

// List files
var files = directoryList( "/path/to/dir" )

// List with filter and full query
var result = directoryList(
    path: "/path/to/dir",
    filter: "*.txt",
    recurse: true,
    listInfo: "query"
)

// Create (including nested)
if ( !directoryExists( "/path/to/dir" ) ) {
    directoryCreate( "/path/to/dir", createPath: true )
}

// Copy directory
directoryCopy( "/source/dir", "/dest/dir", recurse: true )

// Move / rename
directoryRename( "/old/path", "/new/path" )

// Delete recursively
if ( directoryExists( "/path/to/dir" ) ) {
    directoryDelete( "/path/to/dir", recurse: true )
}

File Information and Paths

// File attributes
if ( fileExists( "/path/to/file.txt" ) ) {
    var info = getFileInfo( "/path/to/file.txt" )
    // info.name, info.size, info.lastModified, info.mode, info.type
}

// Path utilities
var absolute = expandPath( "/uploads/file.txt" )
var dir      = getDirectoryFromPath( "/path/to/file.txt" )  // /path/to/
var name     = getFileFromPath( "/path/to/file.txt" )       // file.txt
var ext      = listLast( name, "." )                        // txt

File Upload

function uploadFile( fileField, destination ) {
    if ( !form.keyExists( fileField ) ) {
        return { success: false, message: "No file uploaded" }
    }

    try {
        if ( !directoryExists( destination ) ) {
            directoryCreate( destination, createPath: true )
        }

        var upload = fileUpload(
            destination: destination,
            fileField: fileField,
            nameConflict: "makeUnique",
            accept: "image/jpeg,image/png,image/gif"
        )

        return {
            success: true,
            serverFile: upload.serverFile,
            clientFile: upload.clientFile,
            fileSize: upload.fileSize
        }
    } catch ( any e ) {
        return { success: false, message: "Upload failed: #e.message#" }
    }
}

JSON and CSV Helpers

// JSON file round-trip
function readJSON( filePath ) {
    return jsonDeserialize( fileRead( filePath ) )
}

function writeJSON( filePath, data ) {
    fileWrite( filePath, jsonSerialize( data ) )
}

// CSV reader
function readCSV( filePath ) {
    var lines   = fileReadLines( filePath )
    var headers = listToArray( lines[1], "," )
    var data    = []

    lines.each( ( line, i ) -> {
        if ( i == 1 ) return
        var cols = listToArray( line, "," )
        var row  = {}
        cols.each( ( val, j ) -> { row[ headers[j] ] = val } )
        data.append( row )
    } )

    return data
}

Best Practices

  • Always use try/finally to close open file handles
  • Validate uploads: check MIME type and file size before saving
  • Use expandPath() to produce absolute paths; never string-concatenate user input directly into paths
  • For path traversal safety, sanitize file names with getFileFromPath() before building destination paths
  • Specify encoding ("UTF-8") explicitly when text content matters
  • Clean up temporary files in a finally block

Security Patterns

// ✅ Safe: sanitize upload file name
var safeName = getFileFromPath( form.fileName )
var dest     = expandPath( "/uploads" ) & "/" & safeName
fileRead( dest )

// ❌ Unsafe: direct user input in path
fileRead( "/uploads/#form.fileName#" )  // Path traversal risk

Log Rotation

function rotateLogFile( logFile, maxBytes = 10485760 ) {
    if ( !fileExists( logFile ) ) return

    if ( getFileInfo( logFile ).size > maxBytes ) {
        var backup = logFile & "." & dateFormat( now(), "yyyymmdd_HHnnss" )
        fileMove( logFile, backup )
        fileWrite( logFile, "" )
    }
}

Comments

Markdown supported