GrabDuck

Закрытие потоков | Java

:

Последнее обновление: 30.10.2015

При завершении работы с потоком его надо закрыть с помощью метода close(), который определен в интерфейсе Closeable. Метод close имеет следующее определение:

void close() throws IOException

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

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

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

import java.io.*;

public class FilesApp {

    public static void main(String[] args) {
        
        FileInputStream fin=null;
        try
        {
            fin = new FileInputStream("C://SomeDir//Hello.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-с-ресурсами). Данная конструкция работает с объектами, которые реализуют интерфейс AutiCloseable. Так как все классы потоков реализуют интерфейс Closeable, который в свою очередь наследуется от AutoCloseable, то их также можно использовать в данной конструкции

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

import java.io.*;

public class FilesApp {

    public static void main(String[] args) {
        
        try(FileInputStream fin=new FileInputStream("C://SomeDir//Hello.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().

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

try(FileInputStream fin=new FileInputStream("C://SomeDir//Hello.txt"); 
        FileOutputStream fos = new FileOutputStream("C://SomeDir//Hello2.txt"))
{
	//..................
}