Skip to content

//okio/okio/Buffer

Buffer

[js, native] class Buffer : BufferedSource, BufferedSink
[jvm] class Buffer : BufferedSource, BufferedSink, Cloneable, ByteChannel

Types

Name Summary
UnsafeCursor [jvm]
Brief description
A handle to the underlying data in a buffer. This handle is unsafe because it does not enforce its own invariants. Instead, it assumes a careful user who has studied Okio’s implementation details and their consequences.Buffer Internals ----------------Most code should use Buffer as a black box: a class that holds 0 or more bytes of data with efficient APIs to append data to the end and to consume data from the front. Usually this is also the most efficient way to use buffers because it allows Okio to employ several optimizations, including:
  • Buffers use a shared pool of memory that is not zero-filled before use.
  • A buffer’s capacity can change without copying its contents.
  • Memory ownership can be reassigned from one buffer to another.
  • Multiple buffers can share the same underlying memory.
  • Common operations like UTF-8 encoding and decimal decoding do not require intermediate objects to be allocated.
These optimizations all leverage the way Okio stores data internally. Okio Buffers are implemented using a doubly-linked list of segments. Each segment is a contiguous range within a 8 KiB ByteArray. Each segment has two indexes, start, the offset of the first byte of the array containing application data, and end, the offset of the first byte beyond start whose data is undefined.New buffers are empty and have no segments:val buffer = Buffer()We append 7 bytes of data to the end of our empty buffer. Internally, the buffer allocates a segment and writes its new data there. The lone segment has an 8 KiB byte array but only 7 bytes of data:buffer.writeUtf8(“sealion”)

// [ ‘s’, ‘e’, ‘a’, ‘l’, ‘i’, ‘o’, ‘n’, ‘?’, ‘?’, ‘?’, …]
// ^ ^
// start = 0 end = 7When we read 4 bytes of data from the buffer, it finds its first segment and returns that data to us. As bytes are read the data is consumed. The segment tracks this by adjusting its internal indices.buffer.readUtf8(4) // “seal”

// [ ‘s’, ‘e’, ‘a’, ‘l’, ‘i’, ‘o’, ‘n’, ‘?’, ‘?’, ‘?’, …]
// ^ ^
// start = 4 end = 7As we write data into a buffer we fill up its internal segments. When a write doesn’t fit into a buffer’s last segment, additional segments are allocated and appended to the linked list of segments. Each segment has its own start and end indexes tracking where the user’s data begins and ends.val xoxo = new Buffer()
xoxo.writeUtf8(“xo”.repeat(5_000))

// [ ‘x’, ‘o’, ‘x’, ‘o’, ‘x’, ‘o’, ‘x’, ‘o’, …, ‘x’, ‘o’, ‘x’, ‘o’]
// ^ ^
// start = 0 end = 8192
//
// [ ‘x’, ‘o’, ‘x’, ‘o’, …, ‘x’, ‘o’, ‘x’, ‘o’, ‘?’, ‘?’, ‘?’, …]
// ^ ^
// start = 0 end = 1808The start index is always inclusive and the end index is always exclusive. The data preceding the start index is undefined, and the data at and following the end index is undefined.After the last byte of a segment has been read, that segment may be returned to an internal segment pool. In addition to reducing the need to do garbage collection, segment pooling also saves the JVM from needing to zero-fill byte arrays. Okio doesn’t need to zero-fill its arrays because it always writes memory before it reads it. But if you look at a segment in a debugger you may see its effects. In this example, one of the “xoxo” segments above is reused in an unrelated buffer:val abc = new Buffer()
abc.writeUtf8(“abc”)

// [ ‘a’, ‘b’, ‘c’, ‘o’, ‘x’, ‘o’, ‘x’, ‘o’, …]
// ^ ^
// start = 0 end = 3There is an optimization in Buffer.clone() and other methods that allows two segments to share the same underlying byte array. Clones can’t write to the shared byte array; instead they allocate a new (private) segment early.val nana = new Buffer()
nana.writeUtf8(“na”.repeat(2_500))
nana.readUtf8(2) // “na”

// [ ‘n’, ‘a’, ‘n’, ‘a’, …, ‘n’, ‘a’, ‘n’, ‘a’, ‘?’, ‘?’, ‘?’, …]
// ^ ^
// start = 2 end = 5000

nana2 = nana.clone()
nana2.writeUtf8(“batman”)

// [ ‘n’, ‘a’, ‘n’, ‘a’, …, ‘n’, ‘a’, ‘n’, ‘a’, ‘?’, ‘?’, ‘?’, …]
// ^ ^
// start = 2 end = 5000
//
// [ ‘b’, ‘a’, ‘t’, ‘m’, ‘a’, ‘n’, ‘?’, ‘?’, ‘?’, …]
// ^ ^
// start = 0 end = 6Segments are not shared when the shared region is small (ie. less than 1 KiB). This is intended to prevent fragmentation in sharing-heavy use cases.Unsafe Cursor API -----------------This class exposes privileged access to the internal byte arrays of a buffer. A cursor either references the data of a single segment, it is before the first segment (offset == -1), or it is after the last segment (offset == buffer.size).Call UnsafeCursor.seek to move the cursor to the segment that contains a specified offset. After seeking, UnsafeCursor.data references the segment’s internal byte array, UnsafeCursor.start is the segment’s start and UnsafeCursor.end is its end.Call UnsafeCursor.next to advance the cursor to the next segment. This returns -1 if there are no further segments in the buffer.Use Buffer.readUnsafe to create a cursor to read buffer data and Buffer.readAndWriteUnsafe to create a cursor to read and write buffer data. In either case, always call UnsafeCursor.close when done with a cursor. This is convenient with Kotlin’s use extension function. In this example we read all of the bytes in a buffer into a byte array:val bufferBytes = ByteArray(buffer.size.toInt())

buffer.readUnsafe().use { cursor ->
while (cursor.next() != -1) {
System.arraycopy(cursor.data, cursor.start,
bufferBytes, cursor.offset.toInt(), cursor.end - cursor.start);
}
}Change the capacity of a buffer with resizeBuffer. This is only permitted for read+write cursors. The buffer’s size always changes from the end: shrinking it removes bytes from the end; growing it adds capacity to the end.Warnings --------Most application developers should avoid this API. Those that must use this API should respect these warnings. This class has public, non-final fields because that is convenient for low-level I/O frameworks. Never assign values to these fields; instead use the cursor API to adjust these.data You are on the honor system to never write the buffer in read-only mode. Read-only mode may be more efficient than read+write mode because it does not need to make private copies of shared segments.[start..end) Other data in the byte array is undefined! It may contain private or sensitive data from other parts of your process.Always fill the new capacity when you grow a buffer. New capacity is not zero-filled and may contain data from other parts of your process. Avoid leaking this information by always writing something to the newly-allocated capacity. Do not assume that new capacity will be filled with 0; it will not be.Do not access a buffer while is being accessed by a cursor. Even simple read-only operations like Buffer.clone are unsafe because they mark segments as shared.Do not hard-code the segment size in your application. It is possible that segment sizes will change with advances in hardware. Future versions of Okio may even have heterogeneous segment sizes.These warnings are intended to help you to use this API safely. It’s here for developers that need absolutely the most throughput. Since that’s you, here’s one final performance tip. You can reuse instances of this class if you like. Use the overloads of Buffer.readUnsafe and Buffer.readAndWriteUnsafe that take a cursor and close it after use.
Content
class UnsafeCursor : Closeable


Functions

Name Summary
buffer [jvm]
Brief description
Returns this source’s internal buffer.
Content
open override fun buffer(): Buffer


clear [js, jvm, native]
Content
[js, jvm, native]
fun clear()


