Android 获取U盘的卷标(支持中文卷标)

1: 盘符 和 卷标的区别
之前被这个概念迷惑了很久, 走了不少弯路。
盘符 - window下的概念。 例如 C: 盘 D: 盘, C和D 这是就是盘符。 Linux下无对应的概念。
卷标 - 例如 C 盘如果命名为系统, D盘命名为电影, 系统和电影 这才是卷标。 Linux下也有这东西, 这个属于文件系统的部分。

2: Android 下如何获取卷标
StorageVolume.java 中的 public String getUserLabel() 获取。

3: Android现在支持的情况
如果这么简单获取那就方便了, 首先  StorageVolume.java 这个类是不公开的, 获取方法可以通过反射。
其次  public String getUserLabel()  这个方法, 底层和上层根本就没调通(Android4.4的原生代码部分, 我看是调试通过了)。

1: Vold 接收到 U 盘插入事件。
执行 Volume.cpp 的 int Volume::mountVol() 方法 这里调用  int Volume::extractMetadata(const char* devicePath)方法
/*
 * Use blkid to extract UUID and label from device, since it handles many
 * obscure edge cases around partition types and formats. Always broadcasts
 * updated metadata values.
 */
int Volume::extractMetadata(const char* devicePath) {
    int res = 0;

    std::string cmd;
    cmd = BLKID_PATH;
    cmd += " -c /dev/null ";
    cmd += devicePath;

    FILE* fp = popen(cmd.c_str(), "r");
    if (!fp) {
        SLOGI("Failed to run %s: %s", cmd.c_str(), strerror(errno));
        res = -1;
        goto done;
    }

    char line[1024];
    char value[128];
    if (fgets(line, sizeof(line), fp) != NULL) {
        SLOGI("blkid identified as %s", line);

        char* start = strstr(line, "UUID=");
        if (start != NULL && sscanf(start + 5, "\"%127[^\"]\"", value) == 1) {
            setUuid(value);
        } else {
            setUuid(NULL);
        }

        start = strstr(line, "LABEL=");
        if (start != NULL && sscanf(start + 6, "\"%127[^\"]\"", value) == 1) {
            setUserLabel(value);
        } else {
            setUserLabel(NULL);
        }
    } else {
        SLOGI("blkid failed to identify %s", devicePath);
        res = -1;
    }

    pclose(fp);

done:
    if (res == -1) {
        setUuid(NULL);
        setUserLabel(NULL);
    }
    return res;
}



通过代码就可以 U盘的基本信息 UUID 和 LABEL 都是通过 blkid 获取的。

4: blkid 分析
通过 static void print_tags(blkid_dev dev, char *show[], int numtag, int output) 把相关的信息进行输出。

5: blkid如何支持中文
这个就涉及到字符集相关的问题了, 说一个迷惑了我很久的字符集问题。
字符集包括unicode, gbk 以及gb2312等等,  但是utf-8, 这个东西不是字符集。这个是字符编码。
举个例子就明白啥叫字符编码了。
C中的字符串(char*)问题, 我们认为一个字符串的长度是, 读取到ASCII 0(‘/0’)的位置位置。
假设字符串 "A" 的GBK和UTF8编码都是 0x410 x00, 为啥后面多了个0x00, 这个就是字符串的结束位置。
字符A的 Unicode编码是 0x00 0x41, 如果用char*传递unicode字符串, 不知道字符串大小, 肯定是有问题的。 读到第一个0x00就结束了。
还不明白可以百度了。

对于vfat,fat32格式的U盘, 在windows下命名中文, 保存的字符编码是CP936(跟GBK差不多), 但是对于ntfs格式的u盘, 保存的方式是unicode。
这里涉及到android(linux)的编码问题, linux的默认编码是utf-8. 所以如果要正常显示, 需要在linux中合适的位置坐转码。

思路:
(只涉及中文, 韩文日文不考虑)在blkid这里把, 把编码直接从gbk转到utf8. (/external/e2fsprogs/misc/blkid.c)
特殊的ntfs获取卷标的地方, 为了上层的gbk编码兼容, 可以直接把unicode先转成gbk。(/external/e2fsprogs/lib/blkid/probe.c)

至于编码之间的转换可以参考网上的代码, 也可以使用开源的库iconv. 个人认为可以代码量比较小, 可以考虑网上的参考代码。
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
在C语言中,要获取磁盘卷标名称,可以使用以下步骤: 1. 首先,需要包含Windows.h头文件,这个头文件中定义了一些用于Windows系统编程的函数和数据结构。 2. 使用GetVolumeInformation函数来获取磁盘卷标名称。该函数的原型如下: BOOL GetVolumeInformationA( LPCSTR lpRootPathName, LPSTR lpVolumeNameBuffer, DWORD nVolumeNameSize, LPDWORD lpVolumeSerialNumber, LPDWORD lpMaximumComponentLength, LPDWORD lpFileSystemFlags, LPSTR lpFileSystemNameBuffer, DWORD nFileSystemNameSize ); 其中,lpRootPathName是一个指向包含卷标的根路径的字符串,比如"C:\";lpVolumeNameBuffer是用来存放卷标名称的缓冲区;nVolumeNameSize是缓冲区大小;其他的参数可以传入NULL。 3. 创建一个字符数组,用来存储卷标名称。 4. 调用GetVolumeInformation函数,并传入磁盘根路径和字符数组作为参数。 5. 如果函数返回TRUE,表示获取卷标名称成功,可以通过打印字符数组的值来查看卷标名称。 以下是一个示例代码: ```c #include <Windows.h> #include <stdio.h> int main() { char volumeName[MAX_PATH]; char rootPath[] = "C:\\"; if (GetVolumeInformationA(rootPath, volumeName, sizeof(volumeName), NULL, NULL, NULL, NULL, 0)) { printf("磁盘卷标名称: %s\n", volumeName); } else { printf("无法获取磁盘卷标名称\n"); } return 0; } ``` 以上是用C语言获取磁盘卷标名称的方法。注意,在Windows系统上,不是所有的磁盘都会有卷标名称,所以有可能获取到的名称为空。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值