File.exists () trả về false khi tệp tồn tại


90

Tôi đã gặp một lỗi mà tôi dường như không thể tìm thấy bất kỳ logic nào đằng sau. Tôi có đối tượng Tệp này, được tạo như thế này:

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

Sau đó tôi làm file.exists(), và nó trả về false(!?). Nếu tệp không được tìm thấy, tôi đang đăng nhập f.getAbsolutePath()vào một tệp. Khi tôi nhìn vào con đường, nó có vẻ ổn. Tôi có thể sao chép-dán đường dẫn hoàn chỉnh vào cửa sổ "Run" trong Windows và tệp mở ra tốt.

Tệp luôn tồn tại và không bị xóa cũng như không bị thay đổi trong quá trình chạy ứng dụng của tôi. Nó nằm ở máy cục bộ.

Điều này dường như chỉ xảy ra trong một số tình huống nhất định. Tôi có thể tái tạo lỗi bất kỳ lúc nào, nhưng tôi chắc chắn rằng đường dẫn của đối tượng tệp không bị thay đổi bởi các hành động tôi thực hiện để tái tạo lỗi.

Điều gì có thể khiến file.exists()trả về false? Điều này có liên quan gì đến quyền hoặc khóa tệp, v.v. không?


Vì vậy, có thể đọc từ tệp ngay cả khi hàm tồn tại () trả về giá trị false?
Harry Lime

có, tôi có thể đọc từ tệp ngay cả khi hàm tồn tại () trả về giá trị false.
atsjoo

1
Chính xác thì điều gì là cần thiết để tạo lại lỗi?
user85421

1
Đây là bên trong một ứng dụng gọi các hàm được viết bằng matlab và được biên dịch vào ứng dụng java. Có vẻ như các hàm matlab thay đổi "thư mục hiện tại" đang gây ra sự cố xuất hiện. Tôi đang sử dụng đường dẫn tuyệt đối khi tạo đối tượng tệp, vì vậy đây không phải là vấn đề - tuy nhiên có vẻ như vậy. Tất nhiên tôi đã xác minh đường dẫn tuyệt đối của đối tượng tệp và nó đúng (giống như trước khi hàm matlab thay đổi thư mục hiện tại).
atsjoo

7
Bạn có tình cờ làm việc với một thư mục từ xa (ví dụ như một NFS mount) không?
Tomer Gabel

Câu trả lời:


42

Tôi gặp tình huống sau trên Windows 7:

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

Tệp được đề cập là "var \ log", đường dẫn tuyệt đối đề cập đến tệp hiện có nằm trong thư mục con bình thường (không phải cửa hàng ảo). Điều này được nhìn thấy từ IDE.


16
Tôi vừa mới tìm ra: bug.sun.com/bugdatabase/view_bug.do;:YfiG?bug_id=4483097 Rõ ràng, các hoạt động chạy trên tệp được giải quyết dựa trên thư mục hiện tại, trong khi getAbsolutePath giải quyết dựa trên user.dir. Nếu hai con đường này không khớp, bạn sẽ nhận được kết quả trái ngược nhau. Đồ quỷ!
Roman Zenka

3
Tôi gặp cùng một vấn đề chính xác, tôi đã cố gắng sử dụng cả hai phương pháp để kiểm tra xem tệp có tồn tại hay không và tôi vẫn nhận được sai trên Windows 7! Bất kỳ ý tưởng?
Dejell

@Odelya: Bạn đang sử dụng IDE nào? -Duser.dir của bạn được đặt thành gì? Sự cố của tôi là do đặt -Duser.dir vào một thư mục khác với thư mục đang hoạt động hiện tại.
Roman Zenka

1
Đối với bất kỳ ai đang làm việc trên Dự án Web Động, việc sử dụng file.exists () sẽ đưa ra một ngoại lệ, hãy sử dụng file.getAbsoluteFile (). Being () để kiểm tra các tệp trong thư mục WEB-INF (mẹo chung, không phải dành riêng cho Windows 7 ).
Tái

Cân nhắc tạo một QA riêng cho câu trả lời và nhận xét này
Bato-Bair Tsyrenov

17

Có vẻ như có sự khác biệt về cách đường dẫn được chỉ định trong Java.

Ví dụ: nếu đường dẫn tệp được chỉ định file:/C:/DEV/test.txtsau đó

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

sẽ trở lại false. Đường dẫn có thể hoạt động trong trình thám hiểm hoặc trong trình duyệt, nhưng nó là một URL chứ không phải đường dẫn tệp tuyệt đối.

Nhưng mặt khác, nếu đường dẫn tệp được chỉ định C:/DEV/test.txtthì

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

sẽ trả về truevì đường dẫn không phải là URL, nhưng nó là đường dẫn tuyệt đối.

Với Spring Framework đó chính xác là những gì ResourceUtils.getFile(filename)- trong đó tên có thể là một URL hoặc đường dẫn tệp tuyệt đối.


5
Tôi sẽ không mong đợi file:/C:/DEV/test.txthoạt động như một tên đường dẫn. Đó là một URL không phải là một tên đường dẫn. Trong khi một số người làm sai lầm này, không có bằng chứng cho thấy OP có ...
Stephen C

15

Nếu quá trình không có quyền cho biết liệu tệp có tồn tại hay không, nó sẽ trả về false. Có thể mở một tệp, nhưng không thể thông báo bằng các phương pháp thông thường nếu nó tồn tại.


20
Hấp dẫn. Bạn có thể mở rộng về điều này? Bạn có những quyền cụ thể nào?
Clément

Đây có thể là khả năng chặn java.nio.file.AccessDeniedException để tiếp cận sự tồn tại của tệp / dir. Ví dụ: nếu bạn tiếp tục mở dir trong FAR hoặc trình khám phá tệp khác, sau đó xóa dir với tất cả các tệp lồng nhau và kiểm tra sự tồn tại của dir này, sau đó bạn có thể nhận AccessDeniedException (mở rộng IOException) cho tệp tạm thời được lưu giữ cho bạn. Trong trường hợp này Files.exists trả về false cho IOException.
beluha

11

Các câu trả lời trên không giúp được gì trong trường hợp của tôi. Như đã nêu ở trên, tôi đã:

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

Nguyên nhân gốc rễ của điều này là chủ sở hữu máy Windows 7 đã sửa đổi sổ đăng ký cho CMD để nó tự động chạy một lệnh để khởi chạy trong một thư mục cụ thể để làm việc với Python. Sửa đổi này đã làm tê liệt mã Java 1.6 dường như sử dụng CMD trên Windows cho các hoạt động tệp nhất định, chẳng hạn như exists(). Loại bỏ tự động chạy khỏi sổ đăng ký đã giải quyết được vấn đề.


1
3,5 năm sau, và tôi gặp phải vấn đề tương tự. Tôi đã thiết lập tập lệnh chạy tự động để định cấu hình các biến môi trường mỗi khi khởi chạy cmd.com. Nó thậm chí không thay đổi thư mục hiện tại - chỉ một số macro doskey và một số biến môi trường. Tôi đã xóa tự động chạy và chỉ chạy thủ công các lệnh trong tệp, và đột nhiên File.exists () hoạt động chính xác.
Homr Zodyssey

1
OMG, nó thực sự hoạt động (cả hai), tôi chỉ ngây ngốc kiểm tra tệp sai và bắt gặp câu hỏi này để tìm hiểu tại sao không có tệp nào trong số chúng hoạt động với tôi :) BTW, có vẻ như ()bị thiếu ở dòng thứ hai sau exists; )
RAM237

3

Rõ ràng là có một số nguyên nhân có thể xảy ra và các câu trả lời trước đó ghi lại chúng rất tốt, nhưng đây là cách tôi giải quyết vấn đề này cho một trường hợp cụ thể:

Một học sinh của tôi đã gặp vấn đề này và tôi gần như vò đầu bứt tóc khi cố gắng tìm ra nó. Hóa ra là tệp không tồn tại, mặc dù nó trông giống như vậy. Vấn đề là Windows 7 đã được định cấu hình để "Ẩn phần mở rộng tệp cho các loại tệp đã biết." Điều này có nghĩa là nếu tệp dường như có tên "data.txt" thì tên tệp thực của nó là "data.txt.txt".

Hy vọng điều này sẽ giúp những người khác tiết kiệm cho mình một số tóc.


Tôi không nghĩ đây là vấn đề trong trường hợp của tôi. Như đã đề cập trong câu hỏi của tôi: "Tôi có thể sao chép-dán đường dẫn hoàn chỉnh vào" Run "-window trong Windows và tệp mở ra tốt.", Có nghĩa là tệp thực sự tồn tại.
atsjoo

3

Các new Filelệnh chỉ tạo ra một thể hiện của một tập tin bằng cách sử dụng tên đường dẫn nhất định. Nó không thực sự tạo một tệp trên ổ cứng.

Nếu bạn nói

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

Điều này chỉ có thể trả về true nếu có một tệp hiện có có cùng đường dẫn. Nếu bạn định kiểm tra cùng một tệp được khai báo trong dòng đầu tiên, bạn có thể cần sử dụng nó theo cách này.

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

Bây giờ điều này sẽ trở lại đúng.


giải thích nhỏ: mọi lệnh gọi đến hàm tạo bằng cách sử dụng từ khóa mới sẽ tạo ra một Đối tượng - giống như trong trường hợp này một Đối tượng được mô tả bởi Lớp có tên là Tệp! vì vậy không phải là một phiên bản của File! = descriptors :)
ceph3us

3

Nếu bạn không muốn đối phó với các cuộc gọi getAbsoluteFile () mỗi khi bạn phải gọi một phương thức, tốt hơn bạn nên tạo cá thể tệp của mình với một đường dẫn tuyệt đối. Cái này cần phải dùng mẹo:

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

Tôi đề nghị bao quanh nó bằng một khối try-catch, BTW.


3

Để khái quát vấn đề, vấn đề phát sinh trong khi chuyển đổi URL / URI thành đường dẫn cục bộ.

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

Hi vọng điêu nay co ich.


2

Khi chọn ["Ẩn phần mở rộng cho các loại tệp đã biết."], Các cửa sổ sẽ mở "t.txt.txt" khi nhập "t.txt" trong [explorer] / [chạy cửa sổ] nhưng không phải theo chương trình.


1
Tôi gặp sự cố này và vấn đề là tôi đã tạo một tệp txt, được gọi là 'testFile.txt', trong C: \ test. Tôi đã tham chiếu đến tệp này bằng đường dẫn C: \ test \ testFile.txt, đường dẫn này không hoạt động. Đó là vì tệp thực sự đã được lưu dưới dạng testFile.txt.txt, do đó đã bỏ phiếu ủng hộ giải pháp trên (Câu hỏi cũ, nhưng không có câu trả lời nào được chấp nhận!)
Theblacknight 22/02/12

Chúa ơi Windows tệ quá.
aafc

0

Mọi người phản hồi tốt. Tôi nhận thấy đây có vẻ là vấn đề với Java khi truy cập C:thư mục gốc trên Windows. Bất kỳ thư mục nào khác sẽ ổn, nhưng vì một số lý do, đề cập cụ thể C:\hoặc C:hoặc C:/có thể xuất hiện lỗi. Tôi đã giải quyết vấn đề tương tự này bằng cách đánh dấu đề cập đến new File("C:");và thay thế nó bằng mới File(System.getProperty("file.separator"));hoặc bạn có thể viết mã cứng "\" thay vì nói "c:" làm thư mục tệp của bạn và nó có thể hoạt động. Không thanh lịch, nhưng đã hoàn thành công việc cho tôi trong dự án này.

Tôi hy vọng nó sẽ giúp. Có thể không phải là giải pháp phù hợp, nhưng ít nhất nó đã hiệu quả với tôi. Tôi đang ở trên JRE 1.6, Win 7. Chúc mừng!

Trân trọng,

@ Thợ mộc1010


0

Nếu các tình huống mà nó không thành công liên quan đến việc chạy nó với tư cách người dùng khác và bạn đang sử dụng Windows Vista / Windows 7, thì đó có thể là do VirtualStore, cơ chế mà Windows cho phép người dùng không có đặc quyền "ghi" vào những nơi mà nó thường không thể. Tuy nhiên, các thay đổi được lưu trữ trong "% USERPROFILE% \ AppData \ Local \ VirtualStore \" là riêng tư cho mỗi tài khoản người dùng.


1
Tôi đang chạy trên windows xp x86
atsjoo

0

Khi không có gì từ trên cao phù hợp với tôi, tôi đã cố gắng

filePath = filePath.trim();

Điều này sẽ làm sạch chuỗi của bạn khỏi bất kỳ ký tự không mong muốn nào


0

Gần đây tôi đã gặp vấn đề tương tự. Những gì tôi đã làm là gỡ cài đặt Netbeans, xóa thư mục netbeans khỏi ổ C, tệp chương trình, cập nhật, dữ liệu chương trình, hầu như ở khắp mọi nơi. Sau đó cài đặt lại. Bây giờ đang hoạt động tốt. Đừng quên sao lưu thư mục dự án netbeans trước khi thực hiện các thao tác trên.

Hy vọng nó giúp.


0

Với một số IDE (có thể là) và hoặc với một số hệ điều hành (ví dụ: window), theo mặc định, chúng không có quyền ghi vào tệp. Vì vậy, nếu bạn cố gắng thực hiện file.exists (), nó sẽ hiển thị cho bạn sai. để khắc phục điều này, hãy làm như dưới đây

nếu biến ref của bạn cho File là f, ví dụ: File f = new File ("đường dẫn");

vì vậy để làm cho nó hoạt động, hãy chọn f bằng chuột và sau đó đi tới menu Tìm kiếm> Quyền ghi> Không gian làm việc. Hy vọng rằng nó sẽ hoạt động.


-2

Tôi nghĩ bạn nên sử dụng dấu gạch chéo ngược thay thế, như thế này:

File file = new File ("C: \\ Người dùng \\ tiện ích \\ data \\ someTextFile.txt"); (hai dấu gạch chéo ngược, không phải một lỗi chính tả)

Nên giải quyết vấn đề :)


3
Tôi nghĩ rằng vấn đề liên quan nhiều hơn đến đường dẫn tuyệt đối so với đường dẫn tương đối. Dấu gạch chéo hợp lệ trong Java ngay cả đối với đường dẫn Windows.
рüффп
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.