Java говорит, что FileNotFoundException, но файл существует

#java #filenotfoundexception

#java #filenotfoundexception

Вопрос:

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

 Scanner scores = new Scanner(new File("scores.dat"));
  

Тем не менее, это выдает FileNotFoundException , но я проверял снова и снова, чтобы увидеть, существует ли файл в текущей папке, и после этого я понял, что он должен что-то делать с разрешениями. Я изменил разрешения для чтения и записи для всех, но это все равно не сработало, и он все еще продолжает выдавать ошибку. У кого-нибудь есть идеи, почему это может происходить?

РЕДАКТИРОВАТЬ: на самом деле он указывал на каталог вверх, однако я исправил эту проблему. Теперь file.exists() возвращается true , но когда я пытаюсь поместить его в Scanner , он выдает FileNotFoundException

Вот весь мой код

 import java.util.Scanner;
import java.io.*;
public class readInt{
        public static void main(String args[]){
                File file = new File("lines.txt");
                System.out.println(file.exists());
                Scanner scan = new Scanner(file);
        }
}
  

Комментарии:

1. Что такое текущий каталог? Попробуйте распечатать new File(".")

2. Выведите путь new File("scores.dat") и дважды проверьте, существует ли он в ожидаемом каталоге.

3. @Steinar выполняется поиск в правильном каталоге и указывает правильный абсолютный путь, однако файл по-прежнему не найден

4. Каков текст исключения?

5. Почти наверняка вы находитесь в неправильном каталоге. Распечатайте new File("scores.dat").getAbsolutePath() и убедитесь, что файл действительно находится в этом месте.

Ответ №1:

Существует ряд ситуаций, когда a FileNotFoundException может быть выдан во время выполнения.

  1. Именованный файл не существует. Это может быть по ряду причин, в том числе:

    • Имя пути просто неверно
    • Имя пути выглядит правильным, но на самом деле неверно, потому что оно содержит непечатаемые символы (или гомоглифы), которые вы не заметили
    • Имя пути является относительным, и оно неправильно разрешается относительно фактического текущего каталога запущенного приложения. Обычно это происходит потому, что текущий каталог приложения — это не то, что вы ожидаете или предполагаете.
    • Путь к файлу нарушен; например, неверно указано имя каталога пути, нарушена символическая ссылка на пути или проблема с разрешением с одним из компонентов пути.
  2. Именованный файл на самом деле является каталогом.

  3. По какой-то причине именованный файл не может быть открыт для чтения.

Хорошая новость в том, что проблема неизбежно будет одной из вышеперечисленных. Это просто вопрос определения того, какой. Вот некоторые вещи, которые вы можете попробовать:

  • Вызов file.exists() сообщит вам, существует ли какой-либо объект файловой системы с заданным именем / путем.

  • Вызов file.isDirectory() проверит, является ли это каталогом.

  • Вызов file.canRead() проверит, является ли это читаемым файлом.

  • В этой строке будет указано, что такое текущий каталог:

       System.out.println(new File(".").getAbsolutePath());
      
  • В этой строке будет выведено имя пути таким образом, чтобы было легче определять такие вещи, как неожиданные начальные или конечные пробелы:

       System.out.println("The path is '"   path   "'");
      

    Ищите неожиданные пробелы, разрывы строк и т. Д. В выходных данных.


Оказывается, в вашем примере кода есть ошибка компиляции.

Я запустил ваш код, не обратив внимания на жалобу от Netbeans, только чтобы получить следующее сообщение об исключении:

Исключение в потоке «main» java.lang.RuntimeException: некомпилируемый исходный код — незарегистрированное исключение java.io.FileNotFoundException; должен быть перехвачен или объявлен выброшенным

Если вы измените свой код на следующий, это устранит эту проблему.

 public static void main(String[] args) throws FileNotFoundException {    
    File file = new File("scores.dat");
    System.out.println(file.exists());
    Scanner scan = new Scanner(file);
}
  

Объяснение: Scanner(File) конструктор объявлен как FileNotFoundException создающий исключение. (Случается, что сканер не может открыть файл.) Теперь FileNotFoundException это проверенное исключение. Это означает, что метод, в котором может быть вызвано исключение, должен либо перехватить исключение, либо объявить его в throws предложении. Приведенное выше исправление использует последний подход.

Комментарии:

1. Ваш третий случай включает в себя два других, а также включает в себя ряд других легко разделяемых случаев, таких как проблемы с разрешениями, сбои в сети и т.д., Что не очень поучительно и не дает никаких оснований для существования «трех случаев». Тестирование File.canRead() бесполезно, когда вам уже нужно перехватить исключение, и расточительно, когда системе все равно приходится его тестировать во время открытия.

2. Если проблема возникает в macOS, это может быть связано с тем, что Java или Android Studio / ваша IDE не имеют доступа к папке Documents. Это можно исправить в настройках / Безопасность и конфиденциальность / Файлы и папки (или полный доступ к диску)

Ответ №2:

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

Используйте эту строку и посмотрите, где находится путь:

 System.out.println(new File(".").getAbsoluteFile());
  

Ответ №3:

Очевидно, что существует ряд возможных причин, и предыдущие ответы хорошо их документируют, но вот как я решил это в одном конкретном случае:

У моего ученика была эта проблема, и я чуть не вырвал себе волосы, пытаясь разобраться в этом. Оказалось, что файл не существует, хотя он выглядел так, как будто он существовал. Проблема заключалась в том, что Windows 7 была настроена на «Скрытие расширений файлов для известных типов файлов». Это означает, что если файл имеет имя «data.txt » его фактическое имя файла таково «data.txt.txt «.

Надеюсь, это поможет другим сэкономить немного времени.

Комментарии:

1. Да, это был настоящий виновник. Проверяется «Скрыть расширения файлов для известных типов файлов», и, к сожалению, у моего файла было избыточное расширение.

Ответ №4:

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

 //String path was read from file
System.out.println(path); //file with exactly same visible path exists on disk
File file = new File(path); 
System.out.println(file.exists());  //false
System.out.println(file.canRead());  //false
FileInputStream fis = new FileInputStream(file);  // FileNotFoundExeption 
  

Причиной проблемы было то, что путь содержал невидимые rn символы в конце.

Исправление в моем случае было:

 File file = new File(path.trim()); 
  

Чтобы немного обобщить, невидимые / непечатаемые символы могли включать символы пробела или табуляции и, возможно, другие, и они могли появиться в начале пути, в конце или встроены в путь. Trim будет работать в некоторых случаях, но не во всех. Есть несколько вещей, которые вы можете помочь обнаружить такого рода проблемы:

  1. Выведите путь с символами кавычек вокруг него; например

       System.out.println("Check me! '"   path   "'");
      

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

  2. Используйте Java-отладчик, чтобы тщательно изучить строку имени пути, символ за символом, в поисках символов, которых там быть не должно. (Также проверьте наличие символов гомоглифа!)

Ответ №5:

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

Ответ №6:

Чтение и запись из файла и в файл могут быть заблокированы вашей операционной системой в зависимости от атрибутов разрешения файла.

Если вы пытаетесь выполнить чтение из файла, я рекомендую использовать метод setReadable для файла, чтобы установить для него значение true, или, например, этот код:

 String arbitrary_path = "C:/Users/Username/Blah.txt";
byte[] data_of_file;
File f = new File(arbitrary_path);
f.setReadable(true);
data_of_file = Files.readAllBytes(f);
f.setReadable(false); // do this if you want to prevent un-knowledgeable 
                      //programmers from accessing your file.
  

Если вы пытаетесь выполнить запись в файл, я рекомендую использовать метод File setWritable, чтобы установить для него значение true, или, например, этот код:

 String arbitrary_path = "C:/Users/Username/Blah.txt";
byte[] data_of_file = { (byte) 0x00, (byte) 0xFF, (byte) 0xEE };
File f = new File(arbitrary_path);
f.setWritable(true);
Files.write(f, byte_array);
f.setWritable(false); // do this if you want to prevent un-knowledgeable 
                      //programmers from changing your file (for security.)
  

Ответ №7:

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

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

Это сработало для меня, надеюсь, это кому-то поможет 🙂

Ответ №8:

У меня была такая же ошибка, и я решил ее, просто добавив каталог src, который находится в структуре проекта Java.

 String path = System.getProperty("user.dir")   "\src\package_name\file_name";
File file = new File(path);
Scanner scanner = new Scanner(file);
  

Обратите внимание, что System.getProperty(«user.dir») и new File(«.»).getAbsolutePath() возвращают путь к корневому каталогу вашего проекта, поэтому вам нужно добавить путь к вашим подкаталогам и пакетам

Комментарии:

1. Хотя это сработало для вас, с этим подходом есть проблемы. 1) Вы делаете свое приложение зависимым от платформы, используя синтаксис пути, специфичный для Windows. 2) Вы предполагаете, что ваш код будет выполняться с текущим каталогом, установленным в каталог сборки (или что-то в этом роде). Это не сработает, если вы отправите код кому-то другому.

2. Если файл, который вы пытаетесь прочитать, является частью вашей базы исходного кода, лучшей идеей будет скопировать его в ваш JAR-файл (или дерево файлов, содержащих ваши скомпилированные классы) и использовать getResourceAsStream для его поиска через (runtime) classpath .

Ответ №9:

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

Ответ №10:

Используйте одну косую черту и всегда вводите путь вручную. Например:

 FileInputStream fi= new FileInputStream("D:/excelfiles/myxcel.xlsx");
  

Ответ №11:

Что сработало для меня, так это перехват исключения. Без этого компилятор жалуется, даже если файл существует.

 InputStream file = new FileInputStream("filename");
  

изменено на

 try{
    InputStream file = new FileInputStream("filename");
    System.out.println(file.available());
}
catch (Exception e){
    System.out.println(e);
}
  

Ответ №12:

Это работает для меня. Он также может читать файлы, такие как txt, csv и .in

 public class NewReader {

    public void read() throws FileNotFoundException, URISyntaxException {
        File file = new File(Objects.requireNonNull(NewReader.class.getResource("/test.txt")).toURI());
        Scanner sc = new Scanner(file);

        while (sc.hasNext()) {
            String text = sc.next();
            System.out.println(text);

        }
    }
}
  

файл находится в папке ресурсов, созданной maven. Если у вас есть другие вложенные папки, просто добавьте его к имени файла, например «examples/test.txt «.