File.exists () zwraca false, jeśli plik istnieje

90

Napotkałem błąd, za którym nie mogę znaleźć żadnej logiki. Mam ten obiekt File, który jest utworzony w ten sposób:

File file = new File("utilities/data/someTextFile.txt");

Wtedy robię file.exists()i wraca false(!?). Jeśli plik nie zostanie znaleziony, loguję się f.getAbsolutePath()do pliku. Kiedy patrzę na ścieżkę, wydaje mi się, że jest OK. Mogę skopiować i wkleić pełną ścieżkę do okna „Uruchom” w systemie Windows i plik otwiera się dobrze.

Plik istnieje przez cały czas i nie jest usuwany ani zmieniany podczas działania mojej aplikacji. Znajduje się na komputerze lokalnym.

Wydaje się, że ma to miejsce tylko w określonych sytuacjach. Mogę odtworzyć usterkę w dowolnym momencie, ale jestem pewien, że ścieżka obiektu pliku nie jest zmieniana przez działania, które wykonuję w celu odtworzenia błędu.

Co może spowodować file.exists()zwrócenie fałszu? Czy ma to coś wspólnego z uprawnieniami lub blokadami plików itp.?

atsjoo
źródło
Czy więc można czytać z pliku, nawet jeśli exist () zwraca false?
Harry Lime
tak, mogę czytać z pliku, nawet jeśli exist () zwraca false.
atsjoo
1
Co dokładnie jest potrzebne, aby odtworzyć usterkę?
user85421
1
Jest to wewnątrz aplikacji, która wywołuje funkcje napisane w programie Matlab i wkompilowane w aplikację java. Wygląda na to, że funkcje Matlaba zmieniające "bieżący katalog" powodują pojawienie się problemu. Używam ścieżki bezwzględnej podczas tworzenia obiektu pliku, więc nie powinno to stanowić problemu - jakkolwiek się wydaje. Oczywiście zweryfikowałem bezwzględną ścieżkę do obiektu pliku i jest ona poprawna (taka sama jak przed zmianą bieżącego katalogu przez funkcję Matlab).
atsjoo
7
Czy przez przypadek pracujesz ze zdalnym katalogiem (np. Montowaniem NFS)?
Tomer Gabel

Odpowiedzi:

42

W systemie Windows 7 widzę następującą sytuację:

file.exists() == false
file.getAbsoluteFile().exists() == true

Ten plik to „var \ log”, ścieżka bezwzględna odnosi się do istniejącego pliku, który znajduje się w normalnym podkatalogu (nie w magazynie wirtualnym). Widać to z IDE.

Roman Zenka
źródło
17
Właśnie to rozgryzłem: bugs.sun.com/bugdatabase/view_bug.do;:YfiG?bug_id=4483097 Najwyraźniej operacje wykonywane na pliku są rozwiązywane na bieżącym katalogu, podczas gdy getAbsolutePath rozwiązuje się z user.dir. Jeśli te dwie ścieżki nie pasują, otrzymasz sprzeczne wyniki. Diabelski!
Roman Zenka
3
Mam dokładnie ten sam problem, który próbowałem użyć obu metod, aby sprawdzić, czy plik istnieje, ale nadal otrzymuję błąd tylko w systemie Windows 7! Dowolny pomysł?
Dejell
@Odelya: Jakiego IDE używasz? Jaki jest twój -Duser.dir ustawiony na? Mój problem był spowodowany ustawieniem -Duser.dir na inny katalog niż obecnie działający.
Roman Zenka
1
Dla każdego, kto pracuje nad dynamicznym projektem sieciowym, użycie file.exists () spowoduje zgłoszenie wyjątku, użyj file.getAbsoluteFile (). Exist (), aby sprawdzić pliki w katalogu WEB-INF (ogólna wskazówka, a nie specyficzna dla Windows 7 ).
PS
Rozważ utworzenie osobnej kontroli jakości dla tej odpowiedzi i komentarzy
Bato-Bair Tsyrenov
17

Wygląda na to, że istnieje różnica w sposobie określania ścieżki w Javie.

Na przykład, jeśli ścieżka pliku jest określona jako file:/C:/DEV/test.txtwtedy

File f = new File(filename);
f.exists();

powróci false. Ścieżka może działać w eksploratorze lub przeglądarce, ale jest to adres URL, a nie bezwzględna ścieżka do pliku.

Ale z drugiej strony, jeśli ścieżka pliku jest określona jako C:/DEV/test.txtwtedy

File f = new File(filename);
f.exists();

zwróci, trueponieważ ścieżka nie jest adresem URL, ale ścieżką bezwzględną.

W przypadku Spring Framework dokładnie to ResourceUtils.getFile(filename)działa - gdzie nazwa może być adresem URL lub bezwzględną ścieżką do pliku.

Garima Bathla
źródło
5
Nie spodziewałbym file:/C:/DEV/test.txtsię, że będę działać jako ścieżka. To adres URL, a nie ścieżka. Chociaż niektórzy popełniają ten błąd, nie ma dowodów na to, że OP ma ...
Stephen C
15

Jeśli proces nie ma uprawnień do stwierdzenia, czy plik istnieje, zwróci false. Otwarcie pliku może być możliwe, ale nie można stwierdzić za pomocą zwykłych metod, czy istnieje.

Tom Hawtin - haczyk
źródło
20
Ciekawy. Czy możesz to rozwinąć? Jakie konkretne uprawnienia masz na myśli?
Clément
Tutaj może być java.nio.file.AccessDeniedException blokujący możliwość dotarcia do istnienia pliku / katalogu. Na przykład, jeśli pozostawisz katalog otwarty w FAR lub innym eksploratorze plików, a następnie usuniesz katalog ze wszystkimi zagnieżdżonymi plikami i sprawdź istnienie tego katalogu, możesz uzyskać AccessDeniedException (rozszerza IOException) dla pliku tymczasowego przechowywanego dla ciebie. W tym przypadku Files.exists zwraca wartość false dla IOException.
beluha,
11

Powyższe odpowiedzi nie pomogły w moim przypadku. Jak wspomniano powyżej, miałem:

file.exists() => false
file.getAbsoluteFile().exists => true

Główną przyczyną tego było to, że właściciel komputera z systemem Windows 7 zmodyfikował rejestr dla CMD, tak aby automatycznie uruchamiał polecenie uruchamiania w określonym katalogu do pracy z Pythonem. Ta modyfikacja sparaliżowała kod Javy 1.6, który najwyraźniej używa CMD w systemie Windows do niektórych operacji na plikach, takich jak exists(). Usunięcie automatycznego uruchamiania z rejestru rozwiązało problem.

Karl Lew
źródło
1
3,5 roku później napotkałem ten sam problem. Miałem skonfigurowany skrypt autorun do konfigurowania zmiennych środowiskowych za każdym razem, gdy uruchamiałem cmd.com. Nie zmienił nawet bieżącego katalogu - tylko niektóre makra doskey i niektóre zmienne środowiskowe. Usunąłem autorun i po prostu ręcznie uruchomiłem polecenia w pliku i nagle File.exists () działa poprawnie.
Homr Zodyssey
1
OMG, to naprawdę działa (oba), po prostu głupio sprawdzałem, czy nie ma niewłaściwego pliku i natknąłem się na to pytanie, aby dowiedzieć się, dlaczego żaden z nich nie działa dla mnie :) Przy okazji, wygląda na ()to, że brakuje w drugiej linii po exists; )
RAM237
3

Gdy ["Ukryj rozszerzenia znanych typów plików."] Jest zaznaczone, okna otwierają "t.txt.txt" po wpisaniu "t.txt" w [eksploratorze] / [uruchom okna], ale programowo nie.

Ja też
źródło
1
Miałem ten problem, a problem polegał na tym, że utworzyłem plik txt o nazwie „testFile.txt” w C: \ test. Odniosłem się do tego pliku, używając ścieżki C: \ test \ testFile.txt, która nie działała. To dlatego, że plik został faktycznie zapisany jako testFile.txt.txt, stąd głosowanie za powyższym rozwiązaniem (stare pytanie, ale brak zaakceptowanej odpowiedzi!)
Theblacknight,
God Windows jest do dupy.
aafc
3

Oczywiście istnieje wiele możliwych przyczyn, a poprzednie odpowiedzi dobrze je dokumentują, ale oto jak rozwiązałem to w jednym konkretnym przypadku:

Mój uczeń miał ten problem i prawie wyrwałem sobie włosy, próbując go rozgryźć. Okazało się, że plik nie istnieje, chociaż na to wyglądał. Problem polegał na tym, że system Windows 7 został skonfigurowany do „Ukrywania rozszerzeń plików dla znanych typów plików”. Oznacza to, że jeśli plik wydaje się mieć nazwę „dane.txt”, jego rzeczywista nazwa to „dane.txt.txt”.

Mam nadzieję, że pomoże to innym zaoszczędzić trochę włosów.

petehern
źródło
Nie sądzę, żeby to był problem w moim przypadku. Jak wspomniałem w moim pytaniu: „Mogę skopiować i wkleić pełną ścieżkę do okna„ Uruchom ”w systemie Windows i plik otwiera się dobrze.”, Co oznacza, że ​​plik faktycznie istnieje.
atsjoo
3

new FileKomenda właśnie tworzy instancję pliku przy użyciu danej nazwy ścieżki. W rzeczywistości nie tworzy pliku na dysku twardym.

Jeśli powiesz

File file = new File ("path");
file.exists() 

