You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

迁移至SAF后,如何替代C++ stat判断文件可写性?

解决方案

1. 在Java侧通过SAF查询文件可写性

SAF不依赖传统文件系统的rwx权限,需通过查询文档的COLUMN_FLAGS字段判断是否支持写入:

修改查询代码

在查询子文件时,新增DocumentsContract.Document.COLUMN_FLAGS字段到查询列中:

c = getContentResolver().query(childrenUri, new String[] {
        DocumentsContract.Document.COLUMN_DOCUMENT_ID,
        DocumentsContract.Document.COLUMN_DISPLAY_NAME,
        DocumentsContract.Document.COLUMN_MIME_TYPE,
        DocumentsContract.Document.COLUMN_FLAGS // 新增:获取文档权限标志
}, null, null, null);

判断文件可写性

在遍历Cursor时,解析COLUMN_FLAGS的值,通过FLAG_SUPPORTS_WRITE标识判断是否可写:

while (c.moveToNext()) {
    final String documentId = c.getString(0);
    final String documentName = c.getString(1);
    final int flags = c.getInt(3); // 对应新增的COLUMN_FLAGS字段
    final Uri documentUri = DocumentsContract.buildDocumentUriUsingTree(uri, documentId);

    // 判断是否支持写入
    boolean isWritable = (flags & DocumentsContract.Document.FLAG_SUPPORTS_WRITE) != 0;
    
    // 根据可写性选择打开模式,避免崩溃
    String openMode = isWritable ? "rw" : "r";
    try {
        ParcelFileDescriptor fd = getContentResolver().openFileDescriptor(documentUri, openMode);
        int nativeFD = fd.detachFd();
        // 将nativeFD和isWritable传递给C++侧
    } catch (IOException e) {
        e.printStackTrace();
    }

    folderContent.append(documentName + "\n");
}

2. C++侧可选的验证方式

如果需要在C++侧再次确认文件描述符的可写性,可通过fcntl获取文件状态标志判断:

#include <fcntl.h>
#include <unistd.h>

bool isFileWritable(int fd) {
    int statusFlags = fcntl(fd, F_GETFL);
    if (statusFlags == -1) {
        // 处理错误,比如perror("fcntl failed");
        return false;
    }
    // 检查是否为可写或读写模式
    return (statusFlags & O_WRONLY) != 0 || (statusFlags & O_RDWR) != 0;
}

关键说明

  • SAF的文档权限由文档提供者管理,传统stat获取的文件属性无法反映SAF层面的可写性,必须通过ContentResolver查询文档标志。
  • 打开文件时根据可写性选择对应模式,是避免openFileDescriptor调用崩溃的核心。

内容的提问来源于stack exchange,提问作者user1063364

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 18:03:21