Главная страница

Ответы на вопросы по ревью 4. Java io. Ключевым понятием здесь является понятие потока


Скачать 1.93 Mb.
НазваниеJava io. Ключевым понятием здесь является понятие потока
Дата03.07.2022
Размер1.93 Mb.
Формат файлаdoc
Имя файлаОтветы на вопросы по ревью 4.doc
ТипДокументы
#623608
страница2 из 39
1   2   3   4   5   6   7   8   9   ...   39

Запись файлов и класс FileOutputStream


Класс FileOutputStream предназначен для записи байтов в файл. Он является производным от класса OutputStream, поэтому наследует всю его функциональность.

Через конструктор класса FileOutputStream задается файл, в который производится запись. Класс поддерживает несколько конструкторов:

1

2

3

4

FileOutputStream(String filePath)

FileOutputStream(File fileObj)

FileOutputStream(String filePath, boolean append)

FileOutputStream(File fileObj, boolean append)

Файл задается либо через строковый путь, либо через объект File. Второй параметр - append задает способ записи: eсли он равен true, то данные дозаписываются в конец файла, а при false - файл полностью перезаписывается

Например, запишем в файл строку:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

import java.io.*;

 

public class Program {

  

    public static void main(String[] args) {

          

        String text = "Hello world!"; // строка для записи

        try(FileOutputStream fos=new FileOutputStream("C://SomeDir//notes.txt"))

        {

            // перевод строки в байты

            byte[] buffer = text.getBytes();

              

            fos.write(buffer, 0, buffer.length);

            System.out.println("The file has been written");

        }

        catch(IOException ex){

              

            System.out.println(ex.getMessage());

        }

    }

}

Для создания объекта FileOutputStream используется конструктор, принимающий в качестве параметра путь к файлу для записи. Если такого файла нет, то он автоматически создается при записи. Так как здесь записываем строку, то ее надо сначала перевести в массив байтов. И с помощью метода write строка записывается в файл.

Для автоматического закрытия файла и освобождения ресурса объект FileOutputStream создается с помощью конструктции try...catch.

При этом необязательно записывать весь массив байтов. Используя перегрузку метода write(), можно записать и одиночный байт:

1

fos.write(buffer[0]); // запись первого байта

Чтение файлов и класс FileInputStream


Для считывания данных из файла предназначен класс FileInputStream, который является наследником класса InputStream и поэтому реализует все его методы.

Для создания объекта FileInputStream мы можем использовать ряд конструкторов. Наиболее используемая версия конструктора в качестве параметра принимает путь к считываемому файлу:

1

FileInputStream(String fileName) throws FileNotFoundException

Если файл не может быть открыт, например, по указанному пути такого файла не существует, то генерируется исключение FileNotFoundException.

Считаем данные из ранее записанного файла и выведем на консоль:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

import java.io.*;

 

public class Program {

  

    public static void main(String[] args) {

 

        try(FileInputStream fin=new FileInputStream("C://SomeDir//notes.txt"))

        {

            System.out.printf("File size: %d bytes \n", fin.available());

              

            int i=-1;

            while((i=fin.read())!=-1){

              

                System.out.print((char)i);

            }  

        }

        catch(IOException ex){

              

            System.out.println(ex.getMessage());

        }

    }

}

В данном случае мы считываем каждый отдельный байт в переменную i:

1

while((i=fin.read())!=-1){

Когда в потоке больше нет данных для чтения, метод возвращает число -1.

Затем каждый считанный байт конвертируется в объект типа char и выводится на консоль.

Подобным образом можно считать данные в массив байтов и затем производить с ним манипуляции:

1

2

3

4

5

6

7

8

9

byte[] buffer = new byte[fin.available()];

// считаем файл в буфер

fin.read(buffer, 0, fin.available());

 

System.out.println("File data:");

for(int i=0; i
 

    System.out.print((char)buffer[i]);

}

Совместим оба класса и выполним чтение из одного и запись в другой файл:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

import java.io.*;

 

public class Program {

 

    public static void main(String[] args) {

         

        try(FileInputStream fin=new FileInputStream("C://SomeDir//notes.txt");

                FileOutputStream fos=new FileOutputStream("C://SomeDir//notes_new.txt"))

        {

            byte[] buffer = new byte[fin.available()];

            // считываем буфер

            fin.read(buffer, 0, buffer.length);

            // записываем из буфера в файл

            fos.write(buffer, 0, buffer.length);

        }

        catch(IOException ex){

             

            System.out.println(ex.getMessage());

        }

    }

}

Классы FileInputStream и FileOutputStream предназначены прежде всего для записи двоичных файлов, то есть для записи и чтения байтов. И хотя они также могут использоваться для работы с текстовыми файлами, но все же для этой задачи больше подходят другие классы.
При завершении работы с потоком его надо закрыть с помощью метода close(), который определен в интерфейсе Closeable. Метод close имеет следующее определение:

1

void close() throws IOException

Этот интерфейс уже реализуется в классах InputStream и OutputStream, а через них и во всех классах потоков.

При закрытии потока освобождаются все выделенные для него ресурсы, например, файл. В случае, если поток окажется не закрыт, может происходить утечка памяти.

Есть два способа закрытия файла. Первый традиционный заключается в использовании блока try..catch..finally. Например, считаем данные из файла:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

import java.io.*;

 

public class Program {

 

    public static void main(String[] args) {

         

        FileInputStream fin=null;

        try

        {

            fin = new FileInputStream("C://SomeDir//notes.txt");

             

            int i=-1;

            while((i=fin.read())!=-1){

             

                System.out.print((char)i);

            }

        }

        catch(IOException ex){

             

            System.out.println(ex.getMessage());

        }

        finally{

             

            try{

             

                if(fin!=null)

                    fin.close();

            }

            catch(IOException ex){

             

                System.out.println(ex.getMessage());

            }

        } 

    }

}

Поскольку при открытии или считывании файла может произойти ошибка ввода-вывода, то код считывания помещается в блок try. И чтобы быть уверенным, что поток в любом случае закроется, даже если при работе с ним возникнет ошибка, вызов метода close() помещается в блок finally. И, так как метод close() также в случае ошибки может генерировать исключение IOException, то его вызов также помещается во вложенный блок try..catch

Начиная с Java 7 можно использовать еще один способ, который автоматически вызывает метод close. Этот способ заключается в использовании конструкции try-with-resources (try-с-ресурсами). Данная конструкция работает с объектами, которые реализуют интерфейс AutoCloseable. Так как все классы потоков реализуют интерфейс Closeable, который в свою очередь наследуется от AutoCloseable, то их также можно использовать в данной конструкции

Итак, перепишем предыдущий пример с использованием конструкции try-with-resources:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

import java.io.*;

 

public class Program {

 

    public static void main(String[] args) {

         

        try(FileInputStream fin=new FileInputStream("C://SomeDir//notes.txt"))

        {

            int i=-1;

            while((i=fin.read())!=-1){

             

                System.out.print((char)i);

            }  

        }

        catch(IOException ex){

             

            System.out.println(ex.getMessage());

        }

    }

}

Синтаксис конструкции следующий: try(название_класса имя_переменной = конструктор_класса). Данная конструкция также не исключает использования блоков catch.

После окончания работы в блоке try у ресурса (в данном случае у объекта FileInputStream) автоматически вызывается метод close().

Если нам надо использовать несколько потоков, которые после выполнения надо закрыть, то мы можем указать объекты потоков через точку с запятой:

1

2

3

4

5

try(FileInputStream fin=new FileInputStream("C://SomeDir//Hello.txt");

        FileOutputStream fos = new FileOutputStream("C://SomeDir//Hello2.txt"))

{

    //..................

}


Для работы с массивами байтов - их чтения и записи используются классы ByteArrayInputStream и ByteArrayOutputStream.

Чтение массива байтов и класс ByteArrayInputStream


Класс ByteArrayInputStream представляет входной поток, использующий в качестве источника данных массив байтов. Он имеет следующие конструкторы:

1

2

ByteArrayInputStream(byte[] buf)

ByteArrayInputStream(byte[] buf, int offset, int length)

В качестве параметров конструкторы используют массив байтов buf, из которого производится считывание, смещение относительно начала массива offset и количество считываемых символов length.

Считаем массив байтов и выведем его на экран:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

import java.io.*;

 

public class Program {

 

    public static void main(String[] args) {

         

        byte[] array1 = new byte[]{1, 3, 5, 7};

        ByteArrayInputStream byteStream1 = new ByteArrayInputStream(array1);

        int b;

        while((b=byteStream1.read())!=-1){

         

            System.out.println(b);

        }

         

        String text = "Hello world!";

        byte[] array2 = text.getBytes();

        // считываем 5 символов

        ByteArrayInputStream byteStream2 = new ByteArrayInputStream(array2, 0, 5);

        int c;

        while((c=byteStream2.read())!=-1){

         

            System.out.println((char)c);

        }

    }

}

В отличие от других классов потоков для закрытия объекта ByteArrayInputStream не требуется вызывать метод close.

Запись массива байт и класс ByteArrayOutputStream


Класс ByteArrayOutputStream представляет поток вывода, использующий массив байтов в качестве места вывода.

Чтобы создать объект данного класса, мы можем использовать один из его конструкторов:

1

2

ByteArrayOutputStream()

ByteArrayOutputStream(int size)

Первая версия создает массив для хранения байтов длиной в 32 байта, а вторая версия создает массив длиной size.

Рассмотрим применение класса:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

import java.io.*;

 

public class Program {

 

    public static void main(String[] args) {

         

        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        String text = "Hello Wolrd!";

        byte[] buffer = text.getBytes();

        try{

            baos.write(buffer);

        }

        catch(Exception ex){

         

            System.out.println(ex.getMessage());

        }

        // превращаем массив байтов в строку

        System.out.println(baos.toString());

         

        // получаем массив байтов и выводим по символьно

        byte[] array = baos.toByteArray();

        for(byte b: array){

         

            System.out.print((char)b);

        }

        System.out.println();

    }

}

Как и в других потоках вывода в классе ByteArrayOutputStream определен метод write, который записывает в поток некоторые данные. В данном случае мы записываем в поток массив байтов. Этот массив байтов записывается в объекте ByteArrayOutputStream в защищенное поле buf, которое представляет также массив байтов (protected byte[] buf).

Так как метод write может сгенерировать исключение, то вызов этого метода помещается в блок try..catch.

Используя методы toString() и toByteArray(), можно получить массив байтов buf в виде текста или непосредственно в виде массива байт.

С помощью метода writeTo мы можем вывести массив байт в другой поток. Данный метод в качестве параметра принимает объект OutputStream, в который производится запись массива байт:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

ByteArrayOutputStream baos = new ByteArrayOutputStream();

String text = "Hello Wolrd!";

byte[] buffer = text.getBytes();

try{

    baos.write(buffer);

}

catch(Exception ex){

         

    System.out.println(ex.getMessage());

}

try(FileOutputStream fos = new FileOutputStream("hello.txt")){

     

    baos.writeTo(fos);

}

catch(IOException e){

             

    System.out.println(e.getMessage());

}

После выполнения этой программы в папке с программой появится файл hello.txt, который будет содержать строку "Hello Wolrd!".

И в заключении также надо сказать, что как и для объектов ByteArrayInputStream, для ByteArrayOutputStream не надо явным образом закрывать поток с помощью метода close.
Для оптимизации операций ввода-вывода используются буферизуемые потоки. Эти потоки добавляют к стандартным специальный буфер в памяти, с помощью которого повышается производительность при чтении и записи потоков.

Класс BufferedInputStream


Класс BufferedInputStream накапливает вводимые данные в специальном буфере без постоянного обращения к устройству ввода. Класс BufferedInputStream определяет два конструктора:

1

2

BufferedInputStream(InputStream inputStream)

BufferedInputStream(InputStream inputStream, int bufSize)

Первый параметр - это поток ввода, с которого данные будут считываться в буфер. Второй параметр - размер буфера.

Например, буферизируем считывание данных из потока ByteArrayInputStream:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

import java.io.*;

 

public class Program {

 

    public static void main(String[] args) {

         

         String text = "Hello world!";

         byte[] buffer = text.getBytes();

        ByteArrayInputStream in = new ByteArrayInputStream(buffer);

         

        try(BufferedInputStream bis = new BufferedInputStream(in)){

             

            int c;

            while((c=bis.read())!=-1){

         

                System.out.print((char)c);

            }

        }

        catch(Exception e){

             

            System.out.println(e.getMessage());

        }

        System.out.println();

    }

}

Класс BufferedInputStream в конструкторе принимает объект InputStream. В данном случае таким объектом является экземпляр класса ByteArrayInputStream.

Как и все потоки ввода BufferedInputStream обладает методом read(), который считывает данные. И здесь мы считываем с помощью метода read каждый байт из массива buffer.

Фактические все то же самое можно было сделать и с помощью одного ByteArrayInputStream, не прибегая к буферизированному потоку. Класс BufferedInputStream просто оптимизирует производительность при работе с потоком ByteArrayInputStream. Естественно вместо ByteArrayInputStream может использоваться любой другой класс, который унаследован от InputStream.

Класс BufferedOutputStream


Класс BufferedOutputStream аналогично создает буфер для потоков вывода. Этот буфер накапливает выводимые байты без постоянного обращения к устройству. И когда буфер заполнен, производится запись данных.

BufferedOutputStream определяет два конструктора:

1

2

BufferedOutputStream(OutputStream outputStream)

BufferedOutputStream(OutputStream outputStream, int bufSize)

Первый параметр - это поток вывода, который унаследован от OutputStream, а второй параметр - размер буфера.

Рассмотрим на примере записи в файл:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

import java.io.*;

 

public class Program {

 

    public static void main(String[] args) {

         

        String text = "Hello world!"; // строка для записи

        try(FileOutputStream out=new FileOutputStream("notes.txt");

                BufferedOutputStream bos = new BufferedOutputStream(out))

        {

            // перевод строки в байты

            byte[] buffer = text.getBytes();

            bos.write(buffer, 0, buffer.length);

        }

        catch(IOException ex){

             

            System.out.println(ex.getMessage());

        }

    }

}

Класс BufferedOutputStream в конструкторе принимает в качестве параметра объект OutputStream - в данном случае это файловый поток вывода FileOutputStream. И также производится запись в файл. Опять же BufferedOutputStream не добавляет много новой функциональности, он просто оптимизирует действие потока вывода.

Класс PrintStream


Класс PrintStream - это именно тот класс, который используется для вывода на консоль. Когда мы выводим на консоль некоторую информацию с помощью вызова System.out.println(), то тем самым мы задействует PrintStream, так как переменная out в классе System как раз и представляет объект класса PrintStream, а метод println() - это метод класса PrintStream.

Но PrintStream полезен не только для вывода на консоль. Мы можем использовать данный класс для записи информации в поток вывода. Для этого PrintStream определяет ряд конструкторов:

1

2

3

4

5

6

7

PrintStream(OutputStream outputStream)

PrintStream(OutputStream outputStream, boolean autoFlushingOn)

PrintStream(OutputStream outputStream, boolean autoFlushingOn, String charSet) throws UnsupportedEncodingException

PrintStream(File outputFile) throws FileNotFoundException

PrintStream(File outputFile, String charSet) throws FileNotFoundException, UnsupportedEncodingException

PrintStream(String outputFileName) throws FileNotFoundException

PrintStream(String outputFileName, String charSet) throws FileNotFoundException, UnsupportedEncodingException

Параметр outputStream - это объект OutputStream, в который производится запись. Параметр autoFlushingOn при значении true позволяет автоматически записывать данные в поток вывода. По умолчанию этот параметр равен false. Параметр charSet позволяет указать кодировку символов.

В качестве источника для записи данных вместо OutputStream можно использовать объект File или строковый путь, по которому будет создаваться файл.

Для вывода информации в выходной поток PrintStream использует следующие методы:

Например, запишем информацию в файл:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

import java.io.*;

 

public class Program {

 

    public static void main(String[] args) {

         

        String text = "Привет мир!"; // строка для записи

        try(FileOutputStream fos=new FileOutputStream("C://SomeDir//notes3.txt");

                PrintStream printStream = new PrintStream(fos))

        {

            printStream.println(text);

            System.out.println("Запись в файл произведена");

        }

        catch(IOException ex){

             

            System.out.println(ex.getMessage());

        } 

    }

}

В данном случае применяется форма конструктора PrintStream, которая в качестве параметра принимает поток вывода: PrintStream (OutputStream out). Кроме того, мы могли бы использовать ряд других форм конструктора, например, указывая названия файла для записи: PrintStream (string filename)

В качестве потока вывода используется объект FileOutputStream. С помощью метода println() производится запись информации в выходной поток - то есть в объект FileOutputStream. (В случае с выводом на консоль с помощью System.out.println() в качестве потока вывода выступает консоль)

Кроме того, как и любой поток вывода и наследник класса OutputStream он имеет метод write:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

import java.io.*;

 

public class Program {

  

    public static void main(String[] args) {

          

        try(PrintStream printStream = new PrintStream("notes3.txt"))

        {

            printStream.print("Hello World!");

            printStream.println("Welcome to Java!");

             

            printStream.printf("Name: %s Age: %d \n", "Tom", 34);

             

            String message = "PrintStream";

            byte[] message_toBytes = message.getBytes();

            printStream.write(message_toBytes);

             

            System.out.println("The file has been written");

        }

        catch(IOException ex){

              

            System.out.println(ex.getMessage());

        } 

    }

}

После выполнения этой программы получится файл со следующим содержанием:

Hello World!Welcome to Java!

Name: Tom Age: 34

PrintStream

PrintWriter


На PrintStream похож другой класс PrintWriter. Его можно использовать как для вывода информации на консоль, так и в файл или любой другой поток вывода. Данный класс имеет ряд конструкторов:

  • PrintWriter(File file): автоматически добавляет информацию в указанный файл

  • PrintWriter(File file, String csn): автоматически добавляет информацию в указанный файл с учетом кодировки csn

  • PrintWriter(OutputStream out): для вывода информации используется существующий объект OutputStream, автоматически сбрасывая в него данные

  • PrintWriter(OutputStream out, boolean autoFlush): для вывода информации используется существующий объект OutputStream, второй параметр указывает, надо ли автоматически добавлять в OutputStream данные

  • PrintWriter(String fileName): автоматически добавляет информацию в файл по указанному имени

  • PrintWriter(String fileName, String csn): автоматически добавляет информацию в файл по указанному имени, используя кодировку csn

  • PrintWriter(Writer out): для вывода информации используется существующий объект Writer, в который автоматически идет запись данных

  • PrintWriter(Writer out, boolean autoFlush): для вывода информации используется существующий объект Writer, второй параметр указывает, надо ли автоматически добавлять в Writer данные

PrintWriter реализует интерфейсы Appendable, Closable и Flushable, и поэтому после использования представляемый им поток надо закрывать.

Для записи данных в поток он также используется методы printf() и println().

Например, применим данный класс для вывода на консоль:

1

2

3

4

try PrintWriter pw = new PrintWriter(System.out))

