为什么 `Files.isWritable()` 方法对于一个设置为只读的目录返回true?

huangapple go评论75阅读模式
英文:

Why does Files.isWritable() method return true for a directory even when it is set to read only?

问题

我已经明确通过setReadOnly方法和setWritable(false)方法将只读模式设置为只读模式。

File file = new File(myDir);
file.setReadOnly();
file.setWritable(false);
file.setExecutable(false);
return file.canWrite();

我还通过Windows资源管理器检查了指定的目录是否标记为只读:

在上面的示例中,file.canWrite返回true。是否有更严格的方式来强制只读模式?

英文:

I have explicitly set read only mode both through setReadOnly method as well as setWritable(false).

File file  = new File(myDir);
file.setReadOnly();
file.setWritable(false);
file.setExecutable(false);
return file.canWrite();

I also checked through windows explorer that the specified directory is marked read-only:

为什么 `Files.isWritable()` 方法对于一个设置为只读的目录返回true?

In the above example , the file.canWrite returns true. Is there a stricter way of enforcing read only mode?

答案1

得分: 1

对于 [java.io.File][1] 的 API 规范声明如下,作为一种免责声明:

> 文件系统可以对实际文件系统对象执行某些操作实施限制,如读取、写入和执行。
> 这些限制统称为访问权限。文件系统可以在单个对象上具有多组访问权限。
> 例如,一组可能适用于对象的所有者,另一组可能适用于所有其他用户。对象的访问权限可能导致此类中的某些方法失败。

而且在你的情况下确实是这样。在 Linux(Ubuntu-18.04)上,一切看起来都非常正常,符合规范。
以下是在两个环境中使用 Java sdk-1.8.0_222 运行以下代码的输出:

    import java.io.File;
    
    public class FileDemo {
    
       public static void main(String[] args) {
          File f = null;
          boolean bool = false;
    
          try {
    
             // 创建新文件
             f = new File("test");
    
             f.setWritable(false);
             bool = f.canWrite();
             System.out.println("Can write to test: " + bool);
             f.setWritable(true);
             bool = f.canWrite();
             System.out.println("Can write to test: " + bool + "\n\n");
    
                     f.mkdir();
                     //f.createNewFile();
    
                     f.setWritable(false);
             bool = f.canWrite();
             System.out.println("Can write to test: " + bool);
             f.setWritable(false);
             bool = f.canWrite();
             System.out.println("Can write to test: " + bool);
    
          } catch(Exception e) {
    
             // 如果发生任何I/O错误
             e.printStackTrace();
          }
       }
    }

Windows(文件) -

    C:\Users\rranjan\Desktop>java FileDemo
    Can write to test: false
    Can write to test: false
    
    
    Can write to test: false
    Can write to test: true
    
    C:\Users\rranjan\Desktop>java FileDemo
    Picked up _JAVA_OPTIONS: -Djava.net.preferIPv4Stack=true
    Can write to test: false
    Can write to test: true
    
    
    Can write to test: false
    Can write to test: true

Linux(文件) -

    rranjan@my-workstation:~/scratch/java$ java FileDemo
    Can write to test: false
    Can write to test: false
    
    
    Can write to test: false
    Can write to test: true
    rranjan@my-workstation:~/scratch/java$ java FileDemo
    Can write to test: false
    Can write to test: true
    
    
    Can write to test: false
    Can write to test: true

Windows(目录) -

    C:\Users\rranjan\Desktop>java FileDemo
    Can write to test: false
    Can write to test: false
    
    
    Can write to test: true
    Can write to test: true
    
    C:\Users\rranjan\Desktop>java FileDemo
    Picked up _JAVA_OPTIONS: -Djava.net.preferIPv4Stack=true
    Can write to test: true
    Can write to test: true
    
    
    Can write to test: true
    Can write to test: true

Linux(目录) -

    rranjan@my-workstation:~/scratch/java$ java FileDemo
    Can write to test: false
    Can write to test: false
    
    
    Can write to test: false
    Can write to test: true
    rranjan@my-workstation:~/scratch/java$ java FileDemo
    Can write to test: false
    Can write to test: true
    
    
    Can write to test: false
    Can write to test: true

现在,你可以观察到对于文件或目录,如果它不存在,`canWrite()` 总是返回 `False`。
在 Linux 平台上创建文件/目录后,对于文件和目录,设置可写性都可以正常工作。然而,在 Windows 上,目录似乎总是返回 true。这正是我在上面引用的行为方式。

  [1]: https://docs.oracle.com/javase/7/docs/api/java/io/File.html
英文:

The api specification for java.io.File states the following as kind of disclaimer -

> A file system may implement restrictions to certain operations on the
> actual file-system object, such as reading, writing, and executing.
> These restrictions are collectively known as access permissions. The
> file system may have multiple sets of access permissions on a single
> object. For example, one set may apply to the object's owner, and
> another may apply to all other users. The access permissions on an
> object may cause some methods in this class to fail.

And definitely this is the case with you. On Linux(Ubuntu-18.04) things look to be very normal and as per specification.
Outputs for the following code using Java sdk-1.8.0_222 in the 2 environments is printed below

import java.io.File;
public class FileDemo {
public static void main(String[] args) {
File f = null;
boolean bool = false;
try {
// create new file
f = new File("test");
f.setWritable(false);
bool = f.canWrite();
System.out.println("Can write to test: "+bool);
f.setWritable(true);
bool = f.canWrite();
System.out.println("Can write to test: "+bool+"\n\n");
f.mkdir();
//f.createNewFile();
f.setWritable(false);
bool = f.canWrite();
System.out.println("Can write to test: "+bool);
f.setWritable(false);
bool = f.canWrite();
System.out.println("Can write to test: "+bool);
} catch(Exception e) {
// if any I/O error occurs
e.printStackTrace();
}
}
}

Windows (file) -

C:\Users\rranjan\Desktop>java FileDemo
Can write to test: false
Can write to test: false
Can write to test: false
Can write to test: true
C:\Users\rranjan\Desktop>java FileDemo
Picked up _JAVA_OPTIONS: -Djava.net.preferIPv4Stack=true
Can write to test: false
Can write to test: true
Can write to test: false
Can write to test: true

Linux (file) -

rranjan@my-workstation:~/scratch/java$ java FileDemo
Can write to test: false
Can write to test: false
Can write to test: false
Can write to test: true
rranjan@my-workstation:~/scratch/java$ java FileDemo
Can write to test: false
Can write to test: true
Can write to test: false
Can write to test: true

Windows (directory) -

C:\Users\rranjan\Desktop>java FileDemo
Can write to test: false
Can write to test: false
Can write to test: true
Can write to test: true
C:\Users\rranjan\Desktop>java FileDemo
Picked up _JAVA_OPTIONS: -Djava.net.preferIPv4Stack=true
Can write to test: true
Can write to test: true
Can write to test: true
Can write to test: true

Linux (directory) -

rranjan@my-workstation:~/scratch/java$ java FileDemo
Can write to test: false
Can write to test: false
Can write to test: false
Can write to test: true
rranjan@my-workstation:~/scratch/java$ java FileDemo
Can write to test: false
Can write to test: true
Can write to test: false
Can write to test: true

Now, you can observe that for a file or directory, if it doesn't exist, canWrite() is always False.
After the file/directory is created on a Linux platform, for both a file as well as a directory, setting writeable works seamlessly. Whereas, on a Windows box, directory seems to return true whatsoever. This is the kind of behavior which I quoted in the above lines.

huangapple
  • 本文由 发表于 2020年4月6日 18:16:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/61057493.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定