clone [jvm]
Brief description
Returns a deep copy of this buffer.
Content
open override fun clone(): Buffer


close [js, jvm, native]
Content
[js, jvm, native]
open override fun close()


completeSegmentByteCount [js, jvm, native]
Content
[js, jvm, native]
fun completeSegmentByteCount(): Long


copy [js, jvm, native]
Content
[js, jvm, native]
fun copy(): Buffer


copyTo [js, jvm, native]
Content
[js, jvm, native]
fun copyTo(out: Buffer, offset: Long, byteCount: Long): Buffer
[js, jvm, native]
fun copyTo(out: Buffer, offset: Long): Buffer


[jvm]
Brief description
Copy byteCount bytes from this, starting at offset, to out.
Content
@JvmOverloads()

fun copyTo(out: OutputStream, offset: Long, byteCount: Long): Buffer


emit [js, jvm, native]
Content
[js, jvm, native]
open override fun emit(): Buffer


emitCompleteSegments [js, jvm, native]
Content
[js, jvm, native]
open override fun emitCompleteSegments(): Buffer


equals [js, jvm, native]
Content
[js, jvm, native]
open operator override fun equals(other: Any?): Boolean


exhausted [js, jvm, native]
Content
[js, jvm, native]
open override fun exhausted(): Boolean


flush [js, jvm, native]
Content
[js, jvm, native]
open override fun flush()


get [js, jvm, native]
Content
[js, native]
operator fun get(pos: Long): Byte
[jvm]
@JvmName(name = “getByte”)

operator fun get(pos: Long): Byte


hashCode [js, jvm, native]
Content
[js, jvm, native]
open override fun hashCode(): Int


hmacSha1 [jvm]
Brief description
Returns the 160-bit SHA-1 HMAC of this buffer.
Content
fun hmacSha1(key: ByteString): ByteString


hmacSha256 [jvm]
Brief description
Returns the 256-bit SHA-256 HMAC of this buffer.
Content
fun hmacSha256(key: ByteString): ByteString


hmacSha512 [jvm]
Brief description
Returns the 512-bit SHA-512 HMAC of this buffer.
Content
fun hmacSha512(key: ByteString): ByteString


indexOf [js, jvm, native]
Content
[js, jvm, native]
open override fun indexOf(b: Byte): Long
[js, native]
open override fun indexOf(b: Byte, fromIndex: Long): Long
[js, jvm, native]
open override fun indexOf(b: Byte, fromIndex: Long, toIndex: Long): Long
[js, jvm, native]
open override fun indexOf(bytes: ByteString): Long
[js, jvm, native]
open override fun indexOf(bytes: ByteString, fromIndex: Long): Long


[jvm]
Brief description
Returns the index of b in this at or beyond fromIndex, or -1 if this buffer does not contain b in that range.
Content
open override fun indexOf(b: Byte, fromIndex: Long): Long


indexOfElement [js, jvm, native]
Content
[js, jvm, native]
open override fun indexOfElement(targetBytes: ByteString): Long
[js, jvm, native]
open override fun indexOfElement(targetBytes: ByteString, fromIndex: Long): Long


inputStream [jvm]
Brief description
Returns an input stream that reads from this source.
Content
open override fun inputStream(): InputStream


isOpen [jvm]
Content
open override fun isOpen(): Boolean


md5 [jvm]
Brief description
Returns the 128-bit MD5 hash of this buffer.
Content
fun md5(): ByteString


outputStream [jvm]
Brief description
Returns an output stream that writes to this sink.
Content
open override fun outputStream(): OutputStream


peek [js, jvm, native]
Content
[js, jvm, native]
open override fun peek(): BufferedSource


rangeEquals [js, jvm, native]
Content
[js, jvm, native]
open override fun rangeEquals(offset: Long, bytes: ByteString): Boolean
[js, jvm, native]
open override fun rangeEquals(offset: Long, bytes: ByteString, bytesOffset: Int, byteCount: Int): Boolean


