【问题标题】:Java on MacOS sees external USB drive as not readable - all other applications see it as readableMacOS 上的 Java 将外部 USB 驱动器视为不可读 - 所有其他应用程序将其视为可读
【发布时间】:2022-11-14 07:02:08
【问题描述】:

Mac OSx(Macbook Pro M1、Monterey 12.3)上的 Java(8 和 17)将外部 USB 驱动器视为不可读。这曾经有效,相信问题是从安装 12.3 开始的。下面的测试例程显示 File(..).canRead() 和 Files.isReadable(..) 都返回 false。所有其他应用程序(Finder、终端、Time Machine)都使用相同的驱动器,没有任何问题。提交给 Apple 的问题报告,但有其他人看到过这个问题吗?

注意:如果驱动器不可读,则 File(..).listFiles() 返回 NULL 并且 Files.list(..) 引发异常。

import java.nio.file.*;
import java.io.*;

/** Test routine for failure to access external USB drive (USBExtA in testPath) from Java.
 *
 *  The testPath is attempting to access Time Machine backups on the external drive, which shows as not readable in Java.
 *  BUT IT IS READABLE with no problems from Finder, the terminal, and other applications. Time Machine is still
 *  successfully writing backups to this drive.
 *
 *  THIS USED TO WORK -- believe that it stopped working with installation of Monterey 12.3, and took a while
 *                       before I noticed the problem (but not exactly sure of the date when 12.3 installed).
 *
 *  ----------- Output of executions using Java 8 and Java 17 ------------------
 *
 * --------- Execution Context ----------
 *       java.version -- 1.8.0_311
 *        java.vendor -- Oracle Corporation
 *    java.vm.version -- 25.311-b11
 *     java.vm.vendor -- Oracle Corporation
 * java.class.version -- 52.0
 *            os.name -- Mac OS X
 *            os.arch -- x86_64
 *         os.version -- 10.16
 *
 * java.io.File -- Exists:  T , Readable:  T , Dir:  T , java.nio.Files -- Exists:  T , Readable:  T , Dir:  T  --- PATH: /Volumes
 * java.io.File -- Exists:  T , Readable: *F*, Dir:  T , java.nio.Files -- Exists:  T , Readable: *F*, Dir:  T  --- PATH: /Volumes/USBExtA
 *
 *  --------- Execution Context ----------
 *       java.version -- 17.0.1
 *        java.vendor -- Oracle Corporation
 *    java.vm.version -- 17.0.1+12-LTS-39
 *     java.vm.vendor -- Oracle Corporation
 * java.class.version -- 61.0
 *            os.name -- Mac OS X
 *            os.arch -- aarch64
 *         os.version -- 12.3
 *
 * java.io.File -- Exists:  T , Readable:  T , Dir:  T , java.nio.Files -- Exists:  T , Readable:  T , Dir:  T  --- PATH: /Volumes
 * java.io.File -- Exists:  T , Readable: *F*, Dir:  T , java.nio.Files -- Exists:  T , Readable: *F*, Dir:  T  --- PATH: /Volumes/USBExtA
 */
public class ExtUSBTest {

  public static String testPath = "/Volumes/USBExtA/Backups.backupdb/JDCMacBook";

  public static void main(String[] args) {
    showContext("java.version", "java.vendor", "java.vm.version", "java.vm.vendor", "java.class.version",
                "os.name", "os.arch", "os.version");

    checkPath(Paths.get(testPath));
  }

