Blog

Luis Majano

October 30, 2025

Spread the word


Share your thoughts

We're thrilled to announce the release of bx-csv, a powerful premium module that brings enterprise-grade CSV processing capabilities to BoxLang+ subscribers! Built on Apache Commons CSV, this module provides both traditional functions and a modern, fluent API that makes working with CSV files a breeze.

✨ What's New?

The bx-csv module transforms how you work with CSV files in BoxLang, offering:

  • 🚀 Modern Fluent API - Chainable, elegant code that's easy to read and maintain
  • ⚡ Streaming Support - Process massive files without memory concerns
  • 🎯 Smart Data Transformation - Built-in filtering and mapping during load operations
  • 📦 Multi-Format Support - Seamless conversion between CSV, JSON, Query, and arrays
  • 🎨 Flexible Configuration - Custom delimiters, quotes, escapes, and line separators
  • 💪 Production Ready - Battle-tested Apache Commons CSV foundation

🎟️ Subscription & Trial Information

The bx-csv module is available exclusively to BoxLang+ and BoxLang++ subscribers. However, we want everyone to experience its power, so it comes with a generous 60-day trial when installed alongside the bx-plus module.

Ready to try it? Install it now:

box install bx-csv

Not a subscriber yet? Check out our plans and start your trial today!


🚀 The Modern Way: Fluent API

We've designed the fluent API to be intuitive and powerful. Here's how easy it is to create and manipulate CSV files:

Creating a CSV File

// Create a simple contacts file
CSV()
    .setHeaders( "Name", "Email", "Age" )
    .addRow( [ "John Doe", "john@example.com", 30 ] )
    .addRow( [ "Jane Smith", "jane@example.com", 25 ] )
    .addRow( [ "Bob Johnson", "bob@example.com", 35 ] )
    .save( "contacts.csv" );

That's it! Clean, readable, and maintainable. The fluent API chains methods together, making your intent crystal clear.

Loading and Transforming Data

// Load, filter, and transform in one elegant chain
CSV( "raw-data.csv" )
    .filter( ( row ) => {
        // Only include rows with valid emails
        return row[ 2 ].find( "@" ) > 0;
    } )
    .map( ( row ) => {
        // Normalize the data
        row[ 0 ] = row[ 0 ].trim().toUpperCase(); // Name
        row[ 1 ] = row[ 1 ].trim(); // Phone
        row[ 2 ] = row[ 2 ].trim().toLowerCase(); // Email
        return row;
    } )
    .save( "cleaned-data.csv" );

⚡ Streaming Large Files

One of the most powerful features is the ability to process huge files without loading them entirely into memory:

// Process a multi-gigabyte file efficiently
CSV().process( "huge-file.csv", ( row ) => {
    // Process each row individually
    queryExecute(
        "INSERT INTO customers (name, email) VALUES ( ?, ? )",
        [ row[ 1 ], row[ 2 ] ]
    );
} );

The streaming API ensures your application remains responsive even when processing files with millions of rows.

📊 Seamless Format Conversion

The bx-csv module makes it trivial to convert between different data formats:

From Database to CSV

// Export query results directly to CSV
qData = queryExecute( "
    SELECT
        customer_name,
        order_date,
        product_name,
        quantity,
        unit_price,
        ( quantity * unit_price ) AS total
    FROM orders
    WHERE order_date >= ?
", [ dateAdd( "m", -1, now() ) ] );

CSVFile.fromQuery( qData )
    .delimiter( ',' )
    .quoteMode( "MINIMAL" )
    .save( "reports/monthly-orders.csv" );

From CSV to JSON

// Convert CSV to pretty-printed JSON
csv = CSV()
    .setHeaders( "Name", "Age", "City" )
    .addRow( [ "John", 30, "New York" ] )
    .addRow( [ "Jane", 25, "Los Angeles" ] );

jsonString = csv.toJson( true );
// Returns formatted JSON array of objects

From JSON to CSV

// Import JSON data and save as CSV
jsonData = '[
    { "Product": "Widget A", "Price": 10.99, "InStock": true },
    { "Product": "Widget B", "Price": 15.99, "InStock": false }
]';

CSVFile.fromJson( jsonData ).save( "products.csv" );

🎨 Flexible Configuration

The module supports virtually any CSV format you might encounter:

// Pipe-delimited with custom quote character
CSV()
    .delimiter( '|' )
    .quote( '\'' )
    .trim( true )
    .setHeaders( "Name", "Age", "City" )
    .addRow( [ "John O'Brien", 30, "New York" ] )
    .save( "data.txt" );

// Tab-separated values (TSV)
CSV()
    .delimiter( '\t' )
    .load( "data.tsv" );

// Handle comments and empty lines
CSV()
    .commentMarker( '#' )
    .ignoreEmptyLines( true )
    .load( "data-with-comments.csv" );

