2

我正在寻找一种在不更新文件的最后访问时间的情况下读取 Java 文件内容的方法。在 Linux 上的 C 中,这是通过将O_NOATIME标志open传递给 来实现的,我相信其他语言和平台也有类似的机制。

我正在使用Files.newInputStreamwhich 具有可以传递的各种选项,但没有一个似乎匹配O_NOATIME.

有没有办法在类unix平台上读取Java文件的内容而不更新文件的最后访问时间?

4

1 回答 1

1

我认为在 Java 中没有办法做到这一点(除了用 JNI OFC 本地实现它)。我在 Github 上搜索了 JDK 源代码以获取实例,O_NOATIME但没有得到任何点击。

如果您查看UnixChannelFactory 类,您会看到Flags 类,我认为它列出了所有支持的选项:

protected static class Flags {
    boolean read;
    boolean write;
    boolean append;
    boolean truncateExisting;
    boolean noFollowLinks;
    boolean create;
    boolean createNew;
    boolean deleteOnClose;
    boolean sync;
    boolean dsync;
    boolean direct;

    static Flags toFlags(Set<? extends OpenOption> options) {
        Flags flags = new Flags();
        for (OpenOption option: options) {
            if (option instanceof StandardOpenOption) {
                switch ((StandardOpenOption)option) {
                    case READ : flags.read = true; break;
                    case WRITE : flags.write = true; break;
                    case APPEND : flags.append = true; break;
                    case TRUNCATE_EXISTING : flags.truncateExisting = true; break;
                    case CREATE : flags.create = true; break;
                    case CREATE_NEW : flags.createNew = true; break;
                    case DELETE_ON_CLOSE : flags.deleteOnClose = true; break;
                    case SPARSE : /* ignore */ break;
                    case SYNC : flags.sync = true; break;
                    case DSYNC : flags.dsync = true; break;
                    default: throw new UnsupportedOperationException();
                }
                continue;
            }
            if (option == LinkOption.NOFOLLOW_LINKS && O_NOFOLLOW != 0) {
                flags.noFollowLinks = true;
                continue;
            }

            if (ExtendedOptions.DIRECT.matches(option)) {
                flags.direct = true;
                continue;
            }

            if (option == null)
                throw new NullPointerException();
           throw new UnsupportedOperationException(option + " not supported");
        }
        return flags;
    }
}

作为一种解决方法,您可以在访问文件后恢复上次访问时间:

// Create a file and write some content (empty files don't have their last access time updated after accessing - at least on Windows)
Path file = Files.createTempFile(null, null);
Files.write(file, Arrays.asList("line 1", "line 2"));

// Retrieve the last access time attribute before accessing the file    
FileTime lastAccessTimeBeforeAccessing = getLastAccessTime(file);

// Access the file
Files.readAllLines(file);

// Retrieve the last access time attribute after accessing the file 
FileTime lastAccessTimeAfterAccessing = getLastAccessTime(file);

// Revert the last access time
Files.setAttribute(file, "basic:lastAccessTime", lastAccessTimeBeforeAccessing);

// Retrieve the last access time attribute after reverting it   
FileTime lastAccessTimeAfterReverting = getLastAccessTime(file);

// at this point:
// * lastAccessTimeBeforeAccessing.equals(lastAccessTimeAfterAccessing) is false
// * lastAccessTimeBeforeAccessing.equals(lastAccessTimeAfterReverting) is true

getLastAccessTime功能是:

private static FileTime getLastAccessTime(Path file) throws IOException {
    BasicFileAttributes basicFileAttributes = Files.readAttributes(
        file, BasicFileAttributes.class);
    return basicFileAttributes.lastAccessTime();
}
于 2021-12-14T13:37:46.747 回答