Java как считать данные из файла fileinputstream

Обновлено: 06.07.2024

Байтовые потоки. Классы DataInputStream , DataOutputStream , FileInputStream , FileOutputStream . Примеры использования

В данной теме продемонстрировано использование средств языка Java для работы с байтовыми потоками. Приведены примеры распространенных задач для решения которых используются классы DataInputStream , DataOutputStream , FileInputStream , FileOutputStream .

Содержание

Поиск на других ресурсах:

1. Запись и чтение одномерного массива типа int[] в байтовый файловый поток. Пример

Пусть задан одномерный массив типа int[] , который нужно:

  • записать в байтовый файловый поток;
  • прочитать из байтового файлового потока.

Для решения данной задачи хорошо подойдутклассы:

  • DataInputStream – поток ввода, который содержит методы для чтения данных стандартных типов Java, к которым принадлежит тип int ;
  • DataOutputStream – поток вывода, который содержит методы для записи данных стандартных типов, определенных в Java;
  • FileInputStream – поток ввода, который содержит методы, читающие данные из файла;
  • FileOutputStream – поток вывода, который содержит методы, записывающие данные в файл.

Чтобы организовать запись данных в файл нужно:

  • создать файловый поток типа FileOutputStream ;
  • созданный файловый поток поместить в конструктор DataOutputStream ;
  • использовать методы класса DataOutputStream для записи данных в файл.

Чтобы организовать чтение данных из файла нужно:

  • создать файловый поток типа FileInputStream ;
  • новосозданный файловый поток поместить в конструктор DataInputStream ;
  • использовать методы класса DataInputStream для чтения данных из файла.

Пример.

Результат выполнения программы

2. Запись и чтение данных разных типов ( double , int , char ). Пример
  • записать в файл последовательно значения переменных типов double , int , char ;
  • прочитать значение переменных типов double , int , char .

Результат выполнения программы

4. Пример копирования файлов с использованием байтового потока

В примере приводится фрагмент кода, который осуществляет копирование файлов. Используются средства классов FileInputStream и FileOutputStream .

В Java есть четыре основных абстрактных класса, реализующих потоки ввода-вывода: InputStream, OutputStream, Reader, Writer. Первые два работают с байтами, вторые – с символами.

Для работы с файлами от этих абстрактных классов созданы соответственно классы FileInputStream, FileOutputStream, FileReader, FileWriter. Они являются адаптерами для объектов класса File к "интерфейсам" InputStream, OutputStream, Reader, Writer, т. е. к их методам.

Скажем несколько слов об адаптере как паттерне, или шаблоне, проектирования. Класс-адаптер A наследуется от интерфейса B, к которому приспосабливается объект другого класса – C. Класс-адаптер A имеет поле типа класса объекта C.

Например, объект File адаптируется к потоку ввода InputStream, т. е. все, что мы хотим получить из File, в конечном итоге мы будем получать из InputStream. Фактически мы работаем с InputStream, через адаптер FileInputStream, который с одной стороны наследуется от InputStream, а с другой – имеет поле, которому присваивается объект File.

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

В основной ветке сначала создается объект, для которого требуется адаптер. Затем создается переменная класса, к которому выполняется адаптация. Этой переменной присваивается объект класса-адаптера, в конструктор которого передается адаптируемый объект.

Часто переменную определяют самим классом-адаптером:

В конструктор можно передать строку-адрес. Объект File будет создан внутри адаптера. Пример побайтового копирования файла:

Если используются относительные адреса, они должны начинаться от корня проекта.

В конструктор FileOutputStream можно также передать второй аргумент true. В этом случае, если файл существует, данные в него будут добавляться. Перезаписи файла не произойдет.

Метод available() объекта класса FileInputStream возвращает количество непрочитанных байтов. Метод read() читает один байт и расширяет его до типа int. Кроме этого, есть другой метод read(), читающий массив байт в переменную-аргумент и возвращающий количество реально прочитанных байт. Метод write() также позволяет записывать блоками.