read [js, jvm, native]
Content
[js, jvm, native]
open override fun read(sink: ByteArray): Int
[js, jvm, native]
open override fun read(sink: ByteArray, offset: Int, byteCount: Int): Int
[js, jvm, native]
open override fun read(sink: Buffer, byteCount: Long): Long
[jvm]
open override fun read(sink: ByteBuffer): Int


readAll [js, jvm, native]
Content
[js, jvm, native]
open override fun readAll(sink: Sink): Long


readAndWriteUnsafe [jvm]
Content
@JvmOverloads()

fun readAndWriteUnsafe(unsafeCursor: Buffer.UnsafeCursor): Buffer.UnsafeCursor


readByte [js, jvm, native]
Content
[js, jvm, native]
open override fun readByte(): Byte


readByteArray [js, jvm, native]
Content
[js, jvm, native]
open override fun readByteArray(): ByteArray
[js, jvm, native]
open override fun readByteArray(byteCount: Long): ByteArray


readByteString [js, jvm, native]
Content
[js, jvm, native]
open override fun readByteString(): ByteString
[js, jvm, native]
open override fun readByteString(byteCount: Long): ByteString


readDecimalLong [js, jvm, native]
Content
[js, jvm, native]
open override fun readDecimalLong(): Long


readFrom [jvm]
Brief description
Read and exhaust bytes from input into this.
Content
fun readFrom(input: InputStream): Buffer


[jvm]
Brief description
Read byteCount bytes from input into this.
Content
fun readFrom(input: InputStream, byteCount: Long): Buffer


readFully [js, jvm, native]
Content
[js, jvm, native]
open override fun readFully(sink: Buffer, byteCount: Long)
[js, jvm, native]
open override fun readFully(sink: ByteArray)


readHexadecimalUnsignedLong [js, jvm, native]
Content
[js, jvm, native]
open override fun readHexadecimalUnsignedLong(): Long


readInt [js, jvm, native]
Content
[js, jvm, native]
open override fun readInt(): Int


readIntLe [js, jvm, native]
Content
[js, jvm, native]
open override fun readIntLe(): Int


readLong [js, jvm, native]
Content
[js, jvm, native]
open override fun readLong(): Long


readLongLe [js, jvm, native]
Content
[js, jvm, native]
open override fun readLongLe(): Long


readShort [js, jvm, native]
Content
[js, jvm, native]
open override fun readShort(): Short


readShortLe [js, jvm, native]
Content
[js, jvm, native]
open override fun readShortLe(): Short


readString [jvm]
Brief description
Removes all bytes from this, decodes them as charset, and returns the string.
Content
open override fun readString(charset: Charset): String


[jvm]
Brief description
Removes byteCount bytes from this, decodes them as charset, and returns the string.
Content
open override fun readString(byteCount: Long, charset: Charset): String


readUnsafe [jvm]
Content
@JvmOverloads()

fun readUnsafe(unsafeCursor: Buffer.UnsafeCursor): Buffer.UnsafeCursor


readUtf8 [js, jvm, native]
Content
[js, jvm, native]
open override fun readUtf8(): String
[js, jvm, native]
open override fun readUtf8(byteCount: Long): String


readUtf8CodePoint [js, jvm, native]
Content
[js, jvm, native]
open override fun readUtf8CodePoint(): Int


readUtf8Line [js, jvm, native]
Content
[js, jvm, native]
open override fun readUtf8Line(): String?


readUtf8LineStrict [js, jvm, native]
Content
[js, jvm, native]
open override fun readUtf8LineStrict(): String
[js, jvm, native]
open override fun readUtf8LineStrict(limit: Long): String


request [js, jvm, native]
Content
[js, jvm, native]
open override fun request(byteCount: Long): Boolean


require [js, jvm, native]
Content
[js, jvm, native]
open override fun require(byteCount: Long)


