Android inputstream read buffer

Класс InputStream

Базовый класс InputStream представляет классы, которые получают данные из различных источников:

  • массив байтов
  • строка (String)
  • файл
  • канал (pipe): данные помещаются с одного конца и извлекаются с другого
  • последовательность различных потоков, которые можно объединить в одном потоке
  • другие источники (например, подключение к интернету)

Для работы с указанными источниками используются подклассы базового класса InputStream:

BufferedInputStream Буферизированный входной поток ByteArrayInputStream Позволяет использовать буфер в памяти (массив байтов) в качестве источника данных для входного потока. DataInputStream Входной поток, включающий методы для чтения стандартных типов данных Java FileInputStream Для чтения информации из файла FilterInputStream Абстрактный класс, предоставляющий интерфейс для классов-надстроек, которые добавляют к существующим потокам полезные свойства. InputStream Абстрактный класс, описывающий поток ввода ObjectInputStream Входной поток для объектов StringBufferInputStream Превращает строку (String) во входной поток данных InputStream PipedInputStream Реализует понятие входного канала. PushbackInputStream Входной поток, поддерживающий однобайтовый возврат во входной поток SequenceInputStream Сливает два или более потока InputStream в единый поток

  • int available() — возвращает количество байтов ввода, доступные в данный момент для чтения
  • close() — закрывает источник ввода. Следующие попытки чтения передадут исключение IOException
  • void mark(int readlimit) — помещает метку в текущую точку входного потока, которая остаётся корректной до тех пор, пока не будет прочитано readlimint байт
  • boolean markSupported() — возвращает true, если методы mark() и reset() поддерживаются потоком
  • int read() — возвращает целочисленное представление следующего доступного байта в потоке. При достижении конца файла возвращается значение -1
  • int read(byte[] buffer) — пытается читать байты в буфер, возвращая количество прочитанных байтов. По достижении конца файла возвращает значение -1
  • int read(byte[] buffer, int byteOffset, int byteCount) — пытается читать до byteCount байт в buffer, начиная с смещения byteOffset. По достижении конца файла возвращает -1
  • reset() — сбрасывает входной указатель в ранее установленную метку
  • long skip(long byteCount) — пропускает byteCount байт ввода, возвращая количество проигнорированных байтов

Как преобразовать InputStream в строку

  1. Using IOUtils.toString (Apache Utils):
  2. Using CharStreams (guava)
  3. Using Scanner (JDK)
    символ «\А» является символом начала текста, таким образом вызов next() вернет сразу всю строку.
  4. Using Stream Api (Java 8). Warning: This solution convert different linebreaks (like \r\n) to \n.
  5. Using parallel Stream Api (Java 8). Warning: This solution convert different linebreaks (like \r\n) to \n.
  6. Using InputStreamReader and StringBuilder (JDK)
  7. Using StringWriter and IOUtils.copy (Apache Commons)
  8. Using ByteArrayOutputStream and inputStream.read (JDK)
  9. Using BufferedReader (JDK). Warning: This solution convert different linebreaks (like \n\r) to line.separator system property (for example, in Windows to «\r\n»).
  10. Using BufferedInputStream and ByteArrayOutputStream (JDK)
  11. Using inputStream.read() and StringBuilder (JDK). Warning: This soulition has problem with Unicode, for example with Russian text (work correctly only with non-Unicode text)

Warning:
Solutions 4, 5 and 9 convert different linebreaks to one.
Soulution 11 can’t work correclty with Unicode text

BufferedInputStream

Буферизация ввода-вывода является удобным способом оптимизации производительности, позволяя заключить в оболочку любой поток класса InputStream.

У класса есть конструктор, где размер буфера устанавливается по умолчанию. Также можно использовать конструктор, где размер буфера устанавливается вручную. Рекомендуется использовать размеры буфера, кратные размеру страницы памяти, дисковому блоку и т.п. и может зависеть от принимающей операционной системы, объёма доступной памяти и конфигурации машины.

Читайте также:  Deus ex the fall версия для андроид

ByteArrayInputStream

Класс ByteArrayInputStream использует байтовый массив в качестве источника данных. У данного класса можно не вызывать метод close().

DataInputStream — Форматированное чтение из памяти

Для чтения байтовых данных (не строк) применяется класс DataInputStream. В этом случае необходимо использовать классы из группы InputStream.

Для преобразования строки в массив байтов, пригодный для помещения в поток ByteArrayInputStream, в классе String предусмотрен метод getBytes(). Полученный ByteArrayInputStream представляет собой поток InputStream, подходящий для передачи DataInputStream.

При побайтовом чтении символов из форматированного потока DataInputStream методом readByte() любое полученное значение будет считаться действительным, поэтому возвращаемое значение неприменимо для идентификации конца потока. Вместо этого можно использовать метод available(), который сообщает, сколько еще осталось символов.