При чтении конца файла блок может содержать меньше прочитанных байт, чем размерность массива. Поэтому write() позволяет указывать срез массива.

У объектов FileOutputStream имеется метод flush(), который принудительно записывает находящиеся в буфере байты на диск. При вызове close() это происходит автоматически.

С помощью класса PrintStream также можно создать поток вывода в файл. PrintStream является наследником FilterOutputStream, который в свою очередь наследник OutputStream как и FileOutputStream.

Функция printf() предназначена для форматированного вывода.

Заметим, переменная System.out является объектом типа PrintStream.

В работе с вводом-выводом также используется другой паттерн проектирования – обертка (wrapper), он же декоратор (decorator). Декоратор расширяет функциональность объекта, а не приспосабливает объект к какому-либо стороннему интерфейсу.

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

В основной ветке создается объект оборачиваемого класса, который передается в конструктор обертки. Внутри класса-обертки есть поле типа декорируемого класса. Этому полю присваивается переданный объект.

BufferedInputStream – класс-обертка для InputStream (наследует через FilterInputStream). В отличие от InputStream класс BufferedInputStream позволяет предварительно читать в буфер порции байт, что уменьшает количество обращений к файлу. Существует также BufferedOutputStream.

Конструктор класса BufferedInputStream принимает объект InputStream или его наследника.

Хотя данные считываются блоками, метод read() извлекает их по одному. Однако в данном случае он будет извлекать их из буфера.

С помощью классов FileReader и FileWriter выполняется ввод-вывод в текстовые файлы.

Метод ready() возвращает истину, если остались непрочитанные символы.

Читать и писать можно блоками. Также методу write() можно передать строку:

Рассматривая ввод данных с клавиатуры, мы уже использовали класс BufferedReader, который наследуется от Reader и позволяет читать отдельные строки методом readLine(). Его также можно использовать для построчного чтения файлов:

Ввод-вывод в Java. Классы FileInputStream, FileOutputStream, BufferedInputStream - 1

Привет! В сегодняшней лекции продолжим разговор о потоках ввода и вывода в Java, или сокращенно — Java I/O («input-output»). Это не первая лекция на данную тему, и далеко не последняя :) Так уж получилось, что Java как язык предоставляет много возможностей по работе с вводом-выводом. Классов, которые реализуют эту функциональность довольно много, поэтому мы разделили их на несколько лекций, чтобы ты поначалу не запутался :) В прошлых лекциях мы коснулись BufferedReader ’a, а также абстрактных классов InputStream & OutputStream и нескольких наследников. Сегодня рассмотрим 3 новых класса: FileInputStream , FileOutputStream и BufferedInputStream .

Класс FileOutputStream

Главное назначение класса FileOutputStream — запись байтов в файл. Ничего сложного :) FileOutputStream является одной из реализаций абстрактного класса OutputStream . В конструкторе объекты этого класса принимают либо путь к целевому файлу (в который и нужно записать байты), либо объект класса File . Рассмотрим оба примера: При создании объекта File мы указали в конструкторе путь, где он должен будет находиться. Создавать его заранее нет необходимости: если он не существует, программа создаст его сама. Можно обойтись и без создания лишнего объекта, и просто передать строку с адресом: Результат в обоих случаях будет одинаковым. Мы можем открыть наш файл и увидеть там: Однако есть здесь один нюанс. Попробуй запустить код из примера выше несколько раз подряд, а потом загляни в файл, и ответь на вопрос: сколько записанных в него строк ты видишь? Всего одну. Но ведь ты запускал код несколько раз. Однако при этом данные, оказывается, всякий раз перезаписывались, заменяя старые. Что делать, если нас это не устраивает, и требуется последовательная запись? Что если мы хотим записать наше приветствие в файл три раза подряд? Здесь все просто. Поскольку сам язык не может знать, какое именно поведение нам нужно в каждом случае, в конструктор FileOutputStream ты можешь передать дополнительный параметр — boolean append . Если его значение true, данные будут дозаписаны в конец файла. Если false (а по умолчанию это значение и есть false), старые данные будут стерты, а новые записаны. Давай проверим и запустим наш измененный код трижды: Результат в файле: Другое дело! Не забывай об этой особенности при использовании классов ввода-вывода. В свое время и мне приходилось часами сидеть над задачами, чтобы понять, куда деваются из файлов мои старые данные :) Ну и конечно, как и в случае с другими классами I/O, не забываем об освобождении ресурсов через метод close() .

