import ballerina/io;
function getFileRecordChannel (string filePath, string permission, string encoding,
                               string rs, string fs) returns (io:DelimitedRecordChannel) {
    io:ByteChannel channel = io:openFile(filePath, permission);
    var channelResp = io:createCharacterChannel(channel, encoding);
    match channelResp {
        io:CharacterChannel characterChannel => {
            var recordChannelResp = io:createDelimitedRecordChannel(characterChannel, rs, fs);
            match recordChannelResp {
                io:DelimitedRecordChannel delimitedRecordChannel => {
                    return delimitedRecordChannel;
                }
                io:IOError err => {
                    throw err.cause;
                }
            }
        }
        io:IOError err => {
            throw err.cause;
        }
    }
}
function readNext(io:DelimitedRecordChannel channel)returns (string []){
    var recordResp = channel.nextTextRecord();
    match recordResp {
        string[] records => {
            return records;
        }
        io:IOError err => {
            throw err.cause;
        }    }
}
function write(io:DelimitedRecordChannel channel,string [] records){
    io:IOError err = channel.writeTextRecord(records);
    if(err != null){
       throw err.cause;
    }
}
function process (io:DelimitedRecordChannel srcRecordChannel,
                  io:DelimitedRecordChannel dstRecordChannel) {
    try {
        while (srcRecordChannel.hasNextTextRecord()) {
            string[] records;
            records = readNext(srcRecordChannel);
            write(dstRecordChannel, records);
        }
    }catch (error err) {
        throw err;
    }
}function main (string[] args) {
    string srcFileName = "./files/sample.csv";
    string dstFileName = "./files/sampleResponse.txt";
    io:DelimitedRecordChannel srcRecordChannel =
    getFileRecordChannel(srcFileName, "r", "UTF-8", "\\r?\\n", ",");
    io:DelimitedRecordChannel dstRecordChannel =
    getFileRecordChannel(dstFileName, "w", "UTF-8", "\n", "|");
    try {
        io:println("Start to process CSV file from " + srcFileName + " to text file in "
                   + dstFileName);
        process(srcRecordChannel, dstRecordChannel);
        io:println("Processing completed. The processed file could be located in "
                   + dstFileName);
    }catch(error err){
        io:println("error occurred while processing records " + err.message);
    }finally {
       io:IOError? closeError = srcRecordChannel.closeDelimitedRecordChannel();
       closeError = dstRecordChannel.closeDelimitedRecordChannel();
    }
}

Record I/O

Will demonstrate how records could be read and written through I/O APIs

import ballerina/io;
function getFileRecordChannel (string filePath, string permission, string encoding,
                               string rs, string fs) returns (io:DelimitedRecordChannel) {
    io:ByteChannel channel = io:openFile(filePath, permission);

This function will return a DelimitedRecordChannel from a given file location.The encoding is character represenation of the content in file i.e UTF-8 ASCCI. The rs is record seperator i.e newline etc. and fs is field seperator i.e comma etc.

    var channelResp = io:createCharacterChannel(channel, encoding);
    match channelResp {
        io:CharacterChannel characterChannel => {

Then we create a character channel from the byte channel to read content as text.

            var recordChannelResp = io:createDelimitedRecordChannel(characterChannel, rs, fs);
            match recordChannelResp {
                io:DelimitedRecordChannel delimitedRecordChannel => {
                    return delimitedRecordChannel;
                }
                io:IOError err => {
                    throw err.cause;
                }
            }
        }
        io:IOError err => {
            throw err.cause;
        }
    }
}

Finally we convert the character channel to record channel to read content as records.

function readNext(io:DelimitedRecordChannel channel)returns (string []){
    var recordResp = channel.nextTextRecord();
    match recordResp {
        string[] records => {
            return records;
        }
        io:IOError err => {
            throw err.cause;
        }

This function will read next record from the channel

    }
}
function write(io:DelimitedRecordChannel channel,string [] records){
    io:IOError err = channel.writeTextRecord(records);
    if(err != null){
       throw err.cause;
    }
}

This function will write next record to the channel

function process (io:DelimitedRecordChannel srcRecordChannel,
                  io:DelimitedRecordChannel dstRecordChannel) {
    try {

This function will process CSV file and write content back as text with ‘|’ delimiter.

        while (srcRecordChannel.hasNextTextRecord()) {
            string[] records;

We read all the records from the provided file until there’re no records returned.

            records = readNext(srcRecordChannel);

Here’s how we read records.

            write(dstRecordChannel, records);
        }
    }catch (error err) {
        throw err;
    }
}

Here’s how we write records.

function main (string[] args) {
    string srcFileName = "./files/sample.csv";
    string dstFileName = "./files/sampleResponse.txt";
    io:DelimitedRecordChannel srcRecordChannel =
    getFileRecordChannel(srcFileName, "r", "UTF-8", "\\r?\\n", ",");

Here we specify the location of the CSV file where the record separator is new line and field separator is comma.

    io:DelimitedRecordChannel dstRecordChannel =
    getFileRecordChannel(dstFileName, "w", "UTF-8", "\n", "|");
    try {
        io:println("Start to process CSV file from " + srcFileName + " to text file in "
                   + dstFileName);
        process(srcRecordChannel, dstRecordChannel);
        io:println("Processing completed. The processed file could be located in "
                   + dstFileName);
    }catch(error err){
        io:println("error occurred while processing records " + err.message);
    }finally {

Here we specify the location of the text file where the record separator is new line and field separator is pipe.

       io:IOError? closeError = srcRecordChannel.closeDelimitedRecordChannel();
       closeError = dstRecordChannel.closeDelimitedRecordChannel();
    }
}

Close the text record channel.

$ ballerina run record-i-o.bal
Start to process CSV file from ./files/sample.csv to text file in ./files/sampleResponse.txt
Processing completed. The processed file could be located in ./files/sampleResponse.txt