Потоки вводу / виводу пакету java.Io

Окрім стандартних потоків вводу / виводу мова програмування Java пропонує пакет java.io, що містить у собі набір класів, призначених для створення більш спеціалізованих потоків вводу / виводу. Цей пакет містить два абстрактних класа java.io.InputStream i java.io.OutputStream, що є суперкласами для усіх інших класів, що реалізують потоки. Перший клас використовується для прийому даних, а другий - для запису. Обидва класи є похідними від класа Object. Ієрархія класів пакету java.io виглядає так:

  • Object
    • InputStream
      • FileInputStream
      • StringBufferedInputStream
      • ByteArrayInputStream
      • SequenceInputStream
      • PipedInputStream
        • FIlterInputStream
          • DataInputStream
          • BufferedInputStream
          • LineNumberInputStream
          • PushbackInputStream
    • OutputStream
      • FileOutputStream
      • ByteArrayOutputStream
      • PipedOutputStream
        • FIlterOutputStream
          • DataOutputStream
          • BufferedOutputStream
          • PrintStream

Файловий ввод / вивід

Для організації виводу у файл і вводу з файлу призначені два класи

  • FileInputStream
  • FileOutputStream

Приклад:

InputStream myFile1 = new FileInputStream( "\\dir\\file1.txt"); FileDescriptor myF = myFile1.getFD(); InputStream myFile2 = new FileInputStream( myF);

Ім'я файлу, що вказується при створенні потоків не залежить від платформи, на якої виконується додаток. JVM автоматично перетворює ім'я та шлях до файлу у формат, прийнятний для даної платформи. Для роботи з файлами використовується клас java.io.File. Він призначений для організації доступу до файлів, створення нових файлів, перейменування та видалення файлів. Наступний фрагмент програмного коду ілюструє операції читання ізапису до файлу:

import java.io.*; public class ReadWriteFile { public static void main( String args[]) { int rbyte = 0; FileInputStream readFile; FileOutputStream writeFile; try { readFile = new FileInputStream( "File1.txt"); writeFile = new FileOutputStream( "File2.txt"); try { while ((rbyte = readFile.read()) != -1) { System.out.print( Integer.toHexString( rbyte) + " "); writeFile.write( rbyte); } } catch (IOException ioe) { System.out.println( "Unable to write: " + ioe.toString()); System.exit( 0); } } catch (FileNotFoundException fnfe1) { System.out.println( "Unable to Find Input File: " + fnfe1.toString()); System.exit( 0); } } }

Рядковий ввод / вивід

Для створення потоку вводу, що читає дані з рядка використовується клас StringReader. Приклад його використання наведено нижче:

import java.io.*; public class TestStringIo { public static void main( String args[]) { String s = new String( "String from Stream"); int bt = 0; StringReader mStr = new StringReader( s); try { while ((bt = mStr.read()) != -1) { System.out.print( (char)bt); } System.out.println(); } catch (IOException e) { System.out.println( "Unable to read: " + e.toString()); } } }

Для запису даних у рядок використовується клас StringWriter.

Завдання:

Напишить паралельну програму, яка читає вхідний файл filename1 і записує його у стандартний вихід, а також у файл filename2, тобто створює дві копії вхідних даних. Распаралельте вашу програму так, щоб вона використовувала три процеси: читання із файлу filename1, запису у стандартний вивід и запису у файл filename.

Рекомендація:
Для виконання цього завдання треба створити головний клас, у якому будуть створені (за допомогою оператора new) і запущені на виконання три класи потоків, що виконують процеси читання даних з дискового файлу, запису їх у новий файл, та виводу на консоль.

public class MultiCopy { TextBuffer buffer; MultiCopy() { System.out.println( "MultiCopy:MultiCopy()"); buffer = new TextBuffer(); WriteFile wf = new WriteFile( "File3.txt", buffer); PrintFile pf = new PrintFile( buffer); ReadFile rf = new ReadFile( "File1.txt", buffer, wf); rf.start(); wf.start(); pf.start(); } public static void main( String args[]) { System.out.println( "main"); MultiCopy mc = new MultiCopy(); } }

Передача даних між цима потоками (класами) відбувається через четвертий клас, що виконує функції буферу.

class TextBuffer { int bufferByte; TextBuffer() { System.out.println( "TextBuffer:TextBuffer()"); bufferByte = 0; } public synchronized void setBufferByte( int b) { System.out.println( "TextBuffer:setBufferByte() \r"); bufferByte = b; } public synchronized int getBufferByte() { System.out.println( "TextBuffer:getBufferByte() \r"); return( bufferByte); } }

У цьому класі потрібно визначити методи, за допомогою яких будуть відбуватися процеси наповнення буферу, та читання з нього. Оскільки ці методи у кожний конкретний проміжок часу можуть бути використані тільки одним единим потоком, то їх треба декларувати, як синхронізовані (synchronized).

Синхронізацію потоків можна виконати за допомогою методів wait() та notify(). За допомогою методу notify() поток, що читає дані з вхідного файлу та записує їх до буферу, повідомляє інші потоки про те, що дані вже знаходяться у буфері та доступні для считування.

class ReadFile implements Runnable { FileInputStream readFile; Thread ReadThread; TextBuffer tb = null; WriteFile writeFile; ReadFile( String fileName, TextBuffer b, WriteFile wf) { tb = b; writeFile = wf; try { readFile = new FileInputStream( fileName); } catch (FileNotFoundException fnfe1) { System.out.println( "Unable to Find Input File: " + fnfe1.toString()); System.exit( 0); } } public void start() { System.out.println( "ReadFile:start()"); ReadThread = new Thread( this); ReadThread.start(); } public void stop() { System.out.println( "ReadFile:stop()"); if (ReadThread != null) { ReadThread = null; } } public void run() { int rbyte; System.out.println( "ReadFile:run()"); try { while ((rbyte = readFile.read()) != -1) { tb.setBufferByte( rbyte); synchronized( writeFile) { writeFile.notify(); } try { Thread.sleep( 50); } catch (InterruptedException ee) { System.out.println( "Interrupted Exception: " + ee.toString()); } } tb.setBufferByte( -1); synchronized( writeFile) { writeFile.notify(); } } catch (IOException ioe) { System.out.println( "Unable to read: " + ioe.toString()); } } }

Інші потоки чекають це повідомлення за допомогою методу wait().

class WriteFile implements Runnable { FileOutputStream writeFile; Thread WriteThread; TextBuffer tb = null; WriteFile( String fileName, TextBuffer b) { System.out.println( "WriteFile:WriteFile()"); tb = b; try { writeFile = new FileOutputStream( fileName); } catch (FileNotFoundException fnfe1) { System.out.println( "Unable to Find Output File: " + fnfe1.toString()); System.exit( 0); } } public void start() { System.out.println( "WriteFile:start()"); WriteThread = new Thread( this); WriteThread.start(); } public void stop() { System.out.println( "WriteFile:stop()"); if (WriteThread != null) { WriteThread = null; } } public synchronized void run() { int rbyte; System.out.println( "WriteFile:run()"); try { do { try { wait(); } catch (InterruptedException ee) { System.out.println( "Interrupted Exception: " + ee.toString()); } rbyte = tb.getBufferByte(); writeFile.write( rbyte); } while (rbyte != -1); } catch (IOException ioe) { System.out.println( "Unable to write: " + ioe.toString()); } } }

Лабораторна робота №8.

Наши рекомендации