Класс DataInputStream позволяет читать элементарные данные из потока через интерфейс DataInput, который определяет методы, преобразующие элементарные значения в форму последовательности байтов. Такие потоки облегчают сохранение в файле двоичных данных.

FileInputStream

Класс FileInputStream создаёт объект класса InputStream, который можно использовать для чтения байтов из файла.

  • FileInputStream (File file) — указывается объекта типа File
  • FileInputStream (FileDescriptor fd)
  • FileInputStream (String path) — указывается полное имя файла

При создании объект открывается для чтения. Класс переопределяет методы класса InputStream, кроме методов mark() и reset().

Для чтения байтов входного потока из файла используется конструкция:

PushbackInputStream

Разновидность буферизации, обеспечивающая чтение байта с последующим его возвратом в поток. Класс PushbackInputStream представляет механизм «заглянуть» во входной поток и увидеть, что оттуда поступит в следующий раз, не извлекая информации.

У класса есть дополнительный метод unread().

SequenceInputStream

Класс SequenceInputStream позволяет соединять вместе несколько экземпляров класса InputStream. Конструктор принимает в качестве аргумента либо пару объектов класса InputStream, либо интерфейс Enumeration.

Во время работы класс выполняет запросы на чтение из первого объекта класса InputStream и до конца, а затем переключается на второй. При использовании интерфейса работа продолжится по всем объектам класса InputStream. По достижении конца каждого файла, связанный с ним поток закрывается. Закрытие потока, созданного объектом класса SequenceInputStream, приводит к закрытию всех открытых потоков.

Источник

InputStream

java.lang.Object
java.io.InputStream
Known Direct Subclasses
AssetManager.AssetInputStream
BackupDataInputStream Provides an InputStream -like interface for accessing an entity’s data during a restore operation.
ByteArrayInputStream A specialized InputStream for reading the contents of a byte array.
FileInputStream An input stream that reads bytes from a file.
FilterInputStream Wraps an existing InputStream and performs some transformation on the input data while it is being read.
ObjectInputStream A specialized InputStream that is able to read (deserialize) Java objects as well as primitive data types (int, byte, char etc.).
PipedInputStream Receives information from a communications pipe.
SequenceInputStream Concatenates two or more existing InputStream s.
StringBufferInputStream This class was deprecated in API level 1. Use StringReader instead.
AssetFileDescriptor.AutoCloseInputStream An InputStream you can create on a ParcelFileDescriptor, which will take care of calling ParcelFileDescritor.close() for you when the stream is closed.
Base64InputStream An InputStream that does Base64 decoding on the data read through it.
BufferedInputStream Wraps an existing InputStream and buffers the input.
CheckedInputStream The CheckedInputStream class is used to maintain a checksum at the same time as the data, on which the checksum is computed, is read from a stream.
CipherInputStream This class wraps an InputStream and a cipher so that read() methods return data that are read from the underlying InputStream and processed by the cipher.
DataInputStream Wraps an existing InputStream and reads big-endian typed data from it.
DeflaterInputStream An InputStream filter to compress data.
DigestInputStream DigestInputStream is a FilterInputStream which maintains an associated message digest.
GZIPInputStream The GZIPInputStream class is used to read data stored in the GZIP format, reading and decompressing GZIP data from the underlying stream into its buffer.
InflaterInputStream This class provides an implementation of FilterInputStream that decompresses data that was compressed using the DEFLATE algorithm (see specification).
JarInputStream The input stream from which the JAR file to be read may be fetched.
LineNumberInputStream This class was deprecated in API level 1. Use LineNumberReader instead.
ParcelFileDescriptor.AutoCloseInputStream An InputStream you can create on a ParcelFileDescriptor, which will take care of calling ParcelFileDescriptor.close() for you when the stream is closed.
PushbackInputStream Wraps an existing InputStream and adds functionality to «push back» bytes that have been read, so that they can be read again.
ZipInputStream Used to read (decompress) the data from zip files.

Class Overview

A readable source of bytes.

Most clients will use input streams that read data from the file system ( FileInputStream ), the network ( getInputStream() / getInputStream() ), or from an in-memory byte array ( ByteArrayInputStream ).

Use InputStreamReader to adapt a byte stream like this one into a character stream.

Most clients should wrap their input stream with BufferedInputStream . Callers that do only bulk reads may omit buffering.

Some implementations support marking a position in the input stream and resetting back to this position later. Implementations that don’t return false from markSupported() and throw an IOException when reset() is called.

Subclassing InputStream

All input stream subclasses should override both read() and read(byte[],int,int) . The three argument overload is necessary for bulk access to the data. This is much more efficient than byte-by-byte access.

See Also

Summary

Public Constructors

public InputStream ()

This constructor does nothing. It is provided for signature compatibility.

Public Methods

public int available ()

Returns an estimated number of bytes that can be read or skipped without blocking for more input.

Note that this method provides such a weak guarantee that it is not very useful in practice.