Класс FileInputStream

Ввод-вывод в Java. Классы FileInputStream, FileOutputStream, BufferedInputStream - 2

У класса FileInputStream назначение противоположное — чтение байтов из файла. Так же как FileOutputStream наследует OutputStream , этот класс происходит от абстрактного класса InputStream . Запишем в наш текстовый « test.txt » несколько строк текста: Вот как будет выглядеть реализация чтения данных из файла при помощи FileInputStream : Мы считываем из файла по одному байту, преобразуем считанные байты в символы и выводим их в консоль. А вот и результат в консоли:

Класс BufferedInputStream

Думаю, учитывая знания из прошлых лекций, ты легко сможешь сказать, зачем нужен класс BufferedInputStream и какие преимущества у него есть по сравнению с FileInputStream :) Мы уже встречались с буферизированными потоками, поэтому попробуй предположить (или вспомнить), прежде чем продолжить чтение :) Буферизированные потоки нужны прежде всего для оптимизации ввода-вывода. Обращение к источнику данных, например, чтение из файла, — дорогостоящая в плане производительности операция. И каждый раз обращаться к файлу для чтения по одному байту расточительно. Поэтому BufferedInputStream считывает данные не по одному байту, а блоками и временно хранит их в специальном буфере. Это позволяет нам оптимизировать работу программы за счет того, что мы уменьшаем количество обращений к файлу. Давай посмотрим, как это выглядит: Здесь мы создали объект BufferedInputStream . Он принимает на вход объект InputStream или любого его наследника, так что предыдущий FileInputStream подойдет. В качестве дополнительного параметра он принимает размер буфера в байтах. Теперь благодаря этому данные будут считываться из файла не по одному байту, а по 200! Представь, насколько мы сократили количество обращений к файлу. Для сравнения производительности ты можешь взять какой-нибудь большой текстовый файл размером несколько мегабайт и сравнить, сколько займет его чтение и вывод в консоль в миллисекундах с использованием FileInputStream и BufferedInputStream . Вот оба варианта кода для примера: При чтении файла размером 1,5 Мб на моем компьютере FileInputStream выполнил работу за

3500 миллисекунд, а вот BufferedInputStream — за

1700 миллисекунд. Как видишь, буферизированный поток оптимизировал работу программы в 2 раза! :) Мы еще продолжим изучать классы ввода-вывода — до встречи!


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

1- FileInputStream

FileInputStream - это подкласс InputStream, который используется для чтения двоичных файлов, таких как фотографи, музыка, видео. Полученные данные являются необработанными bytes (raw bytes) . Для обычных текстовых файлов вместо этого следует использовать FileReader.


  • BufferedInputStream
  • ByteArrayInputStream
  • DataInputStream
  • InputStream
  • ObjectInputStream
  • PipedInputStream
  • PushbackInputStream
  • SequenceInputStream

Большинство методов FileInputStream наследуются от InputStream:

FileChannel getChannel()используется для возврата уникального объекта FileChannel, связанного с этим FileInputStream.
FileDescriptor getFD()используется для возврата объекта FileDescriptor.

2- Example 1

В качестве первого примера мы используем FileInputStream для чтения японского текстового файла, закодированного с помощью UTF-8:

Примечание: UTF-8 использует 1, 2, 3 или 4 bytes для хранения одного символа. Тем временем FileInputStream считывает каждый byte из файла, так что вы получите довольно странный результат.


Для чтения текстовых файлов UTF-8, UTF-16, . вы должны использовать FileReader или InputStreamReader:

View more Tutorials:

Это онлайн курс вне вебсайта o7planning, который мы представляем, он включает бесплатные курсы или курсы со скидкой.

Читайте также: