我在资产文件夹里有几个文件。我需要把它们都复制到一个文件夹,比如/sdcard/folder。我想从一个线程中做这件事。我该怎么做?
当前回答
基于您的解决方案,我自己做了一些事情来允许子文件夹。有些人可能会觉得这很有用:
...
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"
}
使用这个问题答案中的一些概念,我编写了一个名为assetcopyer的类来简化复制/assets/。它在github上可用,可以通过jitpack.io访问:
new AssetCopier(MainActivity.this)
.withFileScanning()
.copy("tocopy", destDir);
详情见https://github.com/flipagram/android-assetcopier。
使用AssetManager,它允许读取资产中的文件。然后使用常规的Java IO将文件写入sdcard。
谷歌是你的朋友,搜索一个例子。
基于您的解决方案,我自己做了一些事情来允许子文件夹。有些人可能会觉得这很有用:
...
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());
}
}
import android.app.Activity;
import android.content.Intent;
import android.content.res.AssetManager;
import android.net.Uri;
import android.os.Environment;
import android.os.Bundle;
import android.util.Log;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
copyReadAssets();
}
private void copyReadAssets()
{
AssetManager assetManager = getAssets();
InputStream in = null;
OutputStream out = null;
String strDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)+ File.separator + "Pdfs";
File fileDir = new File(strDir);
fileDir.mkdirs(); // crear la ruta si no existe
File file = new File(fileDir, "example2.pdf");
try
{
in = assetManager.open("example.pdf"); //leer el archivo de assets
out = new BufferedOutputStream(new FileOutputStream(file)); //crear el archivo
copyFile(in, out);
in.close();
in = null;
out.flush();
out.close();
out = null;
} catch (Exception e)
{
Log.e("tag", e.getMessage());
}
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.parse("file://" + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + File.separator + "Pdfs" + "/example2.pdf"), "application/pdf");
startActivity(intent);
}
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);
}
}
}
修改部分代码,如下所示:
out = new BufferedOutputStream(new FileOutputStream(file));
前面的例子是针对pdf文件的,如果是。txt
FileOutputStream fos = new FileOutputStream(file);
推荐文章
- 这是在Android中获取用户位置的好方法
- Android从左到右幻灯片动画
- 如何检索视图的维度?
- 如何改变菜单项的文本颜色在安卓?
- Android选择器和文本颜色
- 视图绑定-我如何获得包含布局的绑定?
- 在Android Studio中改变矢量资产的填充颜色
- 在构建中编写注释的语法是什么?gradle文件?
- 如何以编程方式添加按钮色调
- 用Android Studio进行调试永远停留在“等待调试器”状态
- Openssl不被视为内部或外部命令
- 无法执行dex:在Eclipse中超过GC开销限制
- 如何以编程方式将视图添加到视图
- 单击url会打开默认浏览器
- 使用Retrofit刷新OAuth令牌,而不修改所有调用