{

    pw.println("Hello world!");

}


В качестве потока вывода здесь применяется System.out, а на консоль будет выведена строка "Hello world!"
Классы DataOutputStream и DataInputStream позволяют записывать и считывать данные примитивных типов.

Запись данных и DataOutputStream


Класс DataOutputStream представляет поток вывода и предназначен для записи данных примитивных типов, таких, как int, double и т.д. Для записи каждого из примитивных типов предназначен свой метод:

  • writeBoolean(boolean v) : записывает в поток булевое однобайтовое значение

  • writeByte(int v): записывает в поток 1 байт, которые представлен в виде целочисленного значения

  • writeChar(int v): записывает 2-байтовое значение char

  • writeDouble(double v): записывает в поток 8-байтовое значение double

  • writeFloat(float v): записывает в поток 4-байтовое значение float

  • writeInt(int v): записывает в поток целочисленное значение int

  • writeLong(long v): записывает в поток значение long

  • writeShort(int v): записывает в поток значение short

  • writeUTF(String str): записывает в поток строку в кодировке UTF-8



Считывание данных и DataInputStream


Класс DataInputStream действует противоположным образом - он считывает из потока данные примитивных типов. Соответственно для каждого примитивного типа определен свой метод для считывания:

  • boolean readBoolean(): считывает из потока булевое однобайтовое значение

  • byte readByte(): считывает из потока 1 байт

  • char readChar(): считывает из потока значение char

  • double readDouble(): считывает из потока 8-байтовое значение double

  • float readFloat(): считывает из потока 4-байтовое значение float

  • int readInt(): считывает из потока целочисленное значение int

  • long readLong(): считывает из потока значение long

  • short readShort(): считывает значение short

  • String readUTF(): считывает из потока строку в кодировке UTF-8

  • int skipBytes(int n): пропускает при чтении из потока n байтов

