2012-10-02 20 views
5

tôi có mã Java làm như sau:java.nio.file.Files.isWriteable không đồng ý với java.io.File.canWrite()

  1. Tạo một file trống tạm thời với phần mở rộng ZIP sử dụng File.createTempFile()
  2. Xóa nó với File.delete() (chúng tôi chỉ thực sự muốn có nó để tạo ra một tên tập tin tạm thời)
  3. Sao chép một "mẫu" tập tin ZIP với các đường dẫn tương tự với com.google.commons.io.ByteStreams.copy() sử dụng mới OutputSupplier đưa ra cùng filename
  4. Sửa đổi các bưu điện lưu trữ (xóa trực tiếp ory) sử dụng TrueZIP 7.4.3

Trên một hệ thống cụ thể, bước 4 thất bại liên tục với FsReadOnlyArchiveFileSystemException - "This is a read-only archive file system!" (xem http://java.net/projects/truezip/lists/users/archive/2011-05/message/9)

Gỡ rối mã TrueZIP, tôi nhận thấy như sau:

  • Có không có tệp mở nào xử lý tệp này giữa bất kỳ bước nào ở trên và đặc biệt không phải trước bước 4
  • Kiểm tra cùng một tệp với File.canWrite() thay vì NIO trả về cùng một thời điểm (sử dụng trình gỡ lỗi). cái đó nó là ghi

Dưới đây là những gì bạn thấy trong danh sách biểu debugger:

fn => "C:/myworkdir/temp/myfile4088293380313057223tmp.zip" 
java.nio.file.Files.isWritable(java.nio.file.Paths.get(fn)) => false 
new java.io.File(fn).canWrite() => true 

Sử dụng JDK 1.7.04

Bất kỳ ý tưởng?

+0

Tôi sẽ thử bản cập nhật Java 7 7 để xem lỗi của nó đã được sửa chưa. –

+0

Tôi sẽ tránh sử dụng cả hai API và thay vào đó dựa vào các ngoại lệ được ném bằng ví dụ: 'FileOutputStream() mới '. – EJP

+0

tôi sẽ không sử dụng java 7, để bắt đầu với – njzk2

Trả lời

3

Tôi sẽ tránh sử dụng cả hai API và thay vào đó dựa vào các ngoại lệ được ném bằng ví dụ: new FileOutputStream(). Họ ít nhất là có thật, và quan tâm thực sự. Sử dụng các API mà bạn đề cập là hoàn toàn vô nghĩa và nó giới thiệu các cửa sổ thời gian và mã lặp lại. Bạn phải nắm bắt các IOException anyway: tại sao viết tất cả các mã hai lần?

+0

Điều đó có thể đúng, nhưng câu trả lời của bạn không giải thích lý do tại sao cả hai đưa ra một kết quả khác nhau trong trường hợp này. (xem tiêu đề) – Puce

+0

Bài kiểm tra là một phần của mã TrueZIP thực sự và không thể tránh được vì phụ thuộc vào kết quả, bạn có thể được phép ghi vào hệ thống tệp ảo hay không. –

+1

@Puce Đôi khi câu trả lời cho câu hỏi là làm theo cách khác. – EJP

5

Kết quả cuối cùng là không quá ngạc nhiên:

java.nio.file.Files.isWritable(java.nio.file.Paths.get(fn)) => false 
new java.io.File(fn).canWrite() => true 

File.canWrite không chú ý đến ACL ở tất cả và chỉ kiểm tra MS-DOS thuộc tính chỉ đọc.

Files.isWriteable chú ý đến ACL nhưng vì bất kỳ lý do gì (để giữ cho các chương trình bị hỏng bị hỏng?), Chúng rời File.canWrite un-fixed. Điều này hóa ra là may mắn, bởi vì trong một số trường hợp, có vẻ như nó có thể trả về sai ngay cả khi bạn có thể mở tệp mà không gặp vấn đề gì.

Thực sự, tôi sẽ tóm tắt các phương pháp như thế này:

  • File.canWrite đôi khi trả về true khi bạn không thể thực sự ghi vào tập tin.
  • Files.isWriteable đôi khi trả về false khi bạn thực sự có thể ghi vào tệp.

Tôi không chắc điểm của một trong hai phương pháp là ngay bây giờ. Vì tất cả những người sử dụng những điều này cuối cùng phải viết một số tương đương không bị hỏng mà thực sự cố mở tệp, người ta tự hỏi tại sao họ không chỉ mở tệp để tự kiểm tra.

+0

Vì https://bugs.openjdk.java.net/browse/JDK-7190897 Files.isWritable hoạt động như mong đợi. –

+0

Tôi nghĩ rằng nó vẫn được khuyến khích để chỉ cần thực hiện các hoạt động, thay vì kiểm tra và sau đó thực hiện nó, bởi vì kết quả của Files.isWritable là ngay lập tức lỗi thời, ngay cả khi nó _was_ chính xác. Cùng đi cho isReadable, tồn tại, notExists, isRegularFile, isDirectory, isSymbolicLink, và có lẽ nhiều hơn nữa. – Trejkaz

5

Có lỗi trong java.nio.file.Files.isWritable trong cửa sổ: nó sẽ không xem xét các quyền tiềm ẩn. java bug #7190897

+3

Cập nhật: lỗi này đã được sửa trong Java 8 (b84) và được chuyển thành Java 7u40. –

Các vấn đề liên quan