Java2определяет два типа потоков: байтовый и символьный. Байтовые потоки предоставляют удобные средства для обработки ввода и вывода байт. Байтовые потоки используются, например, при чтении или записи данных в двоичном коде. Символьные потоки предоставляют удобные средства для обработки ввода и вывода символов. Они используют Unicodeи поэтому могут быть интернационализированы. Кроме того, в некоторых случаях символьные потоки более эффективны, чем байтовые. Первоначальная версия Java(Java1.0) не включала символьные потоки, и таким образом, весь ввод/вывод был байтовым. Символьные потоки были добавлены в Java1.1, а некоторые байтовые классы и методы были исключены.
Байтовые потоки определяются в двух иерархиях классов. Наверху этой иерархии — два абстрактных класса: InputStreamи OutputStream. Каждый из этих абстрактных классов имеет несколько конкретных подклассов (табл. 1.2), которые обрабатывают различия между разными устройствами, такими, как дисковые файлы, сетевые соединения и даже буферы памяти.
Абстрактные классы InputStreamи OutputStreamопределяют несколько ключевых методов, которые реализуются другими поточными классами. Два наиболее важных— read()и write(), которые соответственно читают и записывают байты данных. Оба метода объявлены как абстрактные внутри классов InputStreamи OutputStreamи переопределяются производными поточными классами.
Поточный класс |
Назначение |
InputStream OutputStream |
Абстрактные классы, которые описывают поточный ввод и вывод |
BufferedInputStream BufferedOutputStream |
Буферизированный поток ввода и вывода |
ByteArrayInputStream ByteArrayOutputStream |
Поток ввода, который читает из байт-массива Поток вывода, который записывает в байт-массив |
FileInputStream FileOutputStream |
Поток ввода, который читает из файла Поток вывода, который записывает в файл |
RandomAccessFile |
Поддерживает ввод/вывод файла произвольного доступа |
Символьные потоки определены в двух иерархиях классов. Наверху этой иерархии два абстрактных класса: Readerи Writer. Они обрабатывают потоки символов Unicode. В Javaсуществуют несколько конкретных подклассов каждого из них. Классы Readerи Writer– наследники InputStreamи OutputStream. Если с их помощью записывать или считывать текст, то сначала необходимо сопоставить каждому символу его числовой код. Такое соответствие называется кодировкой. Классы символьных потоков показаны в таблице 1.3.
Абстрактные классы Readerи Writerопределяют несколько ключевых методов, которые реализуются другими поточными классами. Два самых важных метода — read()и write(), которые читают и записывают символы данных, соответственно. Они переопределяются производными поточными классами.
Символьный класс |
Назначение |
Reader Writer |
Абстрактные классы символьного потока ввода и вывода |
BufferedReader BufferedWriter |
Буферизированные символьные потоки ввода и вывода |
FileReader FileWriter |
Поток ввода, который читает поток символов из файла; Выходной поток, который записывает символы в файл |
StringReader StringWriter |
Поток ввода, который читает из строки; Поток вывода, который записывает в строку |
PrintWriter |
Поток вывода, который поддерживает методы print() и println() |
Известно, что Java использует кодировку Unicode, в которой символы представляются двухбайтным кодом. Байтовые потоки зачастую работают с текстом упрощенно – они просто отбрасывают старший байт каждого символа. В реальных же приложениях они могут использовать различные кодировки (даже для русского языка их существует несколько). Поэтому в версии Java 1.1 появился дополнительный набор классов, основывающийся на типах Reader и Writer.
Эта иерархия очень схожа с аналогичной для байтовых потоков InputStream и OutputStream. Главное отличие между ними – Readerи Writerработают с потоком символов (char). Только чтение массива символов в Reader описывается методом read(char[]), а запись в Writer– write(char[]).