класи застосовуються таким чином: створюється по об'єкту PipedInputStream і PipedOutputStream, після чого вони можуть бути з'єднані між собою. Один об'єкт PipedOutputStream може бути з'єднаний з рівно одним об'єктом PipedInputStream, і навпаки. Потім в об'єкт PipedOutputStream записуються дані, після чого вони можуть бути лічені саме в підключеному об'єкті PipedInputStream. Таке з'єднання можна забезпечити або викликом методу connect () з передачею відповідного об'єкта PipedI/OStream (будемо так кратно позначати пару класів, в даному випадку PipedInputStream і PipedOutputStream), або передати цей об'єкт ще при виклику конструктора. Використання зв'язки PipedInputStream і PipedOutputStream показано в наступному прикладі:
try {countRead = 0; [] toRead = new byte [100]; pipeIn = new PipedInputStream (); pipeOut = new PipedOutputStream (pipeIn);
// Зчитувати в масив, поки він повністю не буде заповнений (countRead
// Записати в потік деяку кількість байт
for (int i = 0; i <(Math.random () * 10); i + +) {. write ((byte) (Math.random () * 127));
}
// Вважати з потоку доступні дані,
// додати їх до вже ліченим.
int willRead = pipeIn.available (); (willRead + countRead> toRead.length)
// Треба вважати тільки до межі масиву
willRead = toRead.length-countRead; + = pipeIn.read (toRead, countRead, willRead);
}
} catch (IOException e) {. out.println ("Impossible IOException occur:");. printStackTrace ();
}
Даний приклад носить чисто демонстративний характер (в результаті його роботи масив toRead буде заповнений випадковими числами). Більш явно вигода від використання PipedI/OStream в основному проявляється при розробці багатопотокового додатку. Якщо в програмі запускається кілька потоків виконання, організувати передачу даних між ними зручно за допомогою цих класів. Для цього потрібно створити зв'язані об'єкти PipedI/OStream, після чого передати посилання на них у відповідні потоки. Потік виконання, в якому проводиться читання даних, може містити подібний код:
// inStream - об'єкт класу PipedInputStream {(true) {[] readedBytes = null; (inStream) {bytesAvailable = inStream.available (); = new byte [bytesAvailable];. read (readedBytes) ;
}
// обробка даних з readedBytes
// ...
} catch (IOException e) {
/* IOException буде кинуто, коли потік inStream, або
пов'язаний з ним PipedOutputStream, вже закрито, і при цьому
проводиться спроба зчитування з inStream * /. out.println ("робота з потоком inStream завершена");
}
Якщо з об'єктом inStream одночасно можуть працювати кілька потоків виконання, то необхідно використовувати блок synchronized (як і зроблено в прикладі), який гарантує, що в період між викликами inStream.available () і inStream.read ( ...) ні в якому іншому потоці виконання не проводитиметься зчитування з inStream. Тому виклик inStream.read (readedBytes) не приведе до блокування і всі дані, готові до зчитування, будуть лічені. p align="justify"> Клас StringBufferInputStream
Іноді буває зручно працювати з текстовим рядком String як з потоком байт. Для цього можна скористатися класом StringBufferInputStream. При створенні об'єкта цього класу необхідно передати конструктору об'єкт String. Дані, що повертаються методом read (), будуть зчитуватися саме з цього рядка. При цьому символи будуть перетворюватися в байти з втратою точності - старший байт відкидається (нагадаємо, що символ char складається з двох байт). p align="justify"> Клас SequenceInputStream
Клас SequenceInputStream об'єднує потік даних з інших двох і більше вхідних потоків. Дані будуть вичитуватися послідовно - спочатку всі дані з першого потоку в списку, потім з другого, і так далі. Кінець потоку SequenceInputStream буде досягнутий тільки тоді, коли буде досягнуто кінець потоку, останнього в списку. p align="justify"> У цьому класі є два конструктора - приймаюче два потоки і приймає Enumeration (у якому, звичайно, повинні бути тільки екземпляри InputStream і його спадкоємців). Коли викликається метод read (), SequenceInputStream намагається вважати байт з поточного вхідного потоку. Якщо в ньому більше даних немає (лічену з нього значення дорівнює -1), у нього викликається метод close () і наступний вхідний потік стає поточним. Так продовжується до тих пір, поки не будуть отримані всі дані з ос...