我在资产文件夹里有几个文件。我需要把它们都复制到一个文件夹,比如/sdcard/folder。我想从一个线程中做这件事。我该怎么做?
当前回答
嗨,伙计们,我做了这样的事情。 用于n深度复制文件夹和文件复制。 它允许你复制所有的目录结构从Android资产管理器复制:)
private void manageAssetFolderToSDcard()
{
try
{
String arg_assetDir = getApplicationContext().getPackageName();
String arg_destinationDir = FRConstants.ANDROID_DATA + arg_assetDir;
File FolderInCache = new File(arg_destinationDir);
if (!FolderInCache.exists())
{
copyDirorfileFromAssetManager(arg_assetDir, arg_destinationDir);
}
} catch (IOException e1)
{
e1.printStackTrace();
}
}
public String copyDirorfileFromAssetManager(String arg_assetDir, String arg_destinationDir) throws IOException
{
File sd_path = Environment.getExternalStorageDirectory();
String dest_dir_path = sd_path + addLeadingSlash(arg_destinationDir);
File dest_dir = new File(dest_dir_path);
createDir(dest_dir);
AssetManager asset_manager = getApplicationContext().getAssets();
String[] files = asset_manager.list(arg_assetDir);
for (int i = 0; i < files.length; i++)
{
String abs_asset_file_path = addTrailingSlash(arg_assetDir) + files[i];
String sub_files[] = asset_manager.list(abs_asset_file_path);
if (sub_files.length == 0)
{
// It is a file
String dest_file_path = addTrailingSlash(dest_dir_path) + files[i];
copyAssetFile(abs_asset_file_path, dest_file_path);
} else
{
// It is a sub directory
copyDirorfileFromAssetManager(abs_asset_file_path, addTrailingSlash(arg_destinationDir) + files[i]);
}
}
return dest_dir_path;
}
public void copyAssetFile(String assetFilePath, String destinationFilePath) throws IOException
{
InputStream in = getApplicationContext().getAssets().open(assetFilePath);
OutputStream out = new FileOutputStream(destinationFilePath);
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0)
out.write(buf, 0, len);
in.close();
out.close();
}
public String addTrailingSlash(String path)
{
if (path.charAt(path.length() - 1) != '/')
{
path += "/";
}
return path;
}
public String addLeadingSlash(String path)
{
if (path.charAt(0) != '/')
{
path = "/" + path;
}
return path;
}
public void createDir(File dir) throws IOException
{
if (dir.exists())
{
if (!dir.isDirectory())
{
throw new IOException("Can't create directory, a file is in the way");
}
} else
{
dir.mkdirs();
if (!dir.isDirectory())
{
throw new IOException("Unable to create directory");
}
}
}
最后创建一个Asynctask:
private class ManageAssetFolders extends AsyncTask<Void, Void, Void>
{
@Override
protected Void doInBackground(Void... arg0)
{
manageAssetFolderToSDcard();
return null;
}
}
从你的活动中:
new ManageAssetFolders().execute();
其他回答
对于正在更新到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"
}
这是目前为止我能在网上找到的最好的解决方案。 我使用了以下链接https://gist.github.com/mhasby/026f02b33fcc4207b302a60645f6e217,但它有一个错误,我修复了,然后它的工作就像一个魅力。 这是我的代码。您可以轻松使用它,因为它是一个独立的java类。
public class CopyAssets {
public static void copyAssets(Context context) {
AssetManager assetManager = context.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);
out = new FileOutputStream(Environment.getExternalStorageDirectory()+"/www/resources/" + filename);
copyFile(in, out);
} catch(IOException e) {
Log.e("tag", "Failed to copy asset file: " + filename, e);
}
finally {
if (in != null) {
try {
in.close();
in = null;
} catch (IOException e) {
}
}
if (out != null) {
try {
out.flush();
out.close();
out = null;
} catch (IOException e) {
}
}
}
}
}
public static 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);
}
}}
As you can see, just create an instance of CopyAssets in your java class which has an activity. Now this part is important, as far as my testing and researching on the internet, You cannot use AssetManager if the class has no activity . It has something to do with the context of the java class. Now, the c.copyAssets(getApplicationContext()) is an easy way to access the method, where c is and instance of CopyAssets class. As per my requirement, I allowed the program to copy all my resource files inside the asset folder to the /www/resources/ of my internal directory. You can easily find out the part where you need to make changes to the directory as per your use. Feel free to ping me if you need any help.
使用AssetManager,它允许读取资产中的文件。然后使用常规的Java IO将文件写入sdcard。
谷歌是你的朋友,搜索一个例子。
修改了@ danya的SO回答
private void copyAssets(String path, String outPath) {
AssetManager assetManager = this.getAssets();
String assets[];
try {
assets = assetManager.list(path);
if (assets.length == 0) {
copyFile(path, outPath);
} else {
String fullPath = outPath + "/" + path;
File dir = new File(fullPath);
if (!dir.exists())
if (!dir.mkdir()) Log.e(TAG, "No create external directory: " + dir );
for (String asset : assets) {
copyAssets(path + "/" + asset, outPath);
}
}
} catch (IOException ex) {
Log.e(TAG, "I/O Exception", ex);
}
}
private void copyFile(String filename, String outPath) {
AssetManager assetManager = this.getAssets();
InputStream in;
OutputStream out;
try {
in = assetManager.open(filename);
String newFileName = outPath + "/" + 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();
out.flush();
out.close();
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
}
准备工作
在src /主/资产 添加名称折叠文件夹
使用
File outDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString());
copyAssets("fold",outDir.toString());
在外部目录中找到折叠资产内的所有文件和目录
这里是一个针对当前Android设备的清理版本,功能方法设计,以便您可以将其复制到AssetsHelper类,例如;)
/**
*
* Info: prior to Android 2.3, any compressed asset file with an
* uncompressed size of over 1 MB cannot be read from the APK. So this
* should only be used if the device has android 2.3 or later running!
*
* @param c
* @param targetFolder
* e.g. {@link Environment#getExternalStorageDirectory()}
* @throws Exception
*/
@TargetApi(Build.VERSION_CODES.GINGERBREAD)
public static boolean copyAssets(AssetManager assetManager,
File targetFolder) throws Exception {
Log.i(LOG_TAG, "Copying files from assets to folder " + targetFolder);
return copyAssets(assetManager, "", targetFolder);
}
/**
* The files will be copied at the location targetFolder+path so if you
* enter path="abc" and targetfolder="sdcard" the files will be located in
* "sdcard/abc"
*
* @param assetManager
* @param path
* @param targetFolder
* @return
* @throws Exception
*/
public static boolean copyAssets(AssetManager assetManager, String path,
File targetFolder) throws Exception {
Log.i(LOG_TAG, "Copying " + path + " to " + targetFolder);
String sources[] = assetManager.list(path);
if (sources.length == 0) { // its not a folder, so its a file:
copyAssetFileToFolder(assetManager, path, targetFolder);
} else { // its a folder:
if (path.startsWith("images") || path.startsWith("sounds")
|| path.startsWith("webkit")) {
Log.i(LOG_TAG, " > Skipping " + path);
return false;
}
File targetDir = new File(targetFolder, path);
targetDir.mkdirs();
for (String source : sources) {
String fullSourcePath = path.equals("") ? source : (path
+ File.separator + source);
copyAssets(assetManager, fullSourcePath, targetFolder);
}
}
return true;
}
private static void copyAssetFileToFolder(AssetManager assetManager,
String fullAssetPath, File targetBasePath) throws IOException {
InputStream in = assetManager.open(fullAssetPath);
OutputStream out = new FileOutputStream(new File(targetBasePath,
fullAssetPath));
byte[] buffer = new byte[16 * 1024];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
in.close();
out.flush();
out.close();
}
推荐文章
- 警告:API ' variable . getjavacompile()'已过时,已被' variable . getjavacompileprovider()'取代
- 安装APK时出现错误
- 碎片中的onCreateOptionsMenu
- TextView粗体通过XML文件?
- 如何使线性布局的孩子之间的空间?
- DSL元素android.dataBinding。enabled'已过时,已被'android.buildFeatures.dataBinding'取代
- ConstraintLayout:以编程方式更改约束
- PANIC: AVD系统路径损坏。检查ANDROID_SDK_ROOT值
- 如何生成字符串类型的buildConfigField
- Recyclerview不调用onCreateViewHolder
- Android API 21工具栏填充
- Android L中不支持操作栏导航模式
- 如何复制在bash所有目录和文件递归?
- 如何在TextView中添加一个子弹符号?
- PreferenceManager getDefaultSharedPreferences在Android Q中已弃用