select [js, jvm, native]
Content
[js, jvm, native]
open override fun select(options: ): Int


sha1 [jvm]
Brief description
Returns the 160-bit SHA-1 hash of this buffer.
Content
fun sha1(): ByteString


sha256 [jvm]
Brief description
Returns the 256-bit SHA-256 hash of this buffer.
Content
fun sha256(): ByteString


sha512 [jvm]
Brief description
Returns the 512-bit SHA-512 hash of this buffer.
Content
fun sha512(): ByteString


skip [js, jvm, native]
Content
[js, jvm, native]
open override fun skip(byteCount: Long)


snapshot [js, jvm, native]
Content
[js, jvm, native]
fun snapshot(): ByteString
[js, jvm, native]
fun snapshot(byteCount: Int): ByteString


timeout [js, jvm, native]
Content
[js, jvm, native]
open override fun timeout(): Timeout


toString [js, jvm, native]
Brief description
Returns a human-readable string that describes the contents of this buffer. Typically this is a string like [text=Hello] or [hex=0000ffff].
Content
[js, jvm, native]
open override fun toString():


write [js, jvm, native]
Content
[js, jvm, native]
open override fun write(byteString: ByteString): Buffer
[js, jvm, native]
open override fun write(byteString: ByteString, offset: Int, byteCount: Int):
[js, jvm, native]
open override fun write(source: ByteArray): Buffer
[js, jvm, native]
open override fun write(source: ByteArray, offset: Int, byteCount: Int): Buffer
[js, jvm, native]
open override fun write(source: Source, byteCount: Long): Buffer
[js, jvm, native]
open override fun write(source: Buffer, byteCount: Long)
[jvm]
open override fun write(source: ByteBuffer): Int


writeAll [js, jvm, native]
Content
[js, jvm, native]
open override fun writeAll(source: Source): Long


writeByte [js, jvm, native]
Content
[js, jvm, native]
open override fun writeByte(b: Int): Buffer


writeDecimalLong [js, jvm, native]
Content
[js, jvm, native]
open override fun writeDecimalLong(v: Long): Buffer


writeHexadecimalUnsignedLong [js, jvm, native]
Content
[js, jvm, native]
open override fun writeHexadecimalUnsignedLong(v: Long): Buffer


writeInt [js, jvm, native]
Content
[js, jvm, native]
open override fun writeInt(i: Int): Buffer


writeIntLe [js, jvm, native]
Content
[js, jvm, native]
open override fun writeIntLe(i: Int): Buffer


writeLong [js, jvm, native]
Content
[js, jvm, native]
open override fun writeLong(v: Long): Buffer


writeLongLe [js, jvm, native]
Content
[js, jvm, native]
open override fun writeLongLe(v: Long): Buffer


writeShort [js, jvm, native]
Content
[js, jvm, native]
open override fun writeShort(s: Int): Buffer


writeShortLe [js, jvm, native]
Content
[js, jvm, native]
open override fun writeShortLe(s: Int): Buffer


writeString [jvm]
Content
open override fun writeString(string: String, charset: Charset): Buffer
open override fun writeString(string: String, beginIndex: Int, endIndex: Int, charset: Charset): Buffer


writeTo [jvm]
Brief description
Write byteCount bytes from this to out.
Content
@JvmOverloads()

fun writeTo(out: OutputStream, byteCount: Long): Buffer


writeUtf8 [js, jvm, native]
Content
[js, jvm, native]
open override fun writeUtf8(string: String): Buffer
[js, jvm, native]
open override fun writeUtf8(string: String, beginIndex: Int, endIndex: Int): Buffer


writeUtf8CodePoint [js, jvm, native]
Content
[js, jvm, native]
open override fun writeUtf8CodePoint(codePoint: Int): Buffer


Properties

Name Summary
buffer [js, jvm, native] open override val buffer: Buffer
size [js, jvm, native] var size: Long