Module : io

Module Overview

This module is designed to support input and output operations via channels in a canonical way, either in a blocking, or non-blocking manner.

architecture

Channels

A channel represents an I/O source or sink of some bytes, characters, or records that are opened for reading, or writing, respectively.

Byte channels

The most primitive channel is the ByteChannel which reads and writes 8-bit bytes.

// Open a file in read mode.
io:ReadableByteChannel | io:Error readableByteChannel = io:openReadableFile("some/file.txt");

// Here is how 100 bytes are read from the channel.
if (readableByteChannel is io:ReadableByteChannel) {
    [byte[], int] | io:Error result = readableByteChannel.read(100);
}

// Open a file in write mode.
io:WritableByteChannel | io:Error writableByteChannel = io:openWritableFile("some/file.txt");

// Write some content to the beginning of the file.
if (writableByteChannel is io:WritableByteChannel) {
    string someContent = "some cont";
    byte[] content = someContent.toBytes();
    int | io:Error writeResult = writableByteChannel.write(content, 0);
}

Character channels

The CharacterChannel is used to read and write characters. The charset encoding is specified when creating the CharacterChannel.

// Create a `ReadableCharacterChannel` from the `ReadableByteChannel`.
io:ReadableCharacterChannel | io:Error readableCharChannel = new io:ReadableCharacterChannel(readableByteChannel, "UTF-8");

If a ReadableCharacterChannel points to a JSON or XML source, it can be read and then written, directly into a variable of the respective type.

// Reading a JSON.
json | io:Error result = readableCharChannel.readJson();
// Reading an XML.
xml | io:Error result = readableCharChannel.readXml();
// Create a `WritableCharacterChannel` from the `WritableByteChannel`.
io:WritableCharacterChannel | io:Error writableCharChannel = new io:WritableCharacterChannel(writableByteChannel, "UTF-8");
// Writing a JSON.
json content = {fname: "Jhon", lname: "Doe", age: 40};
var writeResult = writableCharChannel.writeJson(content);
if (writeResult is io:Error) {
    return writeResult;
} else {
    io:println("JSON content written successfully.");
}

Record channels

Ballerina also supports I/O for delimited records.

// Create a `ReadableTextRecordChannel` from the `ReadableCharacterChannel`.
// Records are separated using a new line, and fields of a record are separated using a comma.
var readableRecordsChannel = new io:ReadableTextRecordChannel(readableCharChannel, fs = ",", rs = "\n");

// Read few records.
while (readableRecordsChannel.hasNext()) {
    var result = readableRecordsChannel.getNext();
    if (result is string[]) {
        io:println(result); // Retrieved a record.
    } else {
        return result; // An IO error occurred when reading the records.
    }
}

A .CSV file can be read and written directly into a CSVChannel, as shown in this code snippet.

// Create a `ReadableCSVChannel` from the `ReadableCharacterChannel`.
var readableCSVChannel = new io:ReadableCSVChannel(readableCharChannel);

Records of the .CSV file can read directly into a table of a matching type.

// First let’s define a type that matches a record in the CSV file.
type Employee record {
   string id;
   string name;
   float salary;
};

// Now read the CSV file as a table of Employees and compute total salary.
float total = 0.0;
var tableResult = readableCSVChannel.getTable(Employee);
if (tableResult is table<Employee>) {
    foreach var x in tableResult {
      total = total + x.salary;
    }
    return total;
} else {
    return tableResult; //Return the error back to the caller
}

Data Channels

Ballerina supports performing data i/o operations

Person object could be serialized into a file or a network socket in the following manner.

public type Person record {
    string name;
    int age;
    float income;
    boolean isMarried;
};

// Serialize record into binary.
function serialize(Person p, io:WritableByteChannel byteChannel) {
    io:WritableDataChannel dc = new io:WritableDataChannel(byteChannel);
    var length = p.name.toBytes().length();
    var lengthResult = dc.writeInt32(length);
    var nameResult = dc.writeString(p.name, "UTF-8");
    var ageResult = dc.writeInt16(p.age);
    var incomeResult = dc.writeFloat64(p.income);
    var maritalStatusResult = dc.writeBool(p.isMarried);
    var closeResult = dc.close();
}