Рассмотрим применение классов на примере:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

import java.io.*;

 

public class Program {

  

    public static void main(String[] args) {

          

        Person tom = new Person("Tom", 34, 1.68, false);

        // запись в файл

        try(DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.bin")))

        {

           // записываем значения

            dos.writeUTF(tom.name);

            dos.writeInt(tom.age);

            dos.writeDouble(tom.height);

            dos.writeBoolean(tom.married);

            System.out.println("File has been written");

        }

        catch(IOException ex){

              

            System.out.println(ex.getMessage());

        } 

          

        // обратное считывание из файла

        try(DataInputStream dos = new DataInputStream(new FileInputStream("data.bin")))

        {

           // записываем значения

            String name = dos.readUTF();

            int age = dos.readInt();

            double height = dos.readDouble();

            boolean married = dos.readBoolean();

            System.out.printf("Name: %s  Age: %d  Height: %f  Married: %b",

                    name, age, height, married);

        }

        catch(IOException ex){

              

            System.out.println(ex.getMessage());

        } 

    }

}

  

class Person

{

    public String name;

    public int age;

    public double height;

    public boolean married;

      

    public Person(String n, int a, double h, boolean m)

    {

        this.name=n;

        this.height=h;

        this.age=a;

        this.married=m;

    }

}

Здесь мы последовательно записываем в файл данные объекта Person.

Объект DataOutputStream в конструкторе принимает поток вывода: DataOutputStream (OutputStream out). В данном случае в качестве потока вывода используется объект FileOutputStream, поэтому вывод будет происходить в файл. И с помощью выше рассмотренных методов типа writeUTF() производится запись значений в бинарный файл.

Затем происходит чтение ранее записанных данных. Объект DataInputStream в конструкторе принимает поток для чтения: DataInputStream(InputStream in). Здесь таким потоком выступает объект FileInputStream
Хотя с помощью ранее рассмотренных классов можно записывать текст в файлы, однако они предназначены прежде всего дл работы с бинарными потоками данных, и их возможностей для полноценной работы с текстовыми файлами недостаточно. И для этой цели служат совсем другие классы, которые являются наследниками абстрактных классов Reader и Writer.

Запись файлов. Класс FileWriter


Класс FileWriter является производным от класса Writer. Он используется для записи текстовых файлов.

Чтобы создать объект FileWriter, можно использовать один из следующих конструкторов:

1

2

3

4

5

FileWriter(File file)

FileWriter(File file, boolean append)

FileWriter(FileDescriptor fd)

FileWriter(String fileName)

FileWriter(String fileName, boolean append)

Так, в конструктор передается либо путь к файлу в виде строки, либо объект File, который ссылается на конкретный текстовый файл. Параметр append указывает, должны ли данные дозаписываться в конец файла (если параметр равен true), либо файл должен перезаписываться.

Запишем в файл какой-нибудь текст:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

import java.io.*;

 

public class Program {

 

