我在资产文件夹里有几个文件。我需要把它们都复制到一个文件夹,比如/sdcard/folder。我想从一个线程中做这件事。我该怎么做?
当前回答
如果其他人也有同样的问题,我就是这么做的
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移动文件
其他回答
我知道这已经回答,但我有一个稍微更优雅的方式从资产目录复制到sdcard上的文件。它不需要“for”循环,而是使用文件流和通道来完成工作。
(注)如果使用任何类型的压缩文件,APK, PDF,…你可能想重命名文件扩展名之前插入到资产,然后重命名一旦你复制到SDcard)
AssetManager am = context.getAssets();
AssetFileDescriptor afd = null;
try {
afd = am.openFd( "MyFile.dat");
// Create new file to copy into.
File file = new File(Environment.getExternalStorageDirectory() + java.io.File.separator + "NewFile.dat");
file.createNewFile();
copyFdToFile(afd.getFileDescriptor(), file);
} catch (IOException e) {
e.printStackTrace();
}
一种复制文件而不必循环遍历它的方法。
public static void copyFdToFile(FileDescriptor src, File dst) throws IOException {
FileChannel inChannel = new FileInputStream(src).getChannel();
FileChannel outChannel = new FileOutputStream(dst).getChannel();
try {
inChannel.transferTo(0, inChannel.size(), outChannel);
} finally {
if (inChannel != null)
inChannel.close();
if (outChannel != null)
outChannel.close();
}
}
使用AssetManager,它允许读取资产中的文件。然后使用常规的Java IO将文件写入sdcard。
谷歌是你的朋友,搜索一个例子。
由于一些错误,上述解决方案无法工作:
目录创建失败 Android返回的资产也包含三个文件夹:图像,声音和webkit 增加了处理大文件的方法:在项目的资产文件夹中添加扩展名.mp3到文件,在复制目标文件时将没有.mp3扩展名
下面是代码(我留下了Log语句,但你现在可以删除它们):
final static String TARGET_BASE_PATH = "/sdcard/appname/voices/";
private void copyFilesToSdCard() {
copyFileOrDir(""); // copy all files in assets folder in my project
}
private void copyFileOrDir(String path) {
AssetManager assetManager = this.getAssets();
String assets[] = null;
try {
Log.i("tag", "copyFileOrDir() "+path);
assets = assetManager.list(path);
if (assets.length == 0) {
copyFile(path);
} else {
String fullPath = TARGET_BASE_PATH + path;
Log.i("tag", "path="+fullPath);
File dir = new File(fullPath);
if (!dir.exists() && !path.startsWith("images") && !path.startsWith("sounds") && !path.startsWith("webkit"))
if (!dir.mkdirs())
Log.i("tag", "could not create dir "+fullPath);
for (int i = 0; i < assets.length; ++i) {
String p;
if (path.equals(""))
p = "";
else
p = path + "/";
if (!path.startsWith("images") && !path.startsWith("sounds") && !path.startsWith("webkit"))
copyFileOrDir( p + 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;
String newFileName = null;
try {
Log.i("tag", "copyFile() "+filename);
in = assetManager.open(filename);
if (filename.endsWith(".jpg")) // extension was added to avoid compression on APK file
newFileName = TARGET_BASE_PATH + filename.substring(0, filename.length()-4);
else
newFileName = TARGET_BASE_PATH + 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", "Exception in copyFile() of "+newFileName);
Log.e("tag", "Exception in copyFile() "+e.toString());
}
}
编辑:更正了一个错位的“;”,这是抛出一个系统的“无法创建目录”错误。
复制所有文件和目录从资产到您的文件夹!
为了更好地复制,使用apache Commons IO
public void doCopyAssets() throws IOException {
File externalFilesDir = context.getExternalFilesDir(null);
doCopy("", externalFilesDir.getPath());
}
//这是复制的主要方法
private void doCopy(String dirName, String outPath) throws IOException {
String[] srcFiles = assets.list(dirName);//for directory
for (String srcFileName : srcFiles) {
String outFileName = outPath + File.separator + srcFileName;
String inFileName = dirName + File.separator + srcFileName;
if (dirName.equals("")) {// for first time
inFileName = srcFileName;
}
try {
InputStream inputStream = assets.open(inFileName);
copyAndClose(inputStream, new FileOutputStream(outFileName));
} catch (IOException e) {//if directory fails exception
new File(outFileName).mkdir();
doCopy(inFileName, outFileName);
}
}
}
public static void closeQuietly(AutoCloseable autoCloseable) {
try {
if(autoCloseable != null) {
autoCloseable.close();
}
} catch(IOException ioe) {
//skip
}
}
public static void copyAndClose(InputStream input, OutputStream output) throws IOException {
copy(input, output);
closeQuietly(input);
closeQuietly(output);
}
public static void copy(InputStream input, OutputStream output) throws IOException {
byte[] buffer = new byte[1024];
int n = 0;
while(-1 != (n = input.read(buffer))) {
output.write(buffer, 0, n);
}
}
这里是一个针对当前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();
}
推荐文章
- 如何在android中获得当前前景活动上下文?
- 如何在Android中获取当前日期?
- 获取Android设备名称
- 在WebView中上传文件
- 加载HTML文件到WebView
- Android:为什么视图没有maxHeight ?
- 如何获得具有已知资源名称的资源id ?
- 在Android上将字符串转换为整数
- 为什么“System.out。”println“工作在Android?
- WebView显示err_cleartext_not_allowed尽管站点是HTTPS
- Android M权限:对shouldShowRequestPermissionRationale()函数的使用感到困惑
- 为什么构建类型与产品风味不同?
- 我如何在一个片段中访问getSupportFragmentManager() ?
- 调试在哪里。Android Studio中的密钥存储库
- 从资产中读取文件