Może to zwrócić wartość true tylko wtedy, gdy istnieje plik o tej samej ścieżce. Jeśli zamierzałeś sprawdzić ten sam plik zadeklarowany w pierwszej linii, być może będziesz musiał użyć go w ten sposób.

File file = new File ("path");
file.createNewFile();
file.exists();

Teraz to wróci prawda.

R1234
źródło
małe wyjaśnienie: każde wywołanie konstruktora przy użyciu słowa kluczowego new tworzy Object - tak samo jak w tym przypadku Object opisany przez Class o nazwie File! więc nie jest to instancja File! = descriptors :)
ceph3us
3

Jeśli nie chcesz zajmować się wywołaniami getAbsoluteFile () za każdym razem, gdy musisz wywołać metodę, lepiej utwórz instancję pliku z bezwzględną ścieżką. To powinno załatwić sprawę:

File file = new File("utilities/data/someTextFile.txt").getAbsoluteFile();

Przy okazji proponuję otoczyć go blokiem try-catch.

Fran Marzoa
źródło
3

Uogólniając problem, pojawia się problem podczas konwersji adresu URL / URI na ścieżki lokalne.

Example: URL url = file:/D:/code%20repo%20sample/sample.txt

// To remove url reference
String localPath = url.getPath();  
> /D:/code%20repo%20sample/sample.txt

// Decoding reserved characters in url from hexadecimal to character
URLDecoder.decode(localPath, StandardCharsets.UTF_8.toString()); 
> /D:/code repo sample/sample.txt

Mam nadzieję że to pomoże.

Bieg
źródło
0

Dobre odpowiedzi dla wszystkich. Zauważyłem, że jest to problem z dostępem Javy do C:katalogu głównego w systemie Windows. Każdy inny katalog powinien być w porządku, ale z jakiegoś powodu, szczególnie wspominając C:\lub C:lub C:/może powodować błąd. Rozwiązałem ten bardzo podobny problem, przechwytując wzmiankę do new File("C:");i zastępując ją nową. W File(System.getProperty("file.separator"));przeciwnym razie powinieneś być w stanie zakodować na stałe „\” zamiast mówić „c:” jako katalog plików i może się udać. Nie eleganckie, ale wykonałem swoją pracę przy tym projekcie.

Mam nadzieję, że to pomoże. Może nie jest to właściwe rozwiązanie, ale przynajmniej mi się udało. Jestem włączony JRE 1.6, Win 7. Twoje zdrowie!

Z poważaniem

@ Carpenter1010

Code Carpenter
źródło
0

Jeśli sytuacja, w której się nie powiedzie, wymaga uruchomienia go jako innego użytkownika, a pracujesz w systemie Windows Vista / Windows 7, może to być spowodowane przez VirtualStore, mechanizm, w którym system Windows pozwala nieuprzywilejowanemu użytkownikowi „pisać”, normalnie nie może tego zrobić. Zmiany są jednak przechowywane w „% USERPROFILE% \ AppData \ Local \ VirtualStore \”, które są prywatne dla każdego konta użytkownika.

Kjetil Joergensen
źródło
1
Używam systemu Windows XP x86
atsjoo
0

Kiedy nic z góry nie działało, próbowałem

filePath = filePath.trim();

Spowoduje to oczyszczenie sznurka z wszelkich niechcianych znaków

Asim
źródło
-1

Niedawno natknąłem się na ten sam problem. To, co zrobiłem, to odinstalowanie Netbeans, usunięty folder netbeans z dysku C, pliki programów, aktualizacja, programData, praktycznie wszędzie. Następnie zainstaluj ponownie. Teraz działa dobrze. Nie zapomnij wykonać kopii zapasowej folderu projektu netbeans przed wykonaniem powyższych czynności.

Mam nadzieję, że to pomoże.

Evaboy
źródło
-1

Z niektórymi IDE (może być) i lub z niektórymi systemami operacyjnymi (np. Okno), domyślnie nie mają prawa zapisu plików. Więc jeśli spróbujesz zrobić file.exists (), pokaże ci to false. aby to naprawić, wykonaj poniższe czynności

jeśli zmienną ref dla File jest f, przykład: File f = new File ("path");

więc aby to działało, wybierz f za pomocą myszy, a następnie przejdź do menu Wyszukaj> Dostęp do zapisu> Przestrzeń robocza. Mam nadzieję, że to zadziała.

Gautam Anand
źródło
-2

Myślę, że zamiast tego powinieneś użyć odwrotnego ukośnika, na przykład:

Plik plik = nowy Plik ("C: \\ Użytkownik \\ narzędzia \\ dane \\ jakiśTekstFile.txt"); (dwa ukośniki odwrotne, bez literówki)

Powinien rozwiązać problem :)

Hussein Maziad
źródło
3
Myślę, że problem jest bardziej związany ze ścieżką bezwzględną vs ścieżką względną. Ukośnik jest poprawny w Javie nawet dla ścieżek Windows.
рüффп