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.
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;
}
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. |
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. |
Prints |
|
println | Prints |
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.) |
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. |
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(:). |
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. |