2020-10-04
- Fix: Don't corrupt the
Buffer
when writing a slice of a segmentedByteString
. We had a severe bug whereByteString
instances created withsnapshot()
andreadByteString()
incorrectly adjusted the buffer's size by their full length, not the length of the slice. This would have caused buffer reads to crash! We do not believe data was silently corrupted. - New:
CipherSink
andCipherSource
. Use these withjavax.crypto.Cipher
to encrypt and decrypt streams of data. This is a low-level encryption API; most applications should use higher-level APIs like TLS when available. - New: Promote hash functions
md5
,sha1()
,sha512()
, andsha256()
to common Kotlin. These are currently only available onByteString
, multiplatform support forHashingSource
,HashingSink
, andBuffer
should come in a follow-up release. We wrote and optimized our own implementations of these hash functions in Kotlin. On JVM and Android platforms Okio still uses the platform's built-in hash functions. - New: Support OSGi metadata.
- Upgrade: Kotlin 1.4.10.
2020-08-17
- New: Upgrade to Kotlin 1.4.0.
2020-07-07
-
New:
Pipe.cancel()
causes in-progress and future reads and writes on the pipe to immediately fail with anIOException
. The streams may still be canceled normally. -
New: Enlarge Okio's internal segment pool from a fixed 64 KiB total to 64 KiB per processor. For example, on an Intel i9 8-core/16-thread machine the segment pool now uses up to 1 MiB of memory.
-
New: Migrate from
synchronized
to lock-free when accessing the segment pool. Combined with the change above we saw throughput increase 3x on a synthetic benchmark designed to create contention.
2020-04-22
- New:
InflaterSource.readOrInflate()
is likeInflaterSource.read()
, except it will return 0 if consuming deflated bytes from the underlying stream did not produce new inflated bytes.
2020-03-20
- New: Upgrade to Kotlin 1.3.70.
2019-12-20
- New: Upgrade to Kotlin 1.3.61.
2019-12-11
- Fix: Don't crash when an
InputStream
source is exhausted exactly at a buffer segment boundary. We had a bug where a sequence of reads could violate a buffer's invariants, and this could result in a crash when subsequent reads encountered an unexpected empty segment.
2019-12-11
- Fix: Don't crash when an
InputStream
source is exhausted exactly at a buffer segment boundary. We had a bug where a sequence of reads could violate a buffer's invariants, and this could result in a crash when subsequent reads encountered an unexpected empty segment.
2019-10-04
- Fix: Don't cache hash code and UTF-8 string in
ByteString
on Kotlin/Native which prevented freezing.
2019-08-26
- New: Upgrade to Kotlin 1.3.50.
2019-07-29
This release changes our build from Kotlin-JVM to Kotlin-multiplatform (which includes JVM). Both native and JavaScript platforms are unstable preview releases and subject to backwards-incompatible changes in forthcoming releases.
To try Okio in a multiplatform project use this Maven coordinate:
api('com.squareup.okio:okio-multiplatform:2.3.0')
You’ll also need to enable Gradle metadata in your project's settings. The artifact name for JVM projects has not changed.
- New: Upgrade to Kotlin 1.3.40.
- Fix: Use Gradle
api
instead ofimplementation
for the kotlin-stdlib dependency. - Fix: Don't block unless strictly necessary in
BufferedSource.peek()
.
2019-04-29
- Fix: Don't block unless strictly necessary in
BufferedSource.peek()
.
2019-01-28
- Fix: Make
Pipe.fold()
close the underlying sink when necessary.
2019-01-28
- Fix: Make
Pipe.fold()
close the underlying sink when necessary.
2019-01-17
- Fix: Make
Pipe.fold()
flush the underlying sink.
2019-01-17
- Fix: Make
Pipe.fold()
flush the underlying sink.
2019-01-16
-
New:
Throttler
limits sources and sinks to a maximum desired throughput. Multiple sources and sinks can be attached to the same throttler and their combined throughput will not exceed the desired throughput. Multiple throttlers can also be used on the same source or sink and they will all be honored. -
New:
Pipe.fold()
replaces the actively-readableSource
with a passively-writableSink
. This can be used to forward one sink to a target that is initially undetermined. -
New: Optimize performance of ByteStrings created with
Buffer.snapshot()
.
2019-01-16
- Fix: Make the newly-backported
Pipe.fold()
public.
2019-01-16
- New: Backport
Pipe.fold()
to Okio 1.x.
2018-10-08
- New: Backport
BufferedSource.peek()
andBufferedSource.getBuffer()
to Okio 1.x. - Fix: Enforce timeouts when closing
AsyncTimeout
sources.
2018-09-22
-
New:
BufferedSource.peek()
returns anotherBufferedSource
that reads ahead on the current source. Use this to process the same data multiple times. -
New: Deprecate
BufferedSource.buffer()
, replacing it with eitherBufferedSource.getBuffer()
(in Java) orBufferedSource.buffer
(in Kotlin). We have done likewise forBufferedSink
. When we introduced the new extension methodSource.buffer()
in Okio 2.0 we inadvertently collided with an existing method. This fixes that. -
New: Improve performance of
Buffer.writeUtf8()
. This comes alongside initial implementation of UTF-8 encoding and decoding in JavaScript which uses XOR masks for great performance.
2018-08-27
This release commits to a stable 2.0 API. Read the 2.0.0-RC1 changes for advice on upgrading from 1.x to 2.x.
We've also added APIs to ease migration for Kotlin users. They use Kotlin's @Deprecated
annotation
to help you change call sites from the 1.x style to the 2.x style.
2018-07-26
Okio 2 is a major release that upgrades the library's implementation language from Java to Kotlin.
Okio 2.x is binary-compatible with Okio 1.x and does not change any behavior. Classes and .jar files compiled against 1.x can be used with 2.x without recompiling.
Okio 2.x is .java source compatible with Okio 1.x in all but one corner case. In Okio 1.x
Buffer
would throw an unchecked IllegalStateException
when attempting to read more bytes than
available. Okio 2.x now throws a checked EOFException
in this case. This is now consistent with
the behavior of its BufferedSource
interface. Java callers that don't already catch IOException
will now need to.
Okio 2.x is .kt source-incompatible with Okio 1.x. This release adopts Kotlin idioms where they are available.
Java | Kotlin | Idiom |
---|---|---|
Buffer.getByte() | operator fun Buffer.get() | operator function |
Buffer.size() | val Buffer.size | val |
ByteString.decodeBase64(String) | fun String.decodeBase64() | extension function |
ByteString.decodeHex(String) | fun String.decodeHex() | extension function |
ByteString.encodeString(String, Charset) | fun String.encode(Charset) | extension function |
ByteString.encodeUtf8(String) | fun String.encodeUtf8() | extension function |
ByteString.getByte() | operator fun ByteString.get() | operator function |
ByteString.of(ByteBuffer) | fun ByteBuffer.toByteString() | extension function |
ByteString.of(byte[], int, int) | fun ByteArray.toByteString() | extension function |
ByteString.read(InputStream, int) | fun InputStream.readByteString(Int) | extension function |
ByteString.size() | val ByteString.size | val |
DeflaterSink(Sink) | fun Sink.deflater() | extension function |
ForwardingSink.delegate() | val ForwardingSink.delegate | val |
ForwardingSource.delegate() | val ForwardingSource.delegate | val |
GzipSink(Sink, Deflater) | fun Sink.gzip() | extension function |
GzipSink.deflater() | val GzipSink.deflater | val |
GzipSource(Source) | fun Source.gzip() | extension function |
HashingSink.hash() | val HashingSink.hash | val |
HashingSource.hash() | val HashingSource.hash | val |
InflaterSink(Source) | fun Source.inflater() | extension function |
Okio.appendingSink(File) | fun File.appendingSink() | extension function |
Okio.blackhole() | fun blackholeSink() | top level function |
Okio.buffer(Sink) | fun Sink.buffer() | extension function |
Okio.buffer(Source) | fun Source.buffer() | extension function |
Okio.sink(File) | fun File.sink() | extension function |
Okio.sink(OutputStream) | fun OutputStream.sink() | extension function |
Okio.sink(Path) | fun Path.sink() | extension function |
Okio.sink(Socket) | fun Socket.sink() | extension function |
Okio.source(File) | fun File.source() | extension function |
Okio.source(InputStream) | fun InputStream.source() | extension function |
Okio.source(Path) | fun Path.source() | extension function |
Okio.source(Socket) | fun Socket.source() | extension function |
Pipe.sink() | val Pipe.sink | val |
Pipe.source() | val Pipe.source | val |
Utf8.size(String) | fun String.utf8Size() | extension function |
Okio 2.x has similar performance to Okio 1.x. We benchmarked both versions to find potential
performance regressions. We found one regression and fixed it: we were using ==
instead of ===
.
Other changes in this release:
-
New: Add a dependency on kotlin-stdlib. Okio's transitive dependencies grow from none in 1.x to three in 2.x. These are kotlin-stdlib (939 KiB), kotlin-stdlib-common (104 KiB), and JetBrains' annotations (17 KiB).
-
New: Change Okio to build with Gradle instead of Maven.
2018-07-18
- New: Trie-based
Buffer.select()
. This improves performance when selecting among large lists of options. - Fix: Retain interrupted state when throwing
InterruptedIOException
.
2018-02-11
- New:
Buffer.UnsafeCursor
provides direct access to Okio internals. This API is like Okio's version of Java reflection: it's a very powerful API that can be used for great things and dangerous things alike. The documentation is extensive and anyone using it should review it carefully before proceeding! - New: Change
BufferedSource
to implementjava.nio.ReadableByteChannel
andBufferedSink
to implementjava.nio.WritableByteChannel
. Now it's a little easier to interop between Okio and NIO. - New: Automatic module name of
okio
for use with the Java Platform Module System. - New: Optimize
Buffer.getByte()
to search backwards when doing so will be more efficient. - Fix: Honor the requested byte count in
InflaterSource
. Previously this class could return more bytes than requested. - Fix: Improve a performance bug in
AsyncTimeout.sink().write()
.
2017-05-12
-
Okio now uses
@Nullable
to annotate all possibly-null values. We've added a compile-time dependency on the JSR 305 annotations. This is a provided dependency and does not need to be included in your build configuration,.jar
file, or.apk
. We use@ParametersAreNonnullByDefault
and all parameters and return types are never null unless explicitly annotated@Nullable
. -
Warning: this release is source-incompatible for Kotlin users. Nullability was previously ambiguous and lenient but now the compiler will enforce strict null checks.
2017-04-11
- Fix: Change Pipe's sink.flush() to not block. Previously closing a pipe's sink would block until the source had been exhausted. In practice this blocked the caller for no benefit.
- Fix: Change
writeUtf8CodePoint()
to emit?
for partial surrogates. The previous behavior was inconsistent: given a malformed string with a partial surrogate,writeUtf8()
emitted?
butwriteUtf8CodePoint()
threw anIllegalArgumentException
. Most applications will never encounter partial surrogates, but for those that do this behavior was unexpected. - New: Allow length of
readUtf8LineStrict()
to be limited. - New:
Utf8.size()
method to get the number of bytes required to encode a string as UTF-8. This may be useful for length-prefixed encodings. - New: SHA-512 hash and HMAC APIs.
2016-10-11
- Fix: The four-argument overload of
Buffer.writeString()
had a major bug where it didn't respect offsets if the specified charset was UTF-8. This was because our short-circuit optimization omitted necessary offset parameters. - New: HMAC support in
HashingSource
,HashingSink
,ByteString
, andBuffer
. This makes it easy to create a keyed-hash message authentication code (HMAC) wherever your data is. Unlike the other hashes, HMAC uses aByteString
secret key for authentication. - New:
ByteString.of(ByteBuffer)
makes it easier to mix NIO with Okio.
2016-08-28
- Fix: Support reading files larger than 2 GiB with
GzipSource
. Previously attempting to decompress such files would fail due to an overflow when validating the total length. - Fix: Exit the watchdog thread after being idle for 60 seconds. This should make it possible for class unloaders to fully unload Okio.
- New:
Okio.blackhole()
returns a sink where all bytes written are discarded. This is Okio's equivalent of/dev/null
. - New: Encode a string with any charset using
ByteString.encodeString()
and decode strings in any charset usingByteString.string()
. Most applications should preferByteString.encodeUtf8()
andByteString.utf8()
unless it's necessary to support a legacy charset. - New:
GzipSink.deflater()
makes it possible to configure the compression level.
2016-07-01
- New:
Pipe
makes it easy to connect a producer thread to a consumer thread. Reads block until data is available to read. Writes block if the pipe's is full. Both sources and sinks support timeouts. - New:
BufferedSource.rangeEquals()
makes it easy to compare a range in a stream to an expected value. This does the right thing: it blocks to load the data required return a definitive result. But it won't block unnecessarily. - New:
Timeout.waitUntilNotified()
makes it possible to use nice timeout abstractions on Java's built-in wait/notify primitives. - Fix: Don't return incorrect results when
HashingSource
does large reads. There was a bug where it wasn't traversing through the segments of the buffer being hashed. This means thatHashingSource
was returning incorrect answers for any writes that spanned multiple segment boundaries.
2016-05-02
- New:
BufferedSource.select(Options)
API for reading one of a set of expected values. - New: Make
ByteString.toString()
andBuffer.toString()
friendlier. These methods return text if the byte string is valid UTF-8. - New: APIs to match byte strings:
indexOf()
,startsWith()
, andendsWith()
.
2016-04-10
- New: Change the segment size to 8 KiB. This has been reported to dramatically improve performance in some applications.
- New:
md5()
,sha1()
, andsha256()
methods onBuffer
. Also add asha1()
method onByteString
for symmetry. - New:
HashingSource
andHashingSink
. These classes are Okio’s equivalent to the JDK’sDigestInputStream
andDigestOutputStream
. They offer convenientmd5()
,sha1()
, andsha256()
factory methods to avoid an impossibleNoSuchAlgorithmException
. - New:
ByteString.asByteBuffer()
. - Fix: Limit snapshot byte strings to requested size.
- Fix: Change write timeouts to have a maximum write size. Previously large writes could easly suffer timeouts because the entire write was subject to a single timeout.
- Fix: Recover from EBADF failures, which could be triggered by asynchronously closing a stream on older versions of Android.
- Fix: Don't share segments if doing so only saves a small copy. This should improve performance for all applications.
- Fix: Optimize
BufferedSource.indexOfElement()
andindexOf(ByteString)
. Previously this method had a bug that caused it to be very slow on large buffers.
2015-08-25
- New:
BufferedSource.indexOf(ByteString)
searches a source for the next occurrence of a byte string. - Fix: Recover from unexpected
AssertionError
thrown on Android 4.2.2 and earlier when asynchronously closing a socket.
2015-06-19
- Sockets streams now throw
SocketTimeoutException
. This builds on new extension point inAsyncTimeout
to customize the exception when a timeout occurs. - New:
ByteString
now implementsComparable
. The comparison sorts bytes as unsigned: {@code ff} sorts after {@code 00}.
2015-05-16
- Timeout exception changed. Previously
Timeout.throwIfReached()
would throwInterruptedIOException
on thread interruption, andIOException
if the deadline was reached. Now it throwsInterruptedIOException
in both cases. - Fix: throw
EOFException
when attempting to read digits from an empty source. Previously this would crash with an unchecked exception. - New: APIs to read and write UTF-8 code points without allocating strings.
- New:
BufferedSink
can now write substrings directly, potentially saving an allocation for some callers. - New:
ForwardingTimeout
class.
2015-03-16
- New: Read and write signed decimal and unsigned hexadecimal values in
BufferedSource
andBufferedSink
. Unlike the alternatives, these methods don’t do any memory allocations! - New: Segment sharing. This improves the runtime of operations like
Buffer.clone()
andBuffer.copyTo()
by sharing underlying segments between buffers. - New:
Buffer.snapshot()
returns an immutable snapshot of a buffer as aByteString
. This builds on segment sharing so that snapshots are shallow, immutable copies. - New:
ByteString.rangeEquals()
. - New:
ByteString.md5()
andByteString.sha256()
. - New:
ByteString.base64Url()
returns URL-safe Base64. The existing decoding method has been extended to support URL-safe Base64 input. - New:
ByteString.substring()
returns a prefix, infix, or suffix. - New:
Sink
now implementsjava.io.Flushable
. - Fix:
Buffer.write(Source, long)
now always writes fully. The previous behavior would return as soon as any data had been written; this was inconsistent with all other write() methods in the API. - Fix: don't leak empty segments in DeflaterSink and InflaterSource. (This was unlikely to cause problems in practice.)
2014-12-30
- Fix:
Okio.buffer()
always buffers for better predictability. - Fix: Provide context when
readUtf8LineStrict()
throws. - Fix: Buffers do not call through the
Source
on zero-byte writes.
2014-12-11
- Do UTF-8 encoding natively for a performance increase, particularly on Android.
- New APIs:
BufferedSink.emit()
,BufferedSource.request()
andBufferedSink.indexOfElement()
. - Fixed a performance bug in
Buffer.indexOf()
2014-08-08
- Added
read(byte[])
,read(byte[], offset, byteCount)
, andvoid readFully(byte[])
toBufferedSource
. - Refined declared checked exceptions on
Buffer
methods.
2014-05-23
- Bumped release version. No other changes!
2014-05-03
- Use 0 as a sentinel for no timeout.
- Make AsyncTimeout public.
- Remove checked exception from Buffer.readByteArray.
2014-04-24
- Eagerly verify preconditions on public APIs.
- Quick return on Buffer instance equivalence.
- Add delegate types for Sink and Source.
- Small changes to the way deadlines are managed.
- Add append variant of Okio.sink for File.
- Methods to exhaust BufferedSource to byte[] and ByteString.
2014-04-18
- Don't use getters in timeout.
- Use the watchdog to interrupt sockets that have reached deadlines.
- Add java.io and java.nio file source/sink helpers.
2014-04-17
- Methods to read a buffered source fully in UTF-8 or supplied charset.
- API to read a byte[] directly.
- New methods to move all data from a source to a sink.
- Fix a bug on input stream exhaustion.
2014-04-15
- Make ByteString serializable.
- New API:
ByteString.of(byte[] data, int offset, int byteCount)
- New API: stream-based copy, write, and read helpers.
2014-04-08
- Initial public release.
- Imported from OkHttp.