💼 Real-World Use Cases

Data Import Pipeline

// Build a robust data import system
CSV()
    .setPath( "imports/daily-feed.csv" )
    .delimiter( '|' )
    .trim( true )
    .ignoreEmptyLines( true )
    .filter( ( row ) => {
        // Validate required fields
        return row[ 1 ] != "" && row[ 2 ] != "" && row[ 3 ] > 0;
    } )
    .process( ( row ) => {
        // Insert validated rows into database
        try {
            queryExecute(
                "INSERT INTO products ( sku, name, price ) VALUES ( ?, ?, ? )",
                [ row[ 1 ], row[ 2 ], row[ 3 ] ]
            );
        } catch( any e ) {
            logError( "Failed to import row: " & row[ 1 ], e );
        }
    } );

Report Generation

// Generate monthly sales report
qSales = queryExecute( "
    SELECT
        DATE_FORMAT( order_date, '%Y-%m' ) as month,
        COUNT(*) as total_orders,
        SUM( order_total ) as revenue,
        AVG( order_total ) as avg_order
    FROM orders
    WHERE order_date >= DATE_SUB( NOW(), INTERVAL 12 MONTH )
    GROUP BY month
    ORDER BY month DESC
" );

CSVFile.fromQuery( qSales )
    .headerComments(
        "Monthly Sales Report",
        "Generated: " & now(),
        "Period: Last 12 Months"
    )
    .commentMarker( '#' )
    .quoteMode( "NON_NUMERIC" )
    .save( "reports/monthly-sales.csv" );

Data Consolidation

// Combine multiple CSV files from different sources
combined = CSV().setHeaders( "Name", "Email", "Source", "ImportDate" );

// Process each source file
sources = [
    { file: "mailchimp-export.csv", name: "MailChimp" },
    { file: "salesforce-export.csv", name: "Salesforce" },
    { file: "hubspot-export.csv", name: "HubSpot" }
];

sources.each( ( source ) => {
    CSV().process( source.file, ( row ) => {
        // Skip header rows
        if ( row[ 1 ] != "Name" && row[ 1 ] != "name" ) {
            combined.addRow( [
                row[ 1 ],
                row[ 2 ],
                source.name,
                now()
            ] );
        }
    } );
} );

combined.save( "combined-contacts.csv" );

📚 Complete Documentation

The bx-csv module is fully documented in our official BoxLang documentation, and we've even created a dedicated MCP Server for it:

🎁 Get Access

bx-ldap is available exclusively to BoxLang +/++ subscribers. Join our subscription program to access this and other premium modules that extend BoxLang's capabilities:

  • Priority Support - Get help when you need it
  • Premium Modules - Access subscriber-only modules
  • Early Access - Be first to try new features
  • Exclusive Benefits - CFCasts account, FORGEBOX Pro, and more

🛒 Purchase Options

Ready to unlock bx-ldap and other premium modules? Choose your plan:

🌟 View BoxLang Plans & Pricing

Need help choosing the right plan or have questions? Contact us directly:

📧 info@boxlang.io

Add Your Comment

Recent Entries

FIU Students Build AI Applications and Contribute to the BoxLang Ecosystem

FIU Students Build AI Applications and Contribute to the BoxLang Ecosystem

Florida International University students are gaining hands-on software development experience through an ongoing collaboration with Ortus Solutions, building applications with BoxLang and BoxLang AI while exploring opportunities to contribute to the technologies themselves.

Maria Jose Herrera
Maria Jose Herrera
November 02, 2026
Coming Soon:  Version 4 Docker CommandBox Images with Enhanced Performance

Coming Soon: Version 4 Docker CommandBox Images with Enhanced Performance

CommandBox Docker images were the first CFML docker images and have nearly 2 million pulls, since their inception, to date. It's been a source of pride at Ortus that these images have been the most popular and reliable way to run CFML in containers and we are so very pleased to announce the next evolution, which will be the v4 images which run entirely on the BoxLang CLI and represent a significant overhaul of the image architecture.

These images are now available to test by appending -snapshot to your existing version tags and wil be released as stable, once CommandBox v6 emerges from release candidate status and is published as stable.

Jon Clausen
Jon Clausen
October 30, 2026
Free observability with BxMCP: give your AI agents eyes inside a live BoxLang runtime

Free observability with BxMCP: give your AI agents eyes inside a live BoxLang runtime

Ortus Solutions today announces that bx-mcp, the Model Context Protocol (MCP) server for BoxLang, is now free for everyone. Install it, point any MCP capable client at it, and your AI coding assistant, IDE agent or automation pipeline can inspect and operate a live BoxLang runtime: JVM, caches, datasources, slow requests, schedulers, logs and more. No BoxLang+ subscription required.

Luis Majano
Luis Majano
October 29, 2026