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


当前回答

试试这个,它更简单,这将帮助你:

// Open your local db as the input stream
    InputStream myInput = _context.getAssets().open(YOUR FILE NAME);

    // Path to the just created empty db
    String outFileName =SDCARD PATH + YOUR FILE NAME;

    // Open the empty db as the output stream
    OutputStream myOutput = new FileOutputStream(outFileName);

    // transfer bytes from the inputfile to the outputfile
    byte[] buffer = new byte[1024];
    int length;
    while ((length = myInput.read(buffer)) > 0) {
        myOutput.write(buffer, 0, length);
    }
    // Close the streams
    myOutput.flush();
    myOutput.close();
    myInput.close();

其他回答

由于一些错误,上述解决方案无法工作:

目录创建失败 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());
    }

}

编辑:更正了一个错位的“;”,这是抛出一个系统的“无法创建目录”错误。

您还可以使用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);
            }
        }
    }

}

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

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

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

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

基于您的解决方案,我自己做了一些事情来允许子文件夹。有些人可能会觉得这很有用:

...

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());
    }

}