Firstly, the guarantee is «without blocking for more input» rather than «without blocking»: a read may still block waiting for I/O to complete — the guarantee is merely that it won’t have to wait indefinitely for data to be written. The result of this method should not be used as a license to do I/O on a thread that shouldn’t be blocked.

Secondly, the result is a conservative estimate and may be significantly smaller than the actual number of bytes available. In particular, an implementation that always returns 0 would be correct. In general, callers should only use this method if they’d be satisfied with treating the result as a boolean yes or no answer to the question «is there definitely data ready?».

Thirdly, the fact that a given number of bytes is «available» does not guarantee that a read or skip will actually read or skip that many bytes: they may read or skip fewer.

It is particularly important to realize that you must not use this method to size a container and assume that you can read the entirety of the stream without needing to resize the container. Such callers should probably write everything they read to a ByteArrayOutputStream and convert that to a byte array. Alternatively, if you’re reading from a file, length() returns the current length of the file (though assuming the file’s length can’t change may be incorrect, reading a file is inherently racy).

The default implementation of this method in InputStream always returns 0. Subclasses should override this method if they are able to indicate the number of bytes available.

Источник

Android чтение из входного потока эффективно

Я делаю запрос HTTP get на веб-сайт для приложения android, которое я делаю.

Я использую DefaultHttpClient и использую HttpGet для выдачи запроса. Я получаю ответ сущности и из этого получаю объект InputStream для получения html страницы.

затем я прокручиваю ответ, делая следующее:

однако это ужасно медленно.

это неэффективно? Я не загружаю большую веб-страницу — www.cokezone.co.uk чтобы размер файла не большой. Есть ли лучший способ сделать это?

12 ответов

проблема в вашем коде заключается в том, что он создает много тяжелой String объекты, копирование их содержимого и выполнение над ними операций. Вместо этого, вы должны использовать StringBuilder чтобы избежать создания новых String объекты на каждом добавлении и во избежание копирования массивов символов. Реализация для вашего случая будет примерно такой:

теперь вы можете использовать total без преобразования его в String , но если вам нужен результат как String , просто добавить:

результат строки = всего.toString ();

я постараюсь объяснить это лучше.

  • a += b (или a = a + b ), где a и b являются строками, копирует содержимое и a и b на новый объект (обратите внимание, что вы также копирования a , которая содержит набрал String ), и вы делаете эти копии на каждой итерации.
  • a.append(b) , где a это StringBuilder , непосредственно добавляет b содержимое a , поэтому вы не копируете накопленную строку на каждой итерации.

вы пробовали встроенный метод для преобразования потока в строку? Это часть библиотеки Apache Commons (org.Апачи.общее.Ио.IOUtils).

тогда ваш код будет в одну строку:

библиотека Apache Commons IO можно загрузить из здесь: http://commons.apache.org/io/download_io.cgi

еще одна возможность с Guava:

зависимость: compile ‘com.google.guava:guava:11.0.2’

Я считаю, что это достаточно эффективно. Чтобы получить строку из InputStream, я бы вызвал следующий метод:

Я всегда использую UTF-8. Вы можете, конечно, установить charset в качестве аргумента, помимо InputStream.

Как насчет этого. Кажется, дает лучшую производительность.

Edit: на самом деле этот вид охватывает как steelbytes, так и Maurice Perry

возможно, несколько быстрее, чем ответ Хайме Сориано, и без многобайтовых проблем кодирования ответа Адриана, я предлагаю:

возможно, вместо того, чтобы читать «по одной строке за раз» и присоединяться к строкам, попробуйте «прочитать все доступные», чтобы избежать сканирования конца строки, а также избежать соединения строк.

ie, InputStream.available() и InputStream.read(byte[] b), int offset, int length)

чтение одной строки текста за раз, и добавление этой строки к строке по отдельности занимает много времени как при извлечении каждой строки, так и при накладных расходах на так много вызовов методов.

я смог получить лучшую производительность, выделив массив байтов приличного размера для хранения потоковых данных, который при необходимости итеративно заменяется большим массивом и пытается прочитать столько, сколько может содержать массив.

по какой-то причине Android неоднократно не удалось загрузите весь файл, когда код использовал InputStream, возвращенный HTTPUrlConnection, поэтому мне пришлось прибегнуть к использованию как BufferedReader, так и ручного механизма тайм-аута, чтобы гарантировать, что я получу весь файл или отменю передачу.

EDIT: оказывается, что если вам не нужно повторно кодировать контент (т. е. вы хотите, чтобы контент КАК) вы не должны использовать ни один из подклассов Reader. Просто используйте соответствующий поток производный класс.

замените начало предыдущего метода соответствующими строками следующего, чтобы ускорить его дополнительно 2-3 раза.

Если файл длинный, вы можете оптимизировать свой код, добавляя к StringBuilder вместо использования конкатенации строк для каждой строки.

Источник

Читайте также:  Телефонные вирусы андроид виды
Оцените статью