1. OutputStreamклас

Наскоро проучихме входните потоци. Време е да поговорим за изходните потоци.

Класът OutputStreamе родителският клас за всички класове, които поддържат byteов изход. Това е абстрактен клас, който не прави нищо сам, но има класове наследници за всеки случай.

Звучи изключително сложно. Казано по-просто, този клас оперира с byteове, а не, например, със знаци or други типове данни. А фактът, че е абстрактен, означава, че обикновено не го използваме, а по-скоро един от неговите потомствени класове. Например FileOutputStreamи други подобни.

Но обратно към OutputStreamкласа. Този клас има методи, които всички негови класове-потомци трябва да изпълняват. Ето основните от тях:

Методи Описание
void write(int b)
Записва един byte (не int) в потока.
void write(byte[] buffer)
Записва масив от byteове в потока
void write(byte[] buffer, off, len)
Записва част от масив от byteове в потока
void flush()
Записва всички данни, съхранени в буфера, в потока
void close()
Затваря потока

Когато създавате обект от клас, който наследява InputStream, обикновено посочвате обект източник, InputStreamот който чете данни. Когато създавате обект от клас, който наследява OutputStream, обикновено посочвате и целевия обект or поток, в който ще се записват данни.

Нека прегледаме накратко всички методи на OutputStreamкласа:

write(int b)метод

Този метод записва един byte (не int) в изходния поток. Предадената стойност се преобразува в byte и първите три byteа на int се отхвърлят.

write(byte[] buffer)метод

Записва дадения масив от byteове в изходния поток. Това е.

write(byte[] buffer, int offset, int length)метод

Записва част от предадения масив от byteове в изходния поток. Променливата offset показва индекса на първия елемент от масива и lengthе дължината на подмножеството, което трябва да се запише.

flush()метод

Методът flush()се използва, за да принуди всички данни, потенциално буферирани в текущия поток, да бъдат записани в целевия поток. Това е уместно при използване на буфериране и/or множество обекти на поток, подредени във верига.

close()метод

Записва всички незаписани данни в целевия обект. Методът close()не трябва да се извиква, ако използвате try-with-resourcesблок.

Пример за копиране на файл

Код Забележка
String src = "c:\\projects\\log.txt";
String dest = "c:\\projects\\copy.txt";

try(FileInputStream input = new FileInputStream(src);
FileOutputStream output = new FileOutputStream(dest))
{
   byte[] buffer = new byte[65536]; // 64Kb
   while (input.available() > 0)
   {
      int real = input.read(buffer);
      output.write(buffer, 0, real);
   }
}



InputStreamза четене от файл
OutputStreamза запис във файл

Буфер, в който ще четем данните
Докато има данни в потока

Прочетете данни в буфера
Запишете данните от буфера във втория поток

2. Writerклас

Класът Writerе абсолютно същият като OutputStreamкласа, но само с една разлика още веднъж: работи със знаци ( char) instead of с byteове.

Това е абстрактен клас: не можете да създавате обекти от Writerкласа. Основната му цел е да бъде общ родителски клас за стотици наследствени класове и да им даде общи методи за работа с потоци от символи.

Методи на Writerкласа (и всички негови потомствени класове):

Методи Описание
void write(int b)
Записва един символ (не int) в потока.
void write(char[] buffer)
Записва масив от знаци в потока
void write(char[] buffer, off, len)
Записва част от масив от знаци в потока
void write(String str)
Записва низ в потока
void write(String str, off, len)
Записва част от низ в потока
void flush()
Записва всички данни, съхранени в буфера, в потока
void close()
Затваря потока

Методите са много подобни на методите на OutputStreamкласа, но работят със символи instead of с byteове.

Описание на методите:

write(int b)метод

Този метод записва един знак ( char— не int) в изходния поток. Предадената стойност се преобразува в a charи първите два byteа се отхвърлят.

write(char[] buffer)метод

Записва дадения масив от знаци в изходния поток.

write(char[] buffer, int offset, int length)метод

Записва част от предадения масив от знаци в изходния поток. Променливата offsetпоказва индекса на първия елемент от масива и lengthе дължината на подмножеството, което трябва да се запише.

write(String str)метод

Записва дадения низ в изходния поток.

write(String str, int offset, int length)метод

Записва част от дадения низ в изходния поток: низът се преобразува в масив от знаци. Променливата offsetпоказва индекса на първия елемент от масива и lengthе дължината на подмножеството, което трябва да се запише.

flush()метод

Методът flush()се използва, за да принуди всички данни, потенциално буферирани в текущия поток, да бъдат записани в целевия поток. Това е уместно при използване на буфериране и/or множество обекти на поток, подредени във верига.

close()метод

Записва всички незаписани данни в целевия обект. Методът close()не трябва да се извиква, ако използвате try-with-resourcesблок.

Пример за програма, която копира текстов файл:

Код Забележка
String src = "c:\\projects\\log.txt";
String dest = "c:\\projects\\copy.txt";

try(FileReader reader = new FileReader(src);
FileWriter writer = new FileWriter(dest))
{
   char[] buffer = new char[65536]; // 128Kb
   while (reader.ready())
   {
      int real = reader.read(buffer);
      writer.write(buffer, 0, real);
   }
}



Readerза четене от файл
Writerза запис във файл

Буфер, в който ще четем данните
Докато има данни в потока

Четене на данни в буфер
Записване на данните от буфера във втория поток

StringWriterклас

Има още един интересен клас, който наследява Writerкласа: той се нарича StringWriter. Той съдържа променлив низ — StringBufferобект. И всеки път, когато "пишете" нещо на StringWriterобекта, текстът просто се добавя към неговия вътрешен буфер.

Пример:

Код Забележка
StringWriter writer = new StringWriter();
writer.write("Hello");
writer.write(String.valueOf(123));

String result = writer.toString();
StringWriterСъздава се целеви символен поток ( )
Низ се записва в буфера вътре StringWriter
Низ се записва в буфера вътре StringWriter

Преобразуване на съдържанието на обект в низ

В този случай StringWriterкласът е по същество обвивка над StringBufferкласа, но StringWriterкласът е потомък на Writerкласа поток и може да се използва във вериги от обекти на поток. Това е доста полезно свойство на практика.