Stream, File & Network IO
Note
This is not necessarily part of the core language. I’m just thinking about what a good API might look like.
Global IO functions
print("...")with Newline,- calls
cout.writeLine().
- calls
readLine() -> Stringreads up to Newline,- calls
cin.readLine().
- calls
input("Name? ") -> String- as in Python,
- calls
cout.write(), thencin.readLine(). input(String prompt = "") -> String- TODO
ask()orprompt()?
TextStream
For input / output of text.
Writing
cout.write("...")without newline.cout.writeLine("...")with newline.
Reading
cin.read() -> Stringreads- everything from the
istreamuser-level cache (if not empty), - or (otherwise) everything from the kernel buffer/cache:
- With pipes/sockets this is everything currently in the kernel pipe/socket buffer (typically up to 64 KB). Blocks when this buffer is empty.
Only when the pipe/socket is closed (and no data is buffered anymore), then it returns
"". - With files this is everything currently in the kernel “read ahead” cache (typically 64 to 256 KB). Blocks when this cache is empty.
Only when the end of file is reached (and no data is buffered anymore), then it returns
"".
- With pipes/sockets this is everything currently in the kernel pipe/socket buffer (typically up to 64 KB). Blocks when this buffer is empty.
Only when the pipe/socket is closed (and no data is buffered anymore), then it returns
- everything from the
cin.readAll() -> Stringreads everything until the end of the file.- With pipes/sockets, it blocks until the pipe/socket is closed.
cin.readLine() -> Stringreads until newline (or end of file).- The newline character is removed from the line.
\n,\r,\r\nare recognized as (a single) newline.- (Maybe even
\n\rfrom AmigaOS, andNEL/U+0085from EBCDIC/IBM.)
- With pipes/sockets it blocks until a line is available (or pipe/socket is closed).
- When the end of file is reached, then it returns
"". - But as empty lines are also read as
"", you need to checkatEnd()here.
- The newline character is removed from the line.
cin.readGraphemeCluster() -> Stringreads a single grapheme cluster (mostly a character).- Returns a
String, as UTF-8 “characters”/grapheme clusters may consist of multiple code points (therefore called a “grapheme cluster”). - With pipes/sockets it blocks until a character is available (or the pipe/socket is closed).
- When the end of file is reached, then it returns
"". - Unicode variant of
.cin.readChar() -> Char - TODO?
cin.readCodePoint() -> Char32reads a single Unicode code point (asChar32).- But beware: some grapheme clusters, like emoji, consist of multiple code points.
- When the end of file is reached, then it returns
-1.
- Returns a
cin.tryToRead() -> Stringreads everything that is immediately available,- possibly/often returns
"", it never blocks. - Reads everything from the
istreamuser-level cache (if not empty), - or (otherwise) everything from the kernel buffer/cache:
- With pipes/sockets this is everything currently in the kernel pipe/socket buffer (typically up to 64 KB).
Returns
""when no data is buffered anymore (then maybe the pipe/socket is closed). - With files this is everything currently in the kernel “read ahead” cache (typically 64 to 256 KB).
Returns
""when no data is buffered anymore (then maybe the end of file is reached).
- With pipes/sockets this is everything currently in the kernel pipe/socket buffer (typically up to 64 KB).
Returns
- Meant for polling / busy loops only, so rarely appropriate.
- You need to check
atEnd()separately!- As you cannot distinguish “no data available” from EOF or pipe/socket closed.
- possibly/often returns
cin.atEnd()(instead of)cin.isEof()- returns
Trueif- the end of the file is reached (or the pipe/socket is closed),
- and no data is buffered anymore (neither in the
istreamuser-level cache, nor in the kernel cache/buffer),
- Typically necessary to call this function when
cin.read()orcin.readLine()return"".
- returns
ByteStream
For input / output of binary data.
Writing
out.close()out.write(Byte[])out.flush()writes the data buffer (theistreamuser-level cache) to the operating system.- This protects against data loss in the event of a program crash.
out.flushAndSync()callsflush(), then- calls
fsync()to write the kernel buffers to the file system and then to the hard disk/SSD (the write cache should be written/cleared, too). - This protects against data loss in the event of a program or system crash.
- calls
Reading
in.read() -> Byte[]reads- everything from the
istreamuser-level cache, if not0,
otherwise everything from the kernel buffer/cache:- With pipes/sockets this is everything currently in the kernel pipe/socket buffer (typically 64 KB).
- Blocks when this buffer is empty.
- When the pipe/socket is closed (and no data is buffered anymore), then it returns an empty array.
- With files this is everything currently in the kernel “read ahead” cache (typically 64 to 256 KB).
- Blocks when this cache is empty.
- When the end of file is reached (and no data is cached anymore), then it returns an empty array.
- With pipes/sockets this is everything currently in the kernel pipe/socket buffer (typically 64 KB).
- everything from the
in.read(Int n) -> Byte[]reads exactly n bytes.- Blocks until the given number of bytes are read.
- Throws an exception if end of file is reached (or pipe/socket closed) before n bytes are read.
in.read(Int minimum, maximum) -> Byte[]reads everything that is currently available, up to the givenmaximumnumber of bytes.- Blocks until (at least) the
minimumnumber of bytes are read (may return immediately with an empty array whenminimumis0). in.read(minimum..maximum) -> Byte[]
- Blocks until (at least) the
in.readAll() -> Byte[]reads everything until the end of the stream.- With pipes/sockets, it blocks until the pipe/socket is closed.
in.readInto(Span<Byte> buffer, Int minimum = 1)reads into the given buffer.- Blocks until (at least) the
minimumnumber of bytes are read (may return immediately with an empty array whenminimumis0). - Throws an exception if end of file reached (or pipe/socket closed) before
minimumbytes are read. - The effective
maximumif defined bybuffer.size().- You may limit the maximum number of bytes to read by using
buffer.subspan(0, 4096), or configure the starting point (in the buffer) by usingbuffer.subspan(100).
- You may limit the maximum number of bytes to read by using
- Usually more efficient, as the buffer is reused and less allocations are necessary.
- Blocks until (at least) the
in.available() -> Intsays how many bytes are immediately available for reading.- Returns the size of the
istreamcache, if not 0,
otherwise reports the size of the kernel cache/buffer. - As that is the number of bytes you would get with the next
in.read().
- Returns the size of the
in.peek(Int n) -> Byte[]- Blocks until (at least) the
minimumnumber of bytes are read. - May throw an
ArgumentException("Unable to peek() more than ... bytes."). - TODO Limited to 16 bytes or to the buffer size?
- Blocks until (at least) the
in.ignore(Int n)ignores/discards n bytes from the input stream.in.ignoreAll()ignores/discards everything that is currently in the input stream.in.atEnd()returnsTrueif- the end of the file is reached (or the pipe/socket is closed),
- and no data is buffered anymore (neither in the
istreamuser-level cache, nor in the kernel cache/buffer).
File IO
File, derived from ByteStream.
file.size() -> Intfile.position() -> Intfile.setPosition(Int n)(AKA)file.seekFromStart()- A common position for read and write.
file.seek(Int offsetToCurrentPos)offsetToCurrentPoscan be positive (moving towards the end) or negative (moving towards the beginning).
file.seekFromEnd(Int distanceToEnd)distanceToEndis0or positive (here moving from the end towards the beginning).
file.truncate()truncates the file at the current position.file.truncateAt(Int n)truncates the file at the given position.
file.path() -> String
Network IO
NetworkConnection, derived fromByteStream,- a base class for TCP/IP, Bluetooth, infrared, …
connection.connect(...)connection.disconnect()connection.isConnected() -> Boolconnection.remoteAddress() -> Stringconnection.localAddress() -> Stringfor finding out which interface (WLAN, LAN, VPN) the connection is actually running on.connection.readTimeout() -> Durationconnection.setReadTimeout(Duration)
TcpConnection, derived fromNetworkConnectionconnection.shutdownWrite()sends FIN (half-close), allows further reading.connection.connectionTimeout() -> Durationconnection.setConnectionTimeout(Duration)
connection.remotePort() -> UInt16connection.localPort() -> UInt16connection.noDelay() -> Boolconnection.setNoDelay(Bool disableNagle)to disable the Nagle algorithm.
connection.keepAlive() -> Boolconnection.setKeepAlive(Bool)prevents connection termination due to inactivity.
connection.protocolVersion() -> Intreturns4or6.connection.receiveBufferSize() -> Intconnection.setReceiveBufferSize(Int bytes)
connection.sendBufferSize() -> Intconnection.setSendBufferSize(Int bytes)
LocalConnection, derived fromByteStreamconnection.path() -> Stringreturns the file system path (for Unix sockets) or the name (for pipes).connection.peerCredentials() -> Stringreturns the process ID (PID) or user ID of the other party.- TODO Move to
UnixDomainSocket? But on Windows this info is available for pipes, too.
- TODO Move to
SerialConnection(RS-232/UART)setBaudRate(Int)setParity(Bool)setDataBits(Int)
Class Hierarchy
ByteStreamFileMemoryStreamas RAM buffer.NetworkStreamTCPConnectionTLSConnection/SSLConnection
SSHStream
LocalStreamfor interprocess communication.PipeUnixDomainStreamin stream configuration.
DeviceStreamSerialConnectionfor RS-232/UART.USBConnectionfor USB bulk transfers.
MessageChannelfor message/packet/frame/datagram-based protocols (i.e. not only a stream of bytes).UDPSocketfor UDP over IP.UnixDomainSocketin datagram configuration.- Communication with sensors on microcontrollers
I2CDevice(register read/write cycles)SPIDevice(chip-select-controlled frames)CANBusNode
BluetoothConnectionBluetooth RFCOMM / L2CAPZigbeeEndpointWebSocketConnection(message frames over TCP)