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 readableChannel = io:openReadableFile("file.txt");

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

// Open a file in write mode.
io:WritableByteChannel | io:Error writableByteChannel = io:openWritableFile("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(readableChannel, "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.
// 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;
}

Records

Detail Record type to hold the details of an error.

Objects

ReadableByteChannel

ReadableByteChannel represents an input resource (i.e file). 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). 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

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.

COMMA

Comma (,) will be used as the field separator.

TAB

Tab (/t) will be use as the field separator.

COLON

Colon (:) will be use as the field separator.

CONNECTION_TIMED_OUT

This will be used to construct a ConnectionTimedOutError.

GENERIC_ERROR

This will be used to construct an IO GenericError.

ACCESS_DENIED_ERROR

This will be used to construct a AccessDeniedError.

FILE_NOT_FOUND_ERROR

This will be used to construct a FileNotFoundError.

END_OF_FILE_ERROR

This will be used to construct an EofError.

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

Specifies the bytes to be in the order of most significant byte first.

LITTLE_ENDIAN

Specifies the byte order to be the least significant byte first.

Types

Error

Represents IO module related errors.

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.

Separator

Field separators which are supported by DelimitedTextRecordChannel.

COMMA - Delimited text records would be separated using a comma.

TAB - Delimited text records would be separated using a tab.

COLON - Delimited text records would be separated using a colon(:).

Errors

AccessDeniedError

This will get returned due to file permission issues.

ConnectionTimedOutError

This will return when connection timed out happen when try to connect to a remote host.

EofError

This will get returned if read operations are performed on a channel after it closed.

FileNotFoundError

This will get returned if the file is not available in the given file path.

GenericError

Represents generic IO error. The detail record contains the information related to the error.