Создание сканера со встроенным FileReader рекурсивно в Java - PullRequest
0 голосов
/ 17 февраля 2011
public static Scanner getFileScanner()
{
    try{
        Scanner input = new Scanner(System.in);
        String file = input.nextLine();
        Scanner fs = new Scanner(new FileReader(file));            
    }catch (FileNotFoundException fe) {
        System.out.println("Invalid filename. Try another:");
        getFileScanner();
    }finally{
        return fs;
    }
}

Я получаю сообщение об ошибке, что переменная fs не найдена.Я не могу понять, почему для моей жизни.

Ответы [ 6 ]

1 голос
/ 17 февраля 2011

Давайте начнем с перечисления проблем в вашем коде:

  1. Ошибка компиляции в операторе return вызвана тем, что fs находится вне области действия, как описано в других ответах.

  2. Когда вы делаете рекурсивный вызов getFileScanner(), вы не присваиваете или не возвращаете результат. Так что он не вернется к звонящему.

  3. Использование return в блоке finally является плохой идеей . Это раздавит (выбросит) любые другие исключения, которые могут распространяться в этой точке; например исключения, которые не соответствуют catch или исключения, выданные в блоке catch.

  4. Вызов input.nextLine() вызовет исключение, если базовый поток достиг EOF; например пользователь набрал [CONTROL] + D или что-то еще. Вам не нужно ловить его (он не проверен), но возвращение в блоке finally подавляет его (вероятно), в результате чего вызывающий абонент получает null вместо этого. Тьфу ...

  5. Жесткая проводка System.in и System.out делает ваш метод менее пригодным для повторного использования. (Хорошо, это не может быть проблемой, которую вы должны решить в данном конкретном случае. И я не буду, ниже ...)

  6. Теоретически, ваш метод может быть сделан, чтобы бросить StackOverflowError; например если пользователь нажимает [ENTER] несколько раз. Эта проблема присуща вашему рекурсивному решению и является хорошей причиной не делать этого таким образом.

Наконец, вот версия метода, который решает эти проблемы:

public static Scanner getFileScanner() throws NoSuchElementException
{
    Scanner input = new Scanner(System.in);
    while (true) {
        String file = input.nextLine();
        try {
            return new Scanner(new FileReader(file));           
        } catch (FileNotFoundException fe) {
            System.out.println("Invalid filename. Try another:");
        }
    }
}

Обратите внимание, что я заменил рекурсию, избавился от finally и объявил исключение, которое выдается. (Можно перехватить это исключение и либо сообщить о нем, либо повторно выбросить его как исключение для конкретного приложения.)

1 голос
/ 17 февраля 2011

Переменные, объявленные внутри блока try, не находятся в области видимости внутри соответствующего блока finally. В целом, у вашего подхода есть ряд проблем ... Как правило, return внутри блока finally не очень хорошая идея.

Вот что я бы сделал:

public static Scanner getFileScanner() {
  Scanner input = new Scanner(System.in);
  File file = null;
  while (true) {
    file = new File(input.nextLine());
    if (file.exists() && file.isFile())
      break;
    System.out.println("Invalid filename. Try another:");
  }
  return new Scanner(new FileReader(file));
}
1 голос
/ 17 февраля 2011

Ваш fs объявлен в блоке try ... чтобы исправить это, объявите его вне блока: -

Scanner fs = null;
try {
    ...
    fs = new Scanner(new FileReader(file));
}
catch (FileNotFoundException fe) {
    ...
}
finally {
    return fs;
}
0 голосов
/ 17 февраля 2011

Просто чтобы расширить то, что другие парни указали в своих примерах кода ...

Поскольку вы объявляете переменную fs в блоке try, переменная будет видна только в области видимостифигурные скобки сразу после ключевого слова try.

Перемещая объявление переменной fs из блока try в тело метода getFileScanner, вы гарантируете, что к переменной могут обращаться все блоки в пределахтело метода (try, catch и finally блоки).

Надеюсь, это поможет!

0 голосов
/ 17 февраля 2011

Вы объявили fs в блоке try и попытаетесь получить к нему доступ в другой области (блок finally). Обычные парадигмы - объявлять fs перед блоком try как ноль.

0 голосов
/ 17 февраля 2011

Сначала объявите:

public static Scanner getFileScanner() {
    Scanner input = new Scanner(System.in);
    Scanner fs = null;
    while(fs == null) {
        try{
            String file = input.nextLine();
            Scanner fs = new Scanner(new File(file));            
        }catch (FileNotFoundException fe) {
            System.out.println("Invalid filename. Try another:");
        }
    }
    return fs;
}
...