首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >Android:消除文件路径的歧义

Android:消除文件路径的歧义
EN

Stack Overflow用户
提问于 2013-04-05 18:53:17
回答 4查看 4.3K关注 0票数 10

在我的应用程序中,用户选择文件。在内部,我存储关于文件的信息,我根据文件路径键入这些信息。下次使用该文件时,我会使用存储的信息。问题是我用以下命令实例化我的文件:

File file1 = new File(Environment.getExternalStorageDirectory() + "/test.txt");

然后,在一个特定的JB设备上,file1.getCanonicalPath()给出了:"/storage/emulated/0/test.txt“。

问题是,当其他应用程序使用Intent中的文件路径启动我的应用程序时,它们发送的路径往往类似于:"/mnt/sdcard/test.txt“。

有没有一个聪明的策略来消除这两条路径的歧义?也许我应该以不同的方式实例化我的文件?

编辑:

问题是,这两个文件的两个规范路径并不相等。对于下面的示例,cp1=="mnt/sdcard/test/txt"cp2=="/storage/emulated/0/text/txt"

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
File file1 = new File("/mnt/sdcard/test.txt");
File file2 = new File("/storage/emulated/0/test.txt");

String cp1 = file1.getCanonicalPath();
String cp2 = file2.getCanonicalPath();
EN

回答 4

Stack Overflow用户

发布于 2013-04-09 05:35:34

首先,获取外部路径的唯一正确方法是在安卓中使用getExternalStorageDirectory和其他getExternalStorageXXX

Android将首先尝试解析两个系统变量:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
String rawExternalStorage = System.getenv(ENV_EXTERNAL_STORAGE);
String rawEmulatedStorageTarget = System.getenv(ENV_EMULATED_STORAGE_TARGET);

ENV_EXTERNAL_STORAGE = "EXTERNAL_STORAGE"ENV_EMULATED_STORAGE_TARGET = "EMULATED_STORAGE_TARGET"。如果设置了EMULATED_STORAGE_TARGET变量,则意味着设备具有模拟存储,则存储路径将为EMULATED_STORAGE_TARGET。(在Android4.2之后,它支持多用户外部存储,则路径后面将有/0或0)。但如果未设置该变量,并且设置了EXTERNAL_STORAGE,则路径将为EXTERNAL_STORAGE。如果两者都没有设置,则默认路径为/storage/sdcard0。因此,不同的设备可能包含不同的外部存储路径。

正如External Storage Technical Information所说,您可以通过设置init.rc文件来自定义设备的存储。例如,在默认的金鱼one中:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
export EXTERNAL_STORAGE /mnt/sdcard
mkdir /mnt/sdcard 0000 system system
symlink /mnt/sdcard /sdcard

如果使用getExternalStorageDirectory,您将获得/mnt/sdcard,但/sdcard是指向该目录的符号链接。

因此,在您的示例中,init.rc可能包含:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
export EMULATED_STORAGE_TARGET /storage/emulated
symlink /storage/emulated/0 /mnt/sdcard

所以它们不是模棱两可的,它们实际上是一样的。

我认为getCanonicalPath()可能适用于您的绝大多数用例。

规范路径名既是绝对的,也是唯一的。规范形式的精确定义依赖于系统。此方法首先在必要时将此路径名转换为绝对形式,就像通过调用getAbsolutePath()方法一样,然后以依赖于系统的方式将其映射为其唯一形式。这通常涉及删除多余的名称,如“”。和"..“从路径名解析符号链接(在UNIX平台上),并将驱动器号转换为标准大小写(在Microsoft Windows平台上)。

表示现有文件或目录的每个路径名都有唯一的规范形式。表示不存在的文件或目录的每个路径名也具有唯一的规范形式。在创建文件或目录之后,不存在的文件或目录的路径名的规范形式可以不同于相同路径名的规范形式。同样,现有文件或目录的路径名的规范格式可能与删除文件或目录后相同路径名的规范格式不同。

票数 5
EN

Stack Overflow用户

发布于 2013-04-15 10:32:28

对于这个问题,可能没有简单的解决方案。问题在于,显然文件系统中有两个不同的挂载点,它们实际上指向相同的位置。File.getCanonicalPath()只能解析符号链接,不能解析不同的挂载点。

例如,在我的Nexus 4上,这段代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
File file1 = new File(Environment.getExternalStorageDirectory() + "/Android");
System.out.println("file 1: " + file1.getCanonicalPath());
File file2 = new File("/sdcard/Android");
System.out.println("file 2: " + file2.getCanonicalPath());

打印

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
file 1: /storage/emulated/0/Android
file 2: /storage/emulated/legacy/Android

我使用以下代码执行"mount“并打印输出:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Process exec = Runtime.getRuntime().exec("mount");
InputStream in = exec.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
while (true) {
    String line = br.readLine();
    if (line == null)
        break;
    System.out.println(line);
}
in.close();

相关输出为:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/dev/fuse /storage/emulated/0 fuse rw,nosuid,nodev,relatime,user_id=1023,group_id=1023,default_permissions,allow_other 0 0
/dev/fuse /storage/emulated/legacy fuse rw,nosuid,nodev,relatime,user_id=1023,group_id=1023,default_permissions,allow_other 0 0
票数 2
EN

Stack Overflow用户

发布于 2013-04-14 04:12:42

看一下答案here。它还使用规范路径,但使用的方式略有不同,可能适合您

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15841380

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文