- Класс InputStream
- Как преобразовать InputStream в строку
- BufferedInputStream
- ByteArrayInputStream
- DataInputStream — Форматированное чтение из памяти
- FileInputStream
- PushbackInputStream
- SequenceInputStream
- InputStream
- Class Overview
- Subclassing InputStream
- Summary
- Public Constructors
- public InputStream ()
- Public Methods
- public int available ()
- Android чтение из входного потока эффективно
- 12 ответов
Класс 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 в строку
- Using IOUtils.toString (Apache Utils):
- Using CharStreams (guava)
- Using Scanner (JDK)
символ «\А» является символом начала текста, таким образом вызов next() вернет сразу всю строку. - Using Stream Api (Java 8). Warning: This solution convert different linebreaks (like \r\n) to \n.
- Using parallel Stream Api (Java 8). Warning: This solution convert different linebreaks (like \r\n) to \n.
- Using InputStreamReader and StringBuilder (JDK)
- Using StringWriter and IOUtils.copy (Apache Commons)
- Using ByteArrayOutputStream and inputStream.read (JDK)
- Using BufferedReader (JDK). Warning: This solution convert different linebreaks (like \n\r) to line.separator system property (for example, in Windows to «\r\n»).
- Using BufferedInputStream and ByteArrayOutputStream (JDK)
- 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.
У класса есть конструктор, где размер буфера устанавливается по умолчанию. Также можно использовать конструктор, где размер буфера устанавливается вручную. Рекомендуется использовать размеры буфера, кратные размеру страницы памяти, дисковому блоку и т.п. и может зависеть от принимающей операционной системы, объёма доступной памяти и конфигурации машины.
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 |
Class OverviewA 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 InputStreamAll 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 AlsoSummaryPublic Constructorspublic InputStream ()This constructor does nothing. It is provided for signature compatibility. Public Methodspublic 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 (); я постараюсь объяснить это лучше.
вы пробовали встроенный метод для преобразования потока в строку? Это часть библиотеки 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 вместо использования конкатенации строк для каждой строки. Источник |