README.android
README.md
1Okio
2====
3
4Okio is a new library that complements `java.io` and `java.nio` to make it much
5easier to access, store, and process your data.
6
7ByteStrings and Buffers
8-----------------------
9
10Okio is built around two types that pack a lot of capability into a
11straightforward API:
12
13 * [**ByteString**][3] is an immutable sequence of bytes. For character data, `String`
14 is fundamental. `ByteString` is String's long-lost brother, making it easy to
15 treat binary data as a value. This class is ergonomic: it knows how to encode
16 and decode itself as hex, base64, and UTF-8.
17
18 * [**Buffer**][4] is a mutable sequence of bytes. Like `ArrayList`, you don't need
19 to size your buffer in advance. You read and write buffers as a queue: write
20 data to the end and read it from the front. There's no obligation to manage
21 positions, limits, or capacities.
22
23Internally, `ByteString` and `Buffer` do some clever things to save CPU and
24memory. If you encode a UTF-8 string as a `ByteString`, it caches a reference to
25that string so that if you decode it later, there's no work to do.
26
27`Buffer` is implemented as a linked list of segments. When you move data from
28one buffer to another, it _reassigns ownership_ of the segments rather than
29copying the data across. This approach is particularly helpful for multithreaded
30programs: a thread that talks to the network can exchange data with a worker
31thread without any copying or ceremony.
32
33Sources and Sinks
34-----------------
35
36An elegant part of the `java.io` design is how streams can be layered for
37transformations like encryption and compression. Okio includes its own stream
38types called [`Source`][5] and [`Sink`][6] that work like `InputStream` and
39`OutputStream`, but with some key differences:
40
41 * **Timeouts.** The streams provide access to the timeouts of the underlying
42 I/O mechanism. Unlike the `java.io` socket streams, both `read()` and
43 `write()` calls honor timeouts.
44
45 * **Easy to implement.** `Source` declares three methods: `read()`, `close()`,
46 and `timeout()`. There are no hazards like `available()` or single-byte reads
47 that cause correctness and performance surprises.
48
49 * **Easy to use.** Although _implementations_ of `Source` and `Sink` have only
50 three methods to write, _callers_ are given a rich API with the
51 [`BufferedSource`][7] and [`BufferedSink`][8] interfaces. These interfaces give you
52 everything you need in one place.
53
54 * **No artificial distinction between byte streams and char streams.** It's all
55 data. Read and write it as bytes, UTF-8 strings, big-endian 32-bit integers,
56 little-endian shorts; whatever you want. No more `InputStreamReader`!
57
58 * **Easy to test.** The `Buffer` class implements both `BufferedSource` and
59 `BufferedSink` so your test code is simple and clear.
60
61Sources and sinks interoperate with `InputStream` and `OutputStream`. You can
62view any `Source` as an `InputStream`, and you can view any `InputStream` as a
63`Source`. Similarly for `Sink` and `OutputStream`.
64
65Dependable
66----------
67
68Okio started as a component of [OkHttp][1], the capable HTTP+SPDY client
69included in Android. It's well-exercised and ready to solve new problems.
70
71
72Example: a PNG decoder
73----------------------
74
75Decoding the chunks of a PNG file demonstrates Okio in practice.
76
77```java
78private static final ByteString PNG_HEADER = ByteString.decodeHex("89504e470d0a1a0a");
79
80public void decodePng(InputStream in) throws IOException {
81 BufferedSource pngSource = Okio.buffer(Okio.source(in));
82
83 ByteString header = pngSource.readByteString(PNG_HEADER.size());
84 if (!header.equals(PNG_HEADER)) {
85 throw new IOException("Not a PNG.");
86 }
87
88 while (true) {
89 Buffer chunk = new Buffer();
90
91 // Each chunk is a length, type, data, and CRC offset.
92 int length = pngSource.readInt();
93 String type = pngSource.readUtf8(4);
94 pngSource.readFully(chunk, length);
95 int crc = pngSource.readInt();
96
97 decodeChunk(type, chunk);
98 if (type.equals("IEND")) break;
99 }
100
101 pngSource.close();
102}
103
104private void decodeChunk(String type, Buffer chunk) {
105 if (type.equals("IHDR")) {
106 int width = chunk.readInt();
107 int height = chunk.readInt();
108 System.out.printf("%08x: %s %d x %d%n", chunk.size(), type, width, height);
109 } else {
110 System.out.printf("%08x: %s%n", chunk.size(), type);
111 }
112}
113```
114
115Download
116--------
117
118Download [the latest JAR][2] or grab via Maven:
119```xml
120<dependency>
121 <groupId>com.squareup.okio</groupId>
122 <artifactId>okio</artifactId>
123 <version>1.6.0</version>
124</dependency>
125```
126or Gradle:
127```groovy
128compile 'com.squareup.okio:okio:1.6.0'
129```
130
131Snapshots of the development version are available in [Sonatype's `snapshots` repository][snap].
132
133
134 [1]: https://github.com/square/okhttp
135 [2]: https://search.maven.org/remote_content?g=com.squareup.okio&a=okio&v=LATEST
136 [3]: http://square.github.io/okio/okio/ByteString.html
137 [4]: http://square.github.io/okio/okio/Buffer.html
138 [5]: http://square.github.io/okio/okio/Source.html
139 [6]: http://square.github.io/okio/okio/Sink.html
140 [7]: http://square.github.io/okio/okio/BufferedSource.html
141 [8]: http://square.github.io/okio/okio/BufferedSink.html
142 [snap]: https://oss.sonatype.org/content/repositories/snapshots/
143