Подскажите, пожалуйста, правильно ли я понимаю, что поток FileReader и цепочка потоков InputStreamReader + InputStream — взаимозаменяемые? То есть там, где мы используем FileReader мы могли бы использовать и связку InputStreamReader + InputStream? В лекции сказано так: Когда вы читаете символ из объекта FileReader с помощью метода read(), он в свою очередь читает из файла на диске два байта и возвращает их вам как char. Когда вы читаете символ из объекта InputStreamReader с помощью метода read(), он в свою очередь читает два байта из переданного в него объекта FileInputStream, который в свою очередь читает данные из файла. Получается такая цепочка вызовов методов read(). То есть два примера кода ниже одинаковые? Если так, то подскажите, пожалуйста, какой предпочтительнее использовать? Может быть, у них разная скорость выполнения или один из них дает больше возможностей для преобразования? Код 1:
public class Solution {
    public static void main(String[] args) {
        try (Scanner scanner = new Scanner(System.in);
             FileReader fr = new FileReader(scanner.nextLine())) {
            int a;
            while ((a = fr.read()) > -1) {
                System.out.println(Character.toChars(a));
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
Код 2:
public class Solution {
    public static void main(String[] args) {
        try (Scanner scanner = new Scanner(System.in);
             FileInputStream inputStream = new FileInputStream(scanner.nextLine());
             InputStreamReader inputStreamReader = new InputStreamReader(inputStream)) {

            int a;
            while ((a = inputStreamReader.read()) > -1) {
                System.out.println(Character.toChars(a));
            }

        } catch (IOException e) {
        e.printStackTrace();
    }
    }
}