// Deserialize record into binary.
function deserialize(io:ReadableByteChannel byteChannel) returns Person {
    Person person = {name: "", age: 0, income: 0.0, isMarried: false};
    int nameLength = 0;
    string nameValue;
    io:ReadableDataChannel dc = new io:ReadableDataChannel(byteChannel);
    // Read 32 bit signed integer.
    var int32Result = dc.readInt32();
    if (int32Result is int) {
        nameLength = int32Result;
    } else {
        log:printError("Error occurred while reading name length", int32Result);
    }
    // Read UTF-8 encoded string represented through specified amount of bytes.
    var strResult = dc.readString(nameLength, "UTF-8");
    if (strResult is string) {
        person.name = strResult;
    } else {
        log:printError("Error occurred while reading name", strResult);
    }
    // Read 16 bit signed integer.
    var int16Result = dc.readInt16();
    if (int16Result is int) {
        person.age = int16Result;
    } else {
        log:printError("Error occurred while reading age", int16Result);
    }
    // Read 64 bit signed float.
    var float64Result = dc.readFloat64();
    if (float64Result is float) {
        person.income = float64Result;
    } else {
        log:printError("Error occurred while reading income", float64Result);
    }
    // Read boolean.
    var boolResult = dc.readBool();
    if (boolResult is boolean) {
        person.isMarried = boolResult;
    } else {
        log:printError("Error occurred while reading marital status", boolResult);
    }
    // Finally close the data channel.
    var closeResult = dc.close();
    return person;
}

Objects

ReadableByteChannel

ReadableByteChannel represents an input resource (i.e file, socket). which could be used to source bytes.

ReadableCSVChannel

Represents a ReadableCSVChannel which could be used to read records from CSV file.

ReadableCharacterChannel

Represents a channel which could be used to read characters through a given ReadableByteChannel.

ReadableDataChannel

Represents a data channel for reading data.

ReadableTextRecordChannel

Represents a channel which will allow to read

StringReader

Represents a reader which will wrap string content as a channel.

WritableByteChannel

WritableByteChannel represents an output resource (i.e file, socket). which could be used to sink bytes.

WritableCSVChannel

Represents a WritableCSVChannel which could be used to write records from CSV file.

WritableCharacterChannel

Represents a channel which could be used to write characters through a given WritableCharacterChannel.

WritableDataChannel

Represents a WritableDataChannel for writing data.

WritableTextRecordChannel

Represents a channel which will allow to write records through a given WritableCharacterChannel.

Functions

createReadableChannel

Creates an in-memory channel which will reference stream of bytes.

openReadableCsvFile

Retrieves a readable CSV channel from a give file path.

openReadableFile

Retrieves a ReadableByteChannel from a given file path.

openWritableCsvFile

Retrieves a writable CSV channel from a give file path.

openWritableFile

Retrieves a WritableByteChannel from a given file path.

print

Prints any or error value(s) to the STDOUT.

println

Prints any or error value(s) to the STDOUT followed by a new line.

readln

Returns the input read from STDIN.

sprintf

Returns a formatted string using the specified format string and arguments. Following format specifiers are allowed. b boolean B boolean (ALL_CAPS) d int f float x hex X HEX (ALL_CAPS) s string (This specifier is applicable for any of the supported types in Ballerina. These values will be converted to their string representation.)

Constants

DEFAULT
CSV
TDF
COMMA
TAB
COLON
CONNECTION_TIMED_OUT
GENERIC_ERROR
ACCESS_DENIED_ERROR
FILE_NOT_FOUND_ERROR
END_OF_FILE_ERROR
READ
WRITE
RW
APPEND
CSV_RECORD_SEPARATOR

Represents record separator of the CSV file.

FS_COLON

Represents colon separator which should be used to identify colon separated files.

MINIMUM_HEADER_COUNT

Represents minimum number of headers which will be included in CSV.

BIG_ENDIAN
LITTLE_ENDIAN

Types

Error
Format

Format which will be used to represent the CSV.

DEFAULT - Would default to the format specified by CSVChannel. Precedence will be given to field separator and record separator.

CSV - Field separator would be "," and the record separator would be new line.

TDF - Field separator will be tab and record separator will be new line.

Mode
Separator

Field separators which are supported by DelimitedTextRecordChannel.

Errors

AccessDeniedError
ConnectionTimedOutError
EofError
FileNotFoundError
GenericError