我在资产文件夹里有几个文件。我需要把它们都复制到一个文件夹,比如/sdcard/folder。我想从一个线程中做这件事。我该怎么做?


当前回答

这里是一个针对当前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();
}

其他回答

这就是我的个性化文本提取类,希望对大家有用。

package lorenzo.morelli.platedetector;

import android.content.Context;
import android.content.res.AssetManager;
import android.graphics.Bitmap;

import com.googlecode.tesseract.android.TessBaseAPI;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class TextExtractor {

    private final Context context;
    private final String dirName;
    private final String language;

    public TextExtractor(final Context context, final String dirName, final String language) {
        this.context = context;
        this.dirName = dirName;
        this.language = language;
    }

    public String extractText(final Bitmap bitmap) {
        final TessBaseAPI tessBaseApi = new TessBaseAPI();
        final String datapath = this.context.getFilesDir()+ "/tesseract/";
        checkFile(new File(datapath + this.dirName + "/"), datapath, this.dirName, this.language);

        tessBaseApi.init(datapath, this.language);
        tessBaseApi.setImage(bitmap);
        final String extractedText = tessBaseApi.getUTF8Text();
        tessBaseApi.end();
        return extractedText;
    }

    private void checkFile(final File dir, final String datapath, final String dirName, final String language) {
        //directory does not exist, but we can successfully create it
        if (!dir.exists()&& dir.mkdirs()) {
            copyFiles(datapath, dirName, language);
        } //The directory exists, but there is no data file in it
        if(dir.exists()) {
            final String datafilepath = datapath + "/" + dirName + "/" + language + ".traineddata";
            final File datafile = new File(datafilepath);
            if (!datafile.exists()) {
                copyFiles(datapath, dirName, language);
            }
        }
    }

    private void copyFiles(final String datapath, final String dirName, final String language) {
        try {
            //location we want the file to be at
            final String filepath = datapath + "/" + dirName + "/" + language + ".traineddata";

            //get access to AssetManager
            final AssetManager assetManager = this.context.getAssets();

            //open byte streams for reading/writing
            final InputStream instream = assetManager.open(dirName + "/" + language + ".traineddata");
            final OutputStream outstream = new FileOutputStream(filepath);

            //copy the file to the location specified by filepath
            byte[] buffer = new byte[1024];
            int read;
            while ((read = instream.read(buffer)) != -1) {
                outstream.write(buffer, 0, read);
            }
            outstream.flush();
            outstream.close();
            instream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

要使用它,你需要训练过的数据文件。你可以从这个链接下载trainddata文件。

一旦你下载了你想要的traineddata文件,你需要在你的Android项目中创建一个名为assets的Android资源目录。在新创建的资产文件夹中,你需要创建一个名为“tessdata”的常规目录,在那里你可以放置你的训练数据文件。 最后你必须初始化MainActivity中的“TextExtractor”类。

final TextExtractor textExtractor = new TextExtractor(this, "tessdata", "eng");

第一个参数是上下文,第二个参数是刚刚创建的目录名,最后一个参数是刚刚下载的训练数据的语言。

要提取文本,你必须调用"extractText"方法:

final String text = textExtractor.extractText(imageWithText);

注意,extractText需要一个位图图像才能工作!! 你可以用这一行从你的可绘制文件中创建一个BitMap图像:

final BitMap image = BitmapFactory.decodeResource(getResources(), R.drawable.test_image);

如果你需要更多的支持,我建议你遵循这个有用的指南:https://github.com/SamVanRoy/Android_OCR_App

您还可以使用Guava的ByteStream将文件从资产文件夹复制到SD卡。这是我最终得到的解决方案,将文件递归地从资产文件夹复制到SD卡:

/**
 * Copies all assets in an assets directory to the SD file system.
 */
public class CopyAssetsToSDHelper {

    public static void copyAssets(String assetDir, String targetDir, Context context) 
        throws IOException {
        AssetManager assets = context.getAssets();
        String[] list = assets.list(assetDir);
        for (String f : Objects.requireNonNull(list)) {
            if (f.indexOf(".") > 1) { // check, if this is a file
                File outFile = new File(context.getExternalFilesDir(null), 
                    String.format("%s/%s", targetDir, f));
                File parentFile = outFile.getParentFile();
                if (!Objects.requireNonNull(parentFile).exists()) {
                    if (!parentFile.mkdirs()) {
                        throw new IOException(String.format("Could not create directory %s.", 
                            parentFile));
                    }
                }
                try (InputStream fin = assets.open(String.format("%s/%s", assetDir, f));
                     OutputStream fout = new FileOutputStream(outFile)) {
                    ByteStreams.copy(fin, fout);
                }
            } else { // This is a directory
                copyAssets(String.format("%s/%s", assetDir, f), String.format("%s/%s", targetDir, f), 
                    context);
            }
        }
    }

}

复制所有文件和目录从资产到您的文件夹!

为了更好地复制,使用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);
    }
}

轻微修改以上回答复制文件夹递归和适应自定义目的地。

public void copyFileOrDir(String path, String destinationDir) {
    AssetManager assetManager = this.getAssets();
    String assets[] = null;
    try {
        assets = assetManager.list(path);
        if (assets.length == 0) {
            copyFile(path,destinationDir);
        } else {
            String fullPath = destinationDir + "/" + path;
            File dir = new File(fullPath);
            if (!dir.exists())
                dir.mkdir();
            for (int i = 0; i < assets.length; ++i) {
                copyFileOrDir(path + "/" + assets[i], destinationDir + path + "/" + assets[i]);
            }
        }
    } catch (IOException ex) {
        Log.e("tag", "I/O Exception", ex);
    }
}

private void copyFile(String filename, String destinationDir) {
    AssetManager assetManager = this.getAssets();
    String newFileName = destinationDir + "/" + filename;

    InputStream in = null;
    OutputStream out = null;
    try {
        in = assetManager.open(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());
    }
    new File(newFileName).setExecutable(true, false);
}

在Kotlin中,这可以用一行完成!

为InputStream添加扩展乐趣

fun InputStream.toFile(to: File){
    this.use { input->
        to.outputStream().use { out->
            input.copyTo(out)
        }
    }
}

然后使用它

MainActivity.kt

assets.open("test.zip").toFile(File(filesDir,"test.zip"))