在我的应用程序中,用户选择文件。在内部,我存储关于文件的信息,我根据文件路径键入这些信息。下次使用该文件时,我会使用存储的信息。问题是我用以下命令实例化我的文件:
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"
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();
发布于 2013-04-09 05:35:34
首先,获取外部路径的唯一正确方法是在安卓中使用getExternalStorageDirectory
和其他getExternalStorageXXX
。
Android将首先尝试解析两个系统变量:
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中:
export EXTERNAL_STORAGE /mnt/sdcard
mkdir /mnt/sdcard 0000 system system
symlink /mnt/sdcard /sdcard
如果使用getExternalStorageDirectory
,您将获得/mnt/sdcard
,但/sdcard
是指向该目录的符号链接。
因此,在您的示例中,init.rc可能包含:
export EMULATED_STORAGE_TARGET /storage/emulated
symlink /storage/emulated/0 /mnt/sdcard
所以它们不是模棱两可的,它们实际上是一样的。
我认为getCanonicalPath()可能适用于您的绝大多数用例。
规范路径名既是绝对的,也是唯一的。规范形式的精确定义依赖于系统。此方法首先在必要时将此路径名转换为绝对形式,就像通过调用getAbsolutePath()方法一样,然后以依赖于系统的方式将其映射为其唯一形式。这通常涉及删除多余的名称,如“”。和"..“从路径名解析符号链接(在UNIX平台上),并将驱动器号转换为标准大小写(在Microsoft Windows平台上)。
表示现有文件或目录的每个路径名都有唯一的规范形式。表示不存在的文件或目录的每个路径名也具有唯一的规范形式。在创建文件或目录之后,不存在的文件或目录的路径名的规范形式可以不同于相同路径名的规范形式。同样,现有文件或目录的路径名的规范格式可能与删除文件或目录后相同路径名的规范格式不同。
发布于 2013-04-15 10:32:28
对于这个问题,可能没有简单的解决方案。问题在于,显然文件系统中有两个不同的挂载点,它们实际上指向相同的位置。File.getCanonicalPath()只能解析符号链接,不能解析不同的挂载点。
例如,在我的Nexus 4上,这段代码如下:
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());
打印
file 1: /storage/emulated/0/Android
file 2: /storage/emulated/legacy/Android
我使用以下代码执行"mount“并打印输出:
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();
相关输出为:
/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
发布于 2013-04-14 04:12:42
看一下答案here。它还使用规范路径,但使用的方式略有不同,可能适合您
https://stackoverflow.com/questions/15841380
复制相似问题