Explain Codes LogoExplain Codes Logo

Android Reading from an Input stream efficiently

java
input-stream
buffer-size
string-builder
Anton ShumikhinbyAnton Shumikhin·Dec 4, 2024
TLDR

In Android, efficient input stream reading can be achieved by leveraging the BufferedInputStream class in combination with a sensibly sized buffer. This strategy accelerates the performance by reducing the number of disk reads. You can implement it like this:

BufferedInputStream bis = new BufferedInputStream(inputStream); byte[] buffer = new byte[8192]; // The Goldilocks buffer size – just right! while ((bis.read(buffer)) != -1) { // Insert clever data processing here ;-) } bis.close();

The essence here is bulk reads and buffers—they are your road to efficiency. The selected buffer size (set at 8KB here) is significant. It helps strike a balance between memory usage and the reduction of I/O operations.

Understanding buffer size

Selecting an efficient buffer size is an art. Too small, and you end up waking the I/O operations every other microsecond. Too large, you get awarded the "Wasting Memory" badge. Profile on several target devices to find your ideal buffer size.

Meet StringBuilder, your new best friend

The StringBuilder class is your secret weapon for efficiently dealing with character data. It shuns the hassles associated with creating a new String object every other second. Here's how to use it:

InputStreamReader isr = new InputStreamReader(inputStream, StandardCharsets.UTF_8); BufferedReader br = new BufferedReader(isr); StringBuilder sb = new StringBuilder(); String line; while ((line = br.readLine()) != null) { sb.append(line); } br.close(); String result = sb.toString(); // Admire your sleek String!

This design pattern uses InputStreamReader and BufferedReader as layers of decoration on our InputStream for efficient character reading. We then amass the characters in a StringBuilder.

Leveraging libraries for streamlining

Consider adding some steroids to your code —aka using Battle-tested libraries like Apache Commons IO or Google Guava:

  • With Apache Commons IO, IOUtils.toString(inputStream, charset) can convert an InputStream into a String in one easy step.
  • With Guava, ByteStreams.toByteArray(inputStream) converts an InputStream into a byte array rapidly.

Here's how:

String result = IOUtils.toString(inputStream, StandardCharsets.UTF_8); // We're on easy street! // or byte[] byteArray = ByteStreams.toByteArray(inputStream); // Just bytes, nothing to see here!

Remember, using these methods could ramp up your app's size, so make sure the benefits outweigh the costs.

Don’t forget to cover your exceptions

Always remember to handle those unwanted party guests, the IOExceptions, neatly:

try (BufferedInputStream bis = new BufferedInputStream(inputStream)) { // Here be dragons... and code } catch (IOException e) { // Something went wrong, time to panic... or just handle it. }

Employing the try-with-resources statement ensures the BufferedInputStream scrams when it's not needed, keeping your memory squeaky clean.