我在资产文件夹里有几个文件。我需要把它们都复制到一个文件夹,比如/sdcard/folder。我想从一个线程中做这件事。我该怎么做?
当前回答
使用这个问题答案中的一些概念,我编写了一个名为assetcopyer的类来简化复制/assets/。它在github上可用,可以通过jitpack.io访问:
new AssetCopier(MainActivity.this)
.withFileScanning()
.copy("tocopy", destDir);
详情见https://github.com/flipagram/android-assetcopier。
其他回答
基于您的解决方案,我自己做了一些事情来允许子文件夹。有些人可能会觉得这很有用:
...
copyFileOrDir("myrootdir");
...
private void copyFileOrDir(String path) {
AssetManager assetManager = this.getAssets();
String assets[] = null;
try {
assets = assetManager.list(path);
if (assets.length == 0) {
copyFile(path);
} else {
String fullPath = "/data/data/" + this.getPackageName() + "/" + path;
File dir = new File(fullPath);
if (!dir.exists())
dir.mkdir();
for (int i = 0; i < assets.length; ++i) {
copyFileOrDir(path + "/" + assets[i]);
}
}
} catch (IOException ex) {
Log.e("tag", "I/O Exception", ex);
}
}
private void copyFile(String filename) {
AssetManager assetManager = this.getAssets();
InputStream in = null;
OutputStream out = null;
try {
in = assetManager.open(filename);
String newFileName = "/data/data/" + this.getPackageName() + "/" + filename;
out = new FileOutputStream(newFileName);
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
in.close();
in = null;
out.flush();
out.close();
out = null;
} catch (Exception e) {
Log.e("tag", e.getMessage());
}
}
对于正在更新到Kotlin的用户:
按照以下步骤避免FileUriExposedExceptions, 假设用户已授予WRITE_EXTERNAL_STORAGE权限,并且您的文件位于assets/pdfs/mypdf.pdf。
private fun openFile() {
var inputStream: InputStream? = null
var outputStream: OutputStream? = null
try {
val file = File("${activity.getExternalFilesDir(null)}/$PDF_FILE_NAME")
if (!file.exists()) {
inputStream = activity.assets.open("$PDF_ASSETS_PATH/$PDF_FILE_NAME")
outputStream = FileOutputStream(file)
copyFile(inputStream, outputStream)
}
val uri = FileProvider.getUriForFile(
activity,
"${BuildConfig.APPLICATION_ID}.provider.GenericFileProvider",
file
)
val intent = Intent(Intent.ACTION_VIEW).apply {
setDataAndType(uri, "application/pdf")
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY)
}
activity.startActivity(intent)
} catch (ex: IOException) {
ex.printStackTrace()
} catch (ex: ActivityNotFoundException) {
ex.printStackTrace()
} finally {
inputStream?.close()
outputStream?.flush()
outputStream?.close()
}
}
@Throws(IOException::class)
private fun copyFile(input: InputStream, output: OutputStream) {
val buffer = ByteArray(1024)
var read: Int = input.read(buffer)
while (read != -1) {
output.write(buffer, 0, read)
read = input.read(buffer)
}
}
companion object {
private const val PDF_ASSETS_PATH = "pdfs"
private const val PDF_FILE_NAME = "mypdf.pdf"
}
这在Kotlin中是一种简洁的方式。
fun AssetManager.copyRecursively(assetPath: String, targetFile: File) {
val list = list(assetPath)
if (list.isEmpty()) { // assetPath is file
open(assetPath).use { input ->
FileOutputStream(targetFile.absolutePath).use { output ->
input.copyTo(output)
output.flush()
}
}
} else { // assetPath is folder
targetFile.delete()
targetFile.mkdir()
list.forEach {
copyRecursively("$assetPath/$it", File(targetFile, it))
}
}
}
如果其他人也有同样的问题,我就是这么做的
private void copyAssets() {
AssetManager assetManager = getAssets();
String[] files = null;
try {
files = assetManager.list("");
} 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 outFile = new File(getExternalFilesDir(null), 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);
}
}
参考:使用Java移动文件
基于Rohith Nandakumar的解决方案,我自己做了一些事情,从资产的子文件夹中复制文件。“资产/ MyFolder”)。此外,在尝试再次复制之前,我正在检查文件是否已经存在于sdcard中。
private void copyAssets() {
AssetManager assetManager = getAssets();
String[] files = null;
try {
files = assetManager.list("MyFolder");
} 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("MyFolder/"+filename);
File outFile = new File(getExternalFilesDir(null), filename);
if (!(outFile.exists())) {// File does not exist...
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);
}
}
推荐文章
- BottomSheetDialogFragment的圆角
- 在应用程序启动时出现“无法获得BatchedBridge,请确保您的bundle被正确打包”的错误
- 我如何改变默认对话框按钮的文本颜色在安卓5
- 更改单选按钮的圆圈颜色
- 如何在android中复制一个文件?
- adb找不到我的设备/手机(MacOS X)
- 如何在新的材质主题中改变背面箭头的颜色?
- androidviewpager与底部点
- 相同的导航抽屉在不同的活动
- 如何从视图中获得托管活动?
- 单一的TextView与多种颜色的文本
- 如何在非活动类(LocationManager)中使用getSystemService ?
- 在清单中注册应用程序类?
- Android:从数组中编程创建旋转器
- Android命令行工具sdkmanager总是显示:警告:无法创建设置