Android Studio 在run时报的异常 Failed to run command file not found FileNotFoundException

解决Android Studio中文路径异常
本文介绍了解决Android Studio在中文路径下运行项目时出现FileNotFoundException的方法。通过更改项目路径为英文,成功避免了该异常。

Android Studio 在run时报的异常 Failed to run command file not found FileNotFoundException

在github上下载项目,导入后 有时不注意,在build完后,run时会报现个FileNotFoundException,会提示如下的错误:


Error:Execution failed for task ‘:sample:dexDebug’.
com.android.ide.common.internal.LoggedErrorException: Failed to run command:
D:\Program Files\Android\sdk\build-tools\21.1.2\dx.bat –dex –no-optimize –output D:\需要的文档\学习资料\xxx\sample\build\intermediates\dex\debug –input-list=D:\需要的文档\学习资料\xxx\sample\build\intermediates\tmp\dex\debug\inputList.txt
Error Code:
1
Output:
UNEXPECTED TOP-LEVEL EXCEPTION:
java.lang.RuntimeException: D:\闇?瑕佺殑鏂囨。\瀛︿範璧勬枡\js涓巜eb瀹夊叏浜や簰\xxx\sample\build\intermediates\classes\debug: file not found
at com.android.dex.util.FileUtils.readFile(FileUtils.java:51)
at com.android.dx.cf.direct.ClassPathOpener.processOne(ClassPathOpener.java:169)
at com.android.dx.cf.direct.ClassPathOpener.process(ClassPathOpener.java:144)
at com.android.dx.command.dexer.Main.processOne(Main.java:632)
at com.android.dx.command.dexer.Main.processAllFiles(Main.java:510)
at com.android.dx.command.dexer.Main.runMonoDex(Main.java:280)
at com.android.dx.command.dexer.Main.run(Main.java:246)
at com.android.dx.command.dexer.Main.main(Main.java:215)
at com.android.dx.command.Main.main(Main.java:106)
UNEXPECTED TOP-LEVEL EXCEPTION:
java.io.FileNotFoundException: D:\闇?瑕佺殑鏂囨。\瀛︿範璧勬枡\js涓巜eb瀹夊叏浜や簰\xxx\sample\build\intermediates\pre-dexed\debug\classes-6bafb5ea8fc86808334b6373daacdc92babdec8a.jar (系统找不到指定的路径。)
at java.util.zip.ZipFile.open(Native Method)
at java.util.zip.ZipFile.(ZipFile.java:220)
at java.util.zip.ZipFile.(ZipFile.java:150)
at java.util.zip.ZipFile.(ZipFile.java:164)
at com.android.dx.cf.direct.ClassPathOpener.processArchive(ClassPathOpener.java:244)
at com.android.dx.cf.direct.ClassPathOpener.processOne(ClassPathOpener.java:166)
at com.android.dx.cf.direct.ClassPathOpener.process(ClassPathOpener.java:144)
at com.android.dx.command.dexer.Main.processOne(Main.java:632)
at com.android.dx.command.dexer.Main.processAllFiles(Main.java:510)
at com.android.dx.command.dexer.Main.runMonoDex(Main.java:280)
at com.android.dx.command.dexer.Main.run(Main.java:246)
at com.android.dx.command.dexer.Main.main(Main.java:215)
at com.android.dx.command.Main.main(Main.java:106)
UNEXPECTED TOP-LEVEL EXCEPTION:
java.io.FileNotFoundException: D:\闇?瑕佺殑鏂囨。\瀛︿範璧勬枡\js涓巜eb瀹夊叏浜や簰\xxx\sample\build\intermediates\pre-dexed\debug\gson-2.3-317f284ee257b9e36af74bb2d07d373f5b8009da.jar (系统找不到指定的路径。)
at java.util.zip.ZipFile.open(Native Method)
at java.util.zip.ZipFile.(ZipFile.java:220)
at java.util.zip.ZipFile.(ZipFile.java:150)
at java.util.zip.ZipFile.(ZipFile.java:164)
at com.android.dx.cf.direct.ClassPathOpener.processArchive(ClassPathOpener.java:244)
at com.android.dx.cf.direct.ClassPathOpener.processOne(ClassPathOpener.java:166)
at com.android.dx.cf.direct.ClassPathOpener.process(ClassPathOpener.java:144)
at com.android.dx.command.dexer.Main.processOne(Main.java:632)
at com.android.dx.command.dexer.Main.processAllFiles(Main.java:510)
at com.android.dx.command.dexer.Main.runMonoDex(Main.java:280)
at com.android.dx.command.dexer.Main.run(Main.java:246)
at com.android.dx.command.dexer.Main.main(Main.java:215)
at com.android.dx.command.Main.main(Main.java:106)
3 errors; aborting


上面在run时报的异常 Failed to run command file not found,文件居然找不到(FileNotFoundException),,找不到啊。。。
而路径中有乱码了,应该可能是中文乱码的问题。
将project 空间路径转成 英文的,果然发现OK。。


结论:在Android studio中project 工作空间路径不要含有中文,否则很容易会报FileNotFoundException. 这点eclipse是支持中文的。

<think>我们遇到了一个FileNotFoundException,提示"Prefs file not found"。这通常意味着在尝试打开或读取指定的SharedPreferences文件时,该文件不存在于设备上。 ### 原因分析: 1. **首次使用应用**:如果用户是第一次启动应用,或者从未修改过该偏好设置,对应的SharedPreferences文件可能尚未创建。 2. **文件路径错误**:可能使用了错误的路径或文件名来访问文件。 3. **文件被删除**:文件可能被用户、其他应用或系统清理工具删除。 4. **权限问题**:没有足够的权限访问该文件(尽管在应用私有目录下通常不会有此问题)。 ### 解决方案: 我们需要在文件不存在时创建一个新的SharedPreferences文件。以下是完整的处理流程: #### 步骤1:获取SharedPreferences文件路径 ```java File prefsDir = new File(context.getApplicationInfo().dataDir, "shared_prefs"); File prefsFile = new File(prefsDir, "YourPrefsFileName.xml"); ``` #### 步骤2:确保目录存在 ```java if (!prefsDir.exists()) { prefsDir.mkdirs(); } ``` #### 步骤3:处理文件不存在的场景 ```java if (!prefsFile.exists()) { // 创建空的SharedPreferences文件 SharedPreferences initialPrefs = context.getSharedPreferences("YourPrefsFileName", Context.MODE_PRIVATE); initialPrefs.edit().commit(); // 提交空编辑以创建文件 } ``` ### 完整代码示例: ```java public static void modifyPrefsFile(Context context, String targetKey, String newValue) { final String PREFS_NAME = "YourPrefsFileName"; // 无.xml后缀 final String PREFS_FILE = PREFS_NAME + ".xml"; // 1. 获取SharedPreferences文件路径 File prefsDir = new File(context.getApplicationInfo().dataDir, "shared_prefs"); File prefsFile = new File(prefsDir, PREFS_FILE); // 2. 确保目录存在 if (!prefsDir.exists()) { prefsDir.mkdirs(); } // 3. 如果文件不存在,则创建 if (!prefsFile.exists()) { SharedPreferences initialPrefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE); initialPrefs.edit().commit(); // 创建空文件 } // 4. 解析并修改XML try { XmlPullParser parser = Xml.newPullParser(); FileInputStream fis = new FileInputStream(prefsFile); parser.setInput(fis, "UTF-8"); String modifiedXml = modifyXmlValue(parser, targetKey, newValue); fis.close(); // 5. 写回修改后的内容 FileOutputStream fos = new FileOutputStream(prefsFile); fos.write(modifiedXml.getBytes("UTF-8")); fos.close(); } catch (Exception e) { e.printStackTrace(); } } ``` ### 关键点说明: 1. **文件创建**:通过提交一个空的`SharedPreferences.Editor`来初始化文件。 2. **文件路径**: - 应用私有目录:`/data/data/<package_name>/shared_prefs/` - 使用`context.getApplicationInfo().dataDir`获取基础路径 3. **安全写入**:使用`FileOutputStream`写入时,确保使用与原始文件相同的编码(UTF-8)。 ### 错误处理增强: 考虑添加以下保护措施: ```java // 在文件操作时添加异常捕获 try (FileInputStream fis = new FileInputStream(prefsFile); FileOutputStream fos = new FileOutputStream(prefsFile)) { // 处理流程 } catch (FileNotFoundException e) { // 再次检查文件是否存在 if (!prefsFile.exists()) { // 尝试重新创建 SharedPreferences initialPrefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE); initialPrefs.edit().commit(); } } catch (IOException e) { e.printStackTrace(); } ``` ### 注意事项: 1. **并发访问**:在读写SharedPreferences文件时,确保没有其他线程同时操作。 2. **备份**:修改前备份原始文件,以防修改失败导致数据丢失。 3. **性能**:对于大型文件,考虑使用临时文件过渡。 §§相关问题§§: 1. 如何在不使用SharedPreferences API的情况下直接创建SharedPreferences XML文件? 2. 在Android中,如何监听SharedPreferences文件的变更? 3. 直接修改SharedPreferences文件与使用SharedPreferences API修改有何优缺点? 4. 如何确保在修改SharedPreferences文件时不会导致应用崩溃或数据损坏?</think>### 解决 `FileNotFoundException: Prefs file not found` 错误 #### 错误原因分析: 1. **首次运行应用**: - SharedPreferences 文件在首次调用 `commit()` 或 `apply()` 前不会创建 - 如果从未修改过偏好设置,文件可能不存在 2. **文件路径错误**: - 使用了错误的包名或文件名 - 未正确获取应用私有目录路径 3. **权限问题**: - 在 Android 10+ 上未正确处理分区存储 - 缺少文件系统访问权限 4. **文件被删除**: - 用户清除应用数据 - 系统自动清理缓存 #### 完整解决方案代码: ```java public static void safeModifyPrefs(Context context, String targetKey, String newValue) { final String PREFS_NAME = "com.example.app_preferences"; // 无.xml后缀 final String PREFS_FILE = PREFS_NAME + ".xml"; // 1. 获取正确的文件路径 File prefsDir = new File(context.getApplicationInfo().dataDir, "shared_prefs"); File prefsFile = new File(prefsDir, PREFS_FILE); // 2. 确保文件存在 if (!prefsFile.exists()) { createDefaultPrefsFile(context, PREFS_NAME); } // 3. 处理文件修改 try (FileInputStream fis = new FileInputStream(prefsFile)) { XmlPullParser parser = Xml.newPullParser(); parser.setInput(fis, "UTF-8"); String modifiedXml = modifyXmlValue(parser, targetKey, newValue); // 4. 安全写入修改 try (FileOutputStream fos = new FileOutputStream(prefsFile)) { fos.write(modifiedXml.getBytes("UTF-8")); } } catch (Exception e) { Log.e("PrefsUtils", "Error modifying prefs", e); // 5. 回退方案:使用 SharedPreferences API fallbackToPrefsApi(context, PREFS_NAME, targetKey, newValue); } } // 创建默认的 SharedPreferences 文件 private static void createDefaultPrefsFile(Context context, String prefsName) { SharedPreferences prefs = context.getSharedPreferences(prefsName, Context.MODE_PRIVATE); prefs.edit().putBoolean("__initialized__", true).apply(); } // 回退到标准 API 修改 private static void fallbackToPrefsApi(Context context, String prefsName, String key, String value) { SharedPreferences prefs = context.getSharedPreferences(prefsName, Context.MODE_PRIVATE); prefs.edit().putString(key, value).apply(); } // XML 修改方法(简略版) private static String modifyXmlValue(XmlPullParser parser, String targetKey, String newValue) throws Exception { // ... 之前的实现 ... } ``` ### 关键解决方案说明: 1. **文件路径验证**: ```java // 正确获取应用私有目录 File prefsDir = new File(context.getApplicationInfo().dataDir, "shared_prefs"); ``` - 使用 `context.getApplicationInfo().dataDir` 确保获取应用私有目录 - Android 11+ 需要此方式访问受限目录 2. **文件创建机制**: ```java if (!prefsFile.exists()) { createDefaultPrefsFile(context, PREFS_NAME); } ``` - 通过提交一个空编辑创建文件 - 添加虚拟键值确保文件被实际创建 3. **安全资源管理**: ```java try (FileInputStream fis = new FileInputStream(prefsFile)) { // 使用 try-with-resources 自动关闭流 } ``` - 防止文件描述符泄漏 - 确保异常时资源正确释放 4. **回退机制**: ```java private static void fallbackToPrefsApi(...) { prefs.edit().putString(key, value).apply(); } ``` - 当直接文件操作失败时使用标准 API - 保证功能在异常情况下仍可用 ### Android 版本适配要点: 1. **Android 10+ (API 29+)**: - 在 `AndroidManifest.xml` 中添加: ```xml <application android:requestLegacyExternalStorage="true" ...> ``` - 使用 `Context#getDataDir()` 代替环境变量 2. **Android 11+ (API 30+)**: - 添加文件访问权限: ```xml <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" /> ``` - 处理分区存储限制 3. **所有版本通用**: ```java // 检查文件是否存在 if (!prefsFile.exists()) { // 创建文件而不是抛出异常 } ``` ### 最佳实践建议: 1. **文件操作前检查**: ```java if (prefsFile.exists() && prefsFile.length() > 0) { // 修改文件 } else { // 使用 SharedPreferences API } ``` 2. **备份恢复机制**: ```java // 修改前创建备份 File backupFile = new File(prefsDir, "backup_" + PREFS_FILE); Files.copy(prefsFile.toPath(), backupFile.toPath()); // 出错时恢复备份 if (errorOccurred) { Files.copy(backupFile.toPath(), prefsFile.toPath()); } ``` 3. **日志监控**: ```java // 记录文件状态 Log.d("PrefsFile", "Path: " + prefsFile.getAbsolutePath()); Log.d("PrefsFile", "Exists: " + prefsFile.exists()); Log.d("PrefsFile", "Size: " + prefsFile.length()); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值