Assets中APK写入MODE_PRIVATE后读取报FileNotFoundException问题排查
嘿,我一眼就瞅出你代码里的两个关键问题,这就帮你解决:
问题1:读写的文件名不匹配
你在writeFilePrivate里写入的是tmp.apk:
fos = openFileOutput("tmp.apk", Context.MODE_PRIVATE);
但在readFileFromPrivate里却试图读取test.apk:
fis = openFileInput("test.apk");
这就好比你把文件放到了叫“tmp”的抽屉里,却去翻“test”抽屉找,肯定找不到啊!得把文件名统一,要么都叫test.apk,要么都叫tmp.apk。
问题2:读取函数的逻辑完全错误
你的readFileFromPrivate函数犯了一个典型的误解:把APK的二进制内容读成字符串,然后用这个字符串创建File对象。APK是二进制文件,里面的内容是编译后的字节码、资源等,根本不是文件路径字符串!这样创建出来的File对象完全指向一个不存在的路径,自然会报错。
修正后的代码示例
先修正写入函数(统一文件名+优化流关闭)
private void writeFilePrivate() { AssetManager assetManager = getAssets(); InputStream in = null; FileOutputStream fos = null; try { in = assetManager.open("test.apk"); // 统一文件名为test.apk,和读取时对应 fos = openFileOutput("test.apk", Context.MODE_PRIVATE); byte[] buffer = new byte[1024]; int read; while ((read = in.read(buffer)) != -1) { fos.write(buffer, 0, read); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { // 用finally确保流一定会关闭,避免资源泄漏 try { if (in != null) in.close(); if (fos != null) { fos.flush(); fos.close(); } } catch (IOException e) { e.printStackTrace(); } } }
如果你只是想获取私有目录里的APK文件对象
private File getPrivateApkFile() { // getFilesDir()就是Context.MODE_PRIVATE对应的内部存储目录 return new File(getFilesDir(), "test.apk"); }
如果你需要读取APK的二进制内容
private byte[] readPrivateApkContent() { FileInputStream fis = null; ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { fis = openFileInput("test.apk"); byte[] buffer = new byte[1024]; int read; while ((read = fis.read(buffer)) != -1) { baos.write(buffer, 0, read); } return baos.toByteArray(); } catch (FileNotFoundException e) { e.printStackTrace(); return null; } catch (IOException e) { e.printStackTrace(); return null; } finally { try { if (fis != null) fis.close(); baos.close(); } catch (IOException e) { e.printStackTrace(); } } }
额外提醒
记得在调用读取相关方法之前,一定要先调用writeFilePrivate()完成文件复制,不然文件还没存在,肯定也会报找不到的错误哦!
内容的提问来源于stack exchange,提问作者BekaKK
相关产品推荐
相关产品推荐

