— Привіт, Аміго! Сьогодні ми знову будемо займатися розбором роботи InputStream та OutputStream. Насправді те перше пояснення було трохи спрощеним. Це не інтерфейси, а абстрактні класи і вони навіть мають по парі реалізованих методів. Давай подивимося, які методи вони мають:

Методи класу InputStream Що метод робить
int read(byte[] buff);
— метод одразу читає блок байт в буфер (масив байт), покибуфер не заповниться або не закінчаться байти там, звідки він їх читає.
Метод повертає кількість реально прочитаних байт (воно може бути меншим за довжину масиву)
int read();
— метод читає один байт та повертає його як результат. Результат розширюється до int для краси. Якщо всі байти вже прочитані, метод поверне «-1».
int available();
— метод повертає кількість непрочитаних (доступних) байт.
void close();
— метод «закриває» потік – викликається після закінчення роботи з потоком.
Об'єкт виконує службові операції, пов'язані із закриттям файлу на диску тощо.
З потоку більше не можна читати дані.

— Тобто. ми можемо читати не лише по одному байту, а й цілими блоками?

— Так.

— А записувати цілими блоками також можна?

— Так, ось дивись:

Методи OutputStream Що метод робить
void write(int c);< /code>
— Метод записує один байт інформації. Тип int звужується до byte, зайва частина просто відкидається.
void write(byte[] buff) ;
— метод записує блок байт.
void write(byte[] buff, int from, int count);
— метод записує частина блоку байт. Використовується у випадках, коли є можливість, що блок даних був заповнений не повністю
void flush();
— якщо є дані, які зберігаються десь усередині та ще не записані, то вони записуються.
void close();
— метод «закриває» потік – викликається після закінчення роботи з потоком.
Об'єкт виконує службові операції, пов'язані із закриттям файлу на диску і т.д. У потік більше не можна писати дані, flush при цьому викликається автоматично.

— А як виглядатиме код копіювання файлу, якщо ми читатимемо не по одному байту, а цілими блоками?

— Гм. Приблизно так:

Копіюємо файл на диску
public static void main(String[] args) throws Exception
{
 //Створюємо потік-читання-байт-з-файлу
 FileInputStream inputStream = new FileInputStream("c:/data.txt");
 // Створюємо потік-записи-байт-в-файл
 FileOutputStream outputStream = new FileOutputStream("c:/result.txt");

  byte[] buffer = new byte[1000];
 while (inputStream.available() > 0) //поки є ще непрочитані байти
 {
  // прочитати черговий блок байт у змінну buffer та реальну кількість у count
  int count = inputStream.read(buffer );
  outputStream.write(buffer, 0, count); //записати блок(частина блоку) у другий потік
 }

 inputStream.close(); //закриваємо обидва потоки. Вони більше не потрібні.
 outputStream.close();
}

— З буфером все зрозуміло, а що це за змінна count?

— Коли ми читаємо останній блок даних у файлі, може виявитися, що байт залишилося не 1000, а, скажімо, 328. Тоді і при записі потрібно вказати, що записати не весь блок, а тільки його перші 328 байт.

Метод read при читанні останнього блоку поверне значення, що дорівнює кількості реально прочитаних байт. Для всіх читань – 1000, а для останнього блоку – 328.

Тому при записі блоку ми вказуємо, що потрібно записати не всі байти з буфера, а лише 328 (тобто значення, яке зберігається в змінній count).

— Тепер зрозуміло, як це все працює. Дякую, Еллі.