OutputStream
Общая практика завершения работы с потоком вывода заключается в вызове flush() + close(). Для некоторых потоков эти методы могут ничего не делать, как у ByteArrayOutputStream. Но никто еще не был уволен за вызов этой комбинации. close() стоит вызывать в finally секции, в close() могут освобождаться важные системные ресурсы (FileOutputStream - может вызывать освобождение ресурсов операционной системы, связанных с файлом).
Запись всего массива байтов производится методом write(byte[]).
Запись диапазона из массива байтов производится методом write(byte[], int, int). Обратите внимание: второй аргумент - это индекс левого конца, но третий аргумент - это длина диапазона, а не индекс правого конца.
Заметьте, что запись массива и диапазона - безусловны (т.е. либо будут записаны все данные, либо будет инициирована исключительная ситуация - обе ситуации могут произойти после задержки/"залипания"/блокирования метода). Чтение из OutputStream (read(byte[]), read(byte[], int, int)) может не заполнить весь массив данными.
close() - производит "закрытие" потока вывода.
ПОЛНАЯ ВЕРСИЯ:
с) кроме буферизации добавьте чтение в массив (read(byte[]) или read(byte[], int, int)) + запись массивом (write(byte[] или write(byte[], int, int))).
P.S. Для заметного ускорения проводите тестирование на большом (более 1Мб).
OutputStream - это абстракция байтового потока вывода, т.е. способа писать/выводить байты. Возможны и другие абстракции, но именно такой класс был выбран для java.io.*.
Абстрактный класс OutputStream имеет 5 методов: три для записи - write(int), write(byte[]), write(byte[], int, int), и два для завершения - flush(), close().
Надо понимать, что есть контракт класса OutputStream, а есть контракт конкретного наследника. Они могут не совпадать, но контракты наследников не могут противоречить контракту предка! Т.е. код, написанный для работы с предком, должен корректно работать с любым потомком.
Надо понимать, что есть контракт класса OutputStream, а есть контракт конкретного наследника. Они могут не совпадать, но контракты наследников не могут противоречить контракту предка! Т.е. код, написанный для работы с предком, должен корректно работать с любым потомком.
В общем случае, предполагается, что у потока вывода есть два состояние - "готов к записи" и "закрыт" (по факту, может быть всего единственное состояние, как у ByteArrayOutputStream - "Closing a ByteArrayOutputStream has no effect", flush() - унаследован от OutputStream, тоже ничего не делает). У потока вывода нет состояния "новый", это выражается в том, что нет методов init()/open()/connect()/start()/... Сразу же после создания, поток готов к записи. После вызова close() - поток закрыт. Невозможно повторно открыть закрытый поток.
Общая практика завершения работы с потоком вывода заключается в вызове flush() + close(). Для некоторых потоков эти методы могут ничего не делать, как у ByteArrayOutputStream. Но никто еще не был уволен за вызов этой комбинации. close() стоит вызывать в finally секции, в close() могут освобождаться важные системные ресурсы (FileOutputStream - может вызывать освобождение ресурсов операционной системы, связанных с файлом).
"Пишущие" методы
Запись одного байта производится методом write(int). По ряду причин (TODO: каких?) сигнатура метода имеет параметр типа int, а не типа byte. Тут происходит нетривиальное (TODO: какое?) преобразование - байт лежит в диапазоне [-128,127], а преобразуется в значение int в диапазоне [0, 255].Запись всего массива байтов производится методом write(byte[]).
Запись диапазона из массива байтов производится методом write(byte[], int, int). Обратите внимание: второй аргумент - это индекс левого конца, но третий аргумент - это длина диапазона, а не индекс правого конца.
Заметьте, что запись массива и диапазона - безусловны (т.е. либо будут записаны все данные, либо будет инициирована исключительная ситуация - обе ситуации могут произойти после задержки/"залипания"/блокирования метода). Чтение из OutputStream (read(byte[]), read(byte[], int, int)) может не заполнить весь массив данными.
"Завершающий" методы
flush() - производит "сбрасывание" данных, если таковые "застряли" в потоке вывода. Основной пример "застревания" - буферизация. Можно вызывать много раз подряд. После вызова поток вывода готов к продолжению записи данных.close() - производит "закрытие" потока вывода.
УПРОЩЕННАЯ ВЕРСИЯ:
package java.io;
public class OutputStream {
public void write(int b) throws IOException;
public void write(byte b[]) throws IOException;
public void write(byte b[], int off, int len) throws IOException;
public void flush() throws IOException {}
public void close() throws IOException {}
}
ПОЛНАЯ ВЕРСИЯ:
package java.io;
public abstract class OutputStream implements Closeable, Flushable {
public abstract void write(int b) throws IOException;
public void write(byte b[]) throws IOException {
write(b, 0, b.length);
}
public void write(byte b[], int off, int len) throws IOException {
...
for (int i = 0 ; i < len ; i++) {
write(b[off + i]);
}
}
public void flush() throws IOException {}
public void close() throws IOException {}
}
Лабораторные
io.streams.remove_zero
import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Arrays; public class BAOSTest { public static void main(String[] args) throws IOException { ByteArrayOutputStream buff = new ByteArrayOutputStream(); buff.write(0); buff.write(1); buff.write(2); byte[] arr = buff.toByteArray(); System.out.println(Arrays.toString(arr)); } }
Написать программу, которая вычитывает файл и записывает файл, удаляя все байты равные 0.
а) добавьте в текущую программу корректное завершение работы c потоками(flush(), close()) + гарантированные вызов close() ОБОИХ потоков даже в случае IOException.
б) добавьте буферизацию (BufferedInputStream + BufferedOutputStream) в чтение из и запись в файл. Сравните время работы без буфера и с буфером размером 1, 2, 4, 8, ..., 1024 байта.с) кроме буферизации добавьте чтение в массив (read(byte[]) или read(byte[], int, int)) + запись массивом (write(byte[] или write(byte[], int, int))).
P.S. Для заметного ускорения проводите тестирование на большом (более 1Мб).