英文:
Android FileNotFoundException with getAssets
问题
所以意图很简单,我想要将文件从APK的assets文件夹复制到设备存储中。我通过以下代码实现了这一点,而且实际上是有效的:
public void copyAssets() {
AssetManager assetManager = getAssets();
String[] files = null;
try {
files = getAssets().list("sourcedir");
} catch (IOException e) {
Log.e("tag", "无法获取资产文件列表。", e);
}
if (files != null) for (String filename : files) {
InputStream in = null;
OutputStream out = null;
try {
in = assetManager.open(filename);
File folder = new File(Environment.getExternalStorageDirectory() + File.separator + "TargetFol");
if (!folder.exists()) {
folder.mkdirs();
}
File outFile = new File(folder, filename);
out = new FileOutputStream(outFile);
copyFile(in, out);
} catch (IOException e) {
Log.e("tag", "无法复制资产文件:" + filename, e);
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
// NOOP
}
}
if (out != null) {
try {
out.close();
} catch (IOException e) {
// NOOP
}
}
}
}
}
private void copyFile(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
}
getAssets().list("sourcedir")
实际上列出了位于APK的assets文件夹中sourcedir
文件夹中的所有图像。
但是当调用该方法时,对于某些文件,它会抛出FileNotFoundException: myfile.png
的异常。例如,我在sourcedir
中放入了5个PNG文件(1.png、2.png、3.png、myfile.png、zip.png),所有文件都被复制,只有myfile.png
没有被复制。
我验证过没有不同的扩展名或其他任何差异,我也分析过APK,这5个图像实际上都存在于assets/sourcedir
中。
LOGCAT:
E/tag: 无法复制资产文件:myfile.png
java.io.FileNotFoundException: myfile.png
at android.content.res.AssetManager.nativeOpenAsset(Native Method)
at android.content.res.AssetManager.open(AssetManager.java:833)
at android.content.res.AssetManager.open(AssetManager.java:810)
at org.pac.pac.act.copyAssets(act.java:97)
at org.pac.pac.act$2.run(act.java:78)
at java.lang.Thread.run(Thread.java:919)
2020-10-04 21:06:13.189 30767-30999/packagename E/tag: 无法复制资产文件:myfile2.png
java.io.FileNotFoundException: myfile2.png
at android.content.res.AssetManager.nativeOpenAsset(Native Method)
at android.content.res.AssetManager.open(AssetManager.java:833)
at android.content.res.AssetManager.open(AssetManager.java:810)
at org.pac.pac.act.copyAssets(act.java:97)
at org.pac.pac.act$2.run(act.java:78)
我添加了另一个名为myfile2.png
的PNG文件,但是出现了相同的问题。
更新:
所以,我尝试将只有myfile.png
加入到inputstream
中,但即使该文件存在于assets/sourcedir
文件夹中,也会返回相同的异常。
<details>
<summary>英文:</summary>
So the intention is simple, I want to copy the files from the APK's assets folder to the device storage. I achieved that with the below code and it was actually working,
public void copyAssets() {
AssetManager assetManager = getAssets();
String[] files = null;
try {
files = getAssets().list("sourcedir");
} catch (IOException e) {
Log.e("tag", "Failed to get asset file list.", e);
}
if (files != null) for (String filename : files) {
InputStream in = null;
OutputStream out = null;
try {
in = assetManager.open(filename);
File folder = new File(Environment.getExternalStorageDirectory() + File.separator + "TargetFol");
if (!folder.exists()) {
folder.mkdirs();
}
File outFile = new File(folder, filename);
out = new FileOutputStream(outFile);
copyFile(in, out);
} catch (IOException e) {
Log.e("tag", "Failed to copy asset file: " + filename, e);
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
// NOOP
}
}
if (out != null) {
try {
out.close();
} catch (IOException e) {
// NOOP
}
}
}
}
}
private void copyFile(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
}
**getAssets().list("sourcedir") actually lists all the images in the sourcedir in the assets folder of the APK**.
But when the method called it throws `FileNotFoundException: myfile.png` for few files only.
For example, I put 5 png in the sourcedir (1.png, 2.png, 3.png, myfile.png, zip.png) All files copied except the myfile.png
I verified that there is no different extension or whatsoever also I had analyzed the APK and all these 5 images are actually there in assets/sourcedir
**LOGCAT:**
E/tag: Failed to copy asset file: myfile.png
java.io.FileNotFoundException: myfile.png
at android.content.res.AssetManager.nativeOpenAsset(Native Method)
at android.content.res.AssetManager.open(AssetManager.java:833)
at android.content.res.AssetManager.open(AssetManager.java:810)
at org.pac.pac.act.copyAssets(act.java:97)
at org.pac.pac.act$2.run(act.java:78)
at java.lang.Thread.run(Thread.java:919)
2020-10-04 21:06:13.189 30767-30999/packagename E/tag: Failed to copy asset file: myfile2.png
java.io.FileNotFoundException: myfile2.png
at android.content.res.AssetManager.nativeOpenAsset(Native Method)
at android.content.res.AssetManager.open(AssetManager.java:833)
at android.content.res.AssetManager.open(AssetManager.java:810)
at org.pac.pac.act.copyAssets(act.java:97)
at org.pac.pac.act$2.run(act.java:78)
I added another one PNG with the name of myfile2.png and gives the same issue.
**UPDATE:**
So instead of getting all files I tried to add myfile.png in the inputstream but this also returns the same exception even though the file was exists at the assets/sourcedir folder.
</details>
# 答案1
**得分**: 3
发现解决方案,可能也会帮助其他人。因此,如果你从资产目录的子文件夹中获取多个文件,请确保在调用时包含子文件夹名称。在我的情况下,是这样的:
in = assetManager.open(filename);
因此,将子文件夹名称与文件名一起添加到其中,问题就会得到解决。
in = assetManager.open("sourcedir/" + filename);
感谢 @CommonsWare 告诉我这个错误。有趣的是,我从一个在StackOverflow上得到了高投票并被接受为答案的问题中复制了这个方法,但没有人在评论中提到这个问题。是的,这是一个简单的错误,是我的错。
<details>
<summary>英文:</summary>
Found the solution, it may help others too. So if you're getting multiple files from the subfolder in the assets directory, make sure to include the subfolder name while calling. In my case it was,
in = assetManager.open(filename);
So adding the subfolder name along with the filename fixed the issue.
in = assetManager.open("sourcedir/" + filename);
Thanks to @CommonsWare who let me know this mistake. Fun fact I copied this method from one StackOverflow's question with high upvotes and accepted as an answer but nobody mentioned this issue in the comment. Yeah, it's a simple mistake, my bad.
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论