    public static void main(String[] args) {

        

        try(FileWriter writer = new FileWriter("notes3.txt", false))

        {

           // запись всей строки

            String text = "Hello Gold!";

            writer.write(text);

            // запись по символам

            writer.append('\n');

            writer.append('E');

             

            writer.flush();

        }

        catch(IOException ex){

             

            System.out.println(ex.getMessage());

        }

    }

}

В конструкторе использовался параметр append со значением false - то есть файл будет перезаписываться. Затем с помощью методов, определенных в базовом классе Writer производится запись данных.


Чтение файлов. Класс FileReader


Класс FileReader наследуется от абстрактного класса Reader и предоставляет функциональность для чтения текстовых файлов.

Для создания объекта FileReader мы можем использовать один из его конструкторов:

12

3

FileReader(String fileName)

FileReader(File file)

FileReader(FileDescriptor fd)

А используя методы, определенные в базом классе Reader, произвести чтение файла:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

import java.io.*;

 

public class Program {

 

    public static void main(String[] args) {

        

        try(FileReader reader = new FileReader("notes3.txt"))

        {

           // читаем посимвольно

            int c;

            while((c=reader.read())!=-1){

                 

                System.out.print((char)c);

            }

        }

        catch(IOException ex){

             

            System.out.println(ex.getMessage());

        }  

    }

}

Также мы можем считывать в промежуточный буфер из массива символов:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

import java.io.*;

import java.util.Arrays;

 

public class Program {

  

    public static void main(String[] args) {

          

        try(FileReader reader = new FileReader("notes3.txt"))

        {

            char[] buf = new char[256];

            int c;

            while((c = reader.read(buf))>0){

                 

                if(c < 256){

                    buf = Arrays.copyOf(buf, c);

                }

                System.out.print(buf);

            }

        }

        catch(IOException ex){

             

            System.out.println(ex.getMessage());

        }      

    }    

}

В данном случае считываем последовательно символы из файла в массив из 256 символов, пока не дойдем до конца файла в этом случае метод read возвратит число -1.

Поскольку считанная порция файла может быть меньше 256 символов (например, в файле всего 73 символа), и если количество считанных данных меньше размера буфера (256), то выполняем копирование массива с помощью метода Arrays.copy. То есть фактически обрезаем массив buf, оставляя в нем только те символы, которые считаны из файла.

Запись текста через буфер и BufferedWriter


Класс BufferedWriter записывает текст в поток, предварительно буферизируя записываемые символы, тем самым снижая количество обращений к физическому носителю для записи данных.

Класс BufferedWriter имеет следующие конструкторы:

1

2

BufferedWriter(Writer out)

BufferedWriter(Writer out, int sz)

В качестве параметра он принимает поток вывода, в который надо осуществить запись. Второй параметр указывает на размер буфера.

Например, осуществим запись в файл:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

import java.io.*;

 

public class Program {

  

    public static void main(String[] args) {

          

        try(BufferedWriter bw = new BufferedWriter(new FileWriter("notes4.txt")))

        {

            String text = "Hello  World!\nHey! Teachers! Leave the kids alone.";

            bw.write(text);

        }

        catch(IOException ex){

              

            System.out.println(ex.getMessage());

        }

    }

}

Чтение текста и BufferedReader


Класс BufferedReader считывает текст из символьного потока ввода, буферизируя прочитанные символы. Использование буфера призвано увеличить производительность чтения данных из потока.

Класс BufferedReader имеет следующие конструкторы:

1

2

BufferedReader(Reader in)

BufferedReader(Reader in, int sz)

Второй конструктор, кроме потока ввода, из которого производится чтение, также определяет размер буфера, в который будут считываться символы.

Так как BufferedReader наследуется от класса Reader, то он может использовать все те методы для чтения из потока, которые определены в Reader. И также BufferedReader определяет свой собственный метод readLine(), который позволяет считывать из потока построчно.

Рассмотрим применение BufferedReader:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

import java.io.*;

 

public class Program {

 

    public static void main(String[] args) {

        

        try(BufferedReader br = new BufferedReader (new FileReader("notes4.txt")))

        {

           // чтение посимвольно

            int c;

            while((c=br.read())!=-1){

                 

                System.out.print((char)c);

            }

        }

        catch(IOException ex){

             

            System.out.println(ex.getMessage());

        }

    }

}

Также можно считать текст построчно:

1

2

3

4

5

6

7

8

9

10

11

12

13

try(BufferedReader br = new BufferedReader(new FileReader("notes4.txt")))

{

    //чтение построчно

    String s;

    while((s=br.readLine())!=null){

                 

        System.out.println(s);

    }

}

 catch(IOException ex){

             

    System.out.println(ex.getMessage());

}


Считывание с консоли в файл


Соединим оба класса BufferedReader и BufferedWriter для считывания с консоли в файл. Для этого определим следующий код программы:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

import java.io.*;

 

public class Program {

 

    public static void main(String[] args) {

         

        try(BufferedReader br = new BufferedReader (new InputStreamReader(System.in));

                BufferedWriter bw = new BufferedWriter(new FileWriter("notes5.txt")))

        {

           // чтение построчно

            String text;

            while(!(text=br.readLine()).equals("ESC")){

                  

                bw.write(text + "\n");

                bw.flush();

            }

        }

        catch(IOException ex){

              

            System.out.println(ex.getMessage());

        }

    }  

}

Здесь объект BufferedReader устанавливается для чтения с консоли с помощью объекта new InputStreamReader(System.in). В цикле while считывается введенный текст. И пока пользователь не введет строку "ESC", объект BufferedWriter будет записывать текст файл.
2) На каком паттерне основана иерархия потоков ввода/вывода.
1   2   3   4   5   6   7   8   9   ...   39


написать администратору сайта