  /** Recursively check all sub-components of the given path - stops if not exists && readable */
  public static boolean checkPath(Path path) {
    if(path.getParent() == null)
      return true;
    else if(checkPath(path.getParent()))
      return checkThisPath(path);
    else
      return false;
  }
  /** Check this particular path to see if exists & readable */
  public static boolean checkThisPath(Path path) {
    File f            = path.toFile();
    boolean fExists   = f.exists();
    boolean fReadable = f.canRead();
    boolean fDir      = f.isDirectory();
    boolean pExists   = Files.exists(path);
    boolean pReadable = Files.isReadable(path);
    boolean pDir      = Files.isDirectory(path);

    String rslt = String.format("java.io.File -- Exists: %s, Readable: %s, Dir: %s, java.nio.Files -- Exists: %s, Readable: %s, Dir: %s --- PATH: %s",
                                  bstr(fExists), bstr(fReadable), bstr(fDir), bstr(pExists), bstr(pReadable), bstr(pDir), path.toString());
    ln(rslt);
    return (fExists && fReadable) || (pExists && pReadable);
  }
  public static void showContext(String ... props) {
    ln("--------- Execution Context ----------");
    for(int i = 0; i<props.length; i++) showProp(props[i]);
    ln("");
  }
  public static void showProp(String property) {
    ln(String.format("%18s -- %s", property, System.getProperty(property)));
  }
  public static String bstr(boolean b) { return b ? " T " : "*F*";}

  public static void ln(String s) { System.out.println(s); }
}

【问题讨论】:

  • 可能是您需要授予权限吗?在 System Preferences > Security & Privacy 下有一个 Files and Folders 部分,您可以在其中管理此类权限。
  • @gpunto - 好建议。向 Java 添加了“完全磁盘访问”,但结果没有变化。还在原始文件中添加了一个关键行,即 File.listFiles(..) 返回 NULL 并且 Files.list(path) 在目录不可读时抛出异常。

标签: java macos external drive


【解决方案1】:

当我在 Monterey 12.3 上运行的 M1-Pro Mac 上运行上述代码时,我看到以下输出。所以,我不认为这是特定于最新版本的 Monterey(12.3)!

    **--------- Execution Context ----------
      java.version -- 17.0.2
       java.vendor -- Amazon.com Inc.
   java.vm.version -- 17.0.2+8-LTS
    java.vm.vendor -- Amazon.com Inc.
java.class.version -- 61.0
           os.name -- Mac OS X
           os.arch -- aarch64
        os.version -- 12.3
java.io.File -- Exists:  T , Readable:  T , Dir:  T , java.nio.Files -- Exists:  T , Readable:  T , Dir:  T  --- PATH: /Volumes
java.io.File -- Exists:  T , Readable:  T , Dir:  T , java.nio.Files -- Exists:  T , Readable:  T , Dir:  T  --- PATH: /Volumes/SSD1
java.io.File -- Exists:  T , Readable:  T , Dir:  T , java.nio.Files -- Exists:  T , Readable:  T , Dir:  T  --- PATH: /Volumes/SSD1/cp**

【讨论】:

  • 有趣的!所以我们在 JVM、编译器和外部设备方面存在差异。您的外部设备是通过 USB、火线、以太网连接的吗?我有一个 Sabrent USB 驱动器盒通过 Belkin 扩展坞。怀疑是 12.3,因为以前使用相同的设备、编译器和 JVM。谢谢(你的)信息。
【解决方案2】:

抱歉,不是答案 - 附加信息 - 但需要更多空间。希望 StackOverflow 允许附加文件!!!

编写了一个独立的测试例程(粘贴在下面)。这个作品什么时候

  • 在我自己的 ID(管理员)下运行
  • 以普通用户身份运行
  • 以“root”身份登录(并运行)

示例输出:


Starting ....... at Sun Nov 13 17:24:15 EST 2022
        User: jdc
       Drive: /Volumes/USBExtA
      Exists: true
   isSymlink: false
 isDirectory: true
  isReadable: true          ----- NOTE
isExecutable: true

Level  1, Read  10 children, skipped   0, For: /Volumes/USBExtA
Level  2, Read   1 children, skipped   0, For: /Volumes/USBExtA/....
... rest omitted

它确实不是工作时

  • 在“系统”级别的 launchctl 下运行
  • 在“用户”级别的 launchctl 下运行

示例输出:

开始 ....... 2022 年 11 月 13 日星期日 16:34:02 EST
        用户:root ---- 在'root'下运行
       Drive: /Volumes/USBExtA ----完全一样的挂载
      存在:真实
   isSymlink: false
 isDirectory:真
  isReadable: false ----- 注意 - 现在不可读
可执行:真


.........完成于 2022 年 11 月 13 日星期日 16:34:02 EST

(通过 launchctl 在“jdc”下运行时获得相同的输出)

完整的测试代码(注意:一些符号,例如小于号,替换为 HTML 条目,例如 <):



    import java.nio.file.*;
    import java.util.Date;
    /** Test routine to access a mounted volume and attempt to read N levels of directories/files.
     *
     * Usage: java -jar [path/]JavaReadUSB.jar pathToMountedDrive N      -- where N is number of levels to read (may be 0)
     *
     * Example: java -jar /Users/myuser/tmp/JavaReadUSB.jar /Volumes/USBDrive 4
     *
     */
    public class ReadUSBMain {
      public static void main(String[] args) {
        ln("");
        ln("Starting ....... at " + new Date().toString());
        if(args==null || args.length &lt 2)
          showUsage();
        else {
          String mount = args[0];
          int nTo      = getN(args);
    
          Path path = Paths.get(mount);
          if(pathOK(path)){
            processOneLevel(path, 1, nTo);
          }
        }
        ln("");
        ln(".........Finished at " + new Date().toString());
        ln("");
      }
    
      public static void processOneLevel(Path dir, int nLevel, int nTo){
        int skipped = 0;
        if(nLevel <= nTo) {
          try {
            Object[] arr = Files.list(dir).toArray();
            for(int i = 0; i < arr.length; i++){
              Path p = (Path) arr[i];
              if(Files.isSymbolicLink(p) || (Files.isDirectory(p) && !Files.isReadable(p))) skipped++;
            }
            ln(String.format("Level %2d, Read %3d children, skipped %3d, For: %s", nLevel, arr.length, skipped, dir.toString()));
            for(int i = 0; i < arr.length; i++){
              Path p = (Path) arr[i];
              if(!Files.isSymbolicLink(p) && Files.isDirectory(p) && Files.isReadable(p)) processOneLevel(p, nLevel + 1, nTo);
            }
          } catch (Exception e) {
            err("Directory: " + dir.toString() + " Threw: " + e.toString());
          }
        }
      }
      public static boolean pathOK(Path path) {
        boolean exists       = Files.exists(path);
        boolean isSymLink    = Files.isSymbolicLink(path);
        boolean isDir        = exists && Files.isDirectory(path);
        boolean isReadable   = exists && Files.isReadable(path);
        boolean isExecutable = exists && Files.isExecutable(path);
    
        ln("        User: " + System.getProperty("user.name"));
        ln("       Drive: " + path.toString());
        ln("      Exists: " + exists);
        ln("   isSymlink: " + isSymLink);
        ln(" isDirectory: " + isDir);
        ln("  isReadable: " + isReadable);
        ln("isExecutable: " + isExecutable);
        ln("");
        return isDir && isReadable;
      }
      public static int getN(String[] args){
        return Integer.parseInt(args[1]);
      }
      public static void showUsage(){
        ln("");
        ln("Usage: java -jar [path/]JavaReadUSB.jar pathToMountedDrive Nlevels");
        ln("");
        ln("Example: java -jar /Users/myuser/tmp/JavaReadUSB.jar /Volumes/USBDrive 4");
        ln("");
        ln("         N may be zero. Will show whether drive is readable, but not actually read anything.");
        ln("");
        ln("         Note: Any Symlink or directory which is not Readable is skipped and a count shown in the output");
        ln("");
      }
      public static void ln(String str) { System.out.println(str); }
      public static void err(String str){
        ln("");
        ln("ERROR -- " + str);
        ln("");
      }
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多