Wie kopiere ich Dateien aus dem Ordner "Assets" auf die SD-Karte?
251
Ich habe ein paar Dateien im assetsOrdner. Ich muss sie alle in einen Ordner kopieren, z. B. / sdcard / folder. Ich möchte dies aus einem Thread heraus tun. Wie mache ich es?
Bevor Sie eine der folgenden (großartigen!) Lösungen kopieren / einfügen, sollten Sie diese Bibliothek in einer Codezeile verwenden: stackoverflow.com/a/41970539/9648
JohnnyLambada
Antworten:
346
Wenn jemand das gleiche Problem hat, habe ich es so gemacht
Um Dateien auf die SD-Karte zu schreiben, müssen Sie die Berechtigung für das Manifest erteilen, z. B. <Verwendungsberechtigung android: name = "android.permission.WRITE_EXTERNAL_STORAGE" />
IronBlossom
22
Ich würde mich auch nicht darauf verlassen, dass sich die SD-Karte unter / sdcard befindet, sondern den Pfad mit Environment.getExternalStorageDirectory ()
Axarydax
2
Sollte ich verwenden: 16 * 1024 (16kb) Ich tendiere dazu, 16K oder 32K als eine gute Balance zwischen Speichernutzung und Leistung zu wählen.
Nam Vu
3
@rciovati bekam diesen LaufzeitfehlerFailed to copy asset file: myfile.txt java.io.FileNotFoundException: myfile.txt at android.content.res.AssetManager.openAsset(Native Method)
likejudo
7
Für mich funktioniert dieser Code nur, wenn ich in = assetManager.open("images-wall/"+filename);
Folgendes
62
Basierend auf Ihrer Lösung habe ich etwas Eigenes getan, um Unterordner zuzulassen. Jemand könnte dies hilfreich finden:
assetManager.list(path)kann auf dem Gerät langsam sein, um Assets Pfade Liste im Voraus zu erstellen, kann dieses Snippet aus assetsdir verwendet werden:find . -name "*" -type f -exec ls -l {} \; | awk '{print substr($9,3)}' >> assets.list
alexkasko
3
Schöne Lösung! Die einzige erforderliche Korrektur besteht darin, führende Trennzeichen am Anfang von copyFileOrDir () zu kürzen: path = path.startsWith ("/")? path.substring (1): path;
Cross_
Dieser Stackoverflow ist auf bestimmten Geräten zB: S5
siehe
2
Ersetzen Sie "/ data / data /" + this.getPackageName () durch this.getFilesDir (). getAbsolutePath ()
ibrahimyilmaz
1
... und Streams im finallyBlock schließen))
Mixaz
48
Die obige Lösung hat aufgrund einiger Fehler nicht funktioniert:
Die Verzeichniserstellung hat nicht funktioniert
Von Android zurückgegebene Assets enthalten außerdem drei Ordner: Bilder, Sounds und Webkit
Möglichkeit zum Umgang mit großen Dateien hinzugefügt: Fügen Sie der Datei im Assets-Ordner Ihres Projekts die Erweiterung .mp3 hinzu, und während des Kopierens wird die Zieldatei ohne die Erweiterung .mp3 angezeigt
Hier ist der Code (ich habe die Log-Anweisungen verlassen, aber Sie können sie jetzt löschen):
finalstaticString TARGET_BASE_PATH ="/sdcard/appname/voices/";privatevoid copyFilesToSdCard(){
copyFileOrDir("");// copy all files in assets folder in my project}privatevoid 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 =newFile(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);}}privatevoid copyFile(String filename){AssetManager assetManager =this.getAssets();InputStreamin=null;OutputStreamout=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=newFileOutputStream(newFileName);byte[] buffer =newbyte[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());}}
EDIT: Ein falsches ";" Das warf einen systematischen Fehler "Dir konnte nicht erstellt werden".
HINWEIS: Log.i ("Tag", "Verzeichnis konnte nicht erstellt werden" + fullPath); passiert immer als; ist auf dem if verlegt.
RoundSparrow Hilltx
super Weg! Vielen Dank! Aber warum überprüfen Sie die JPG-Datei?
Phuong
32
Ich weiß, dass dies beantwortet wurde, aber ich habe eine etwas elegantere Möglichkeit, aus dem Asset-Verzeichnis in eine Datei auf der SD-Karte zu kopieren. Es erfordert keine "for" -Schleife, sondern verwendet stattdessen Dateistreams und Kanäle, um die Arbeit zu erledigen.
(Hinweis) Wenn Sie eine komprimierte Datei, APK, PDF, ... verwenden, möchten Sie möglicherweise die Dateierweiterung vor dem Einfügen in das Asset umbenennen und nach dem Kopieren auf die SD-Karte umbenennen.)
AssetManager am = context.getAssets();AssetFileDescriptor afd =null;try{
afd = am.openFd("MyFile.dat");// Create new file to copy into.File file =newFile(Environment.getExternalStorageDirectory()+ java.io.File.separator +"NewFile.dat");
file.createNewFile();
copyFdToFile(afd.getFileDescriptor(), file);}catch(IOException e){
e.printStackTrace();}
Eine Möglichkeit, eine Datei zu kopieren, ohne sie durchlaufen zu müssen.
Gefiel dies gegenüber den anderen Lösungen, etwas ordentlicher. Leichte Änderung an meiner, die das Erstellen fehlender Dateiformate umfasst. Prost!
Chris.Jenkins
3
Dies würde für mich nicht über den Dateideskriptor hinaus funktionieren This file can not be opened as a file descriptor; it is probably compressed- es ist eine PDF-Datei. Wissen Sie, wie Sie das beheben können?
Gaʀʀʏ
1
Dies setzt voraus, dass inChannel.size () die Größe der Dateigröße zurückgibt. Es gibt keine solche Garantie . Ich bekomme 2,5 MiB für 2 Dateien mit jeweils 450 KiB.
AI0867
1
Ich habe gerade festgestellt, dass AssetFileDescriptor.getLength () die richtige Dateigröße zurückgibt.
AI0867
1
Darüber hinaus startet das Asset möglicherweise nicht an Position 0 im Dateideskriptor. AssetFileDescriptor.getStartOffset () gibt den Startoffset zurück.
AI0867
5
Probieren Sie es aus, es ist viel einfacher, dies wird Ihnen helfen:
// Open your local db as the input streamInputStream myInput = _context.getAssets().open(YOUR FILE NAME);// Path to the just created empty dbString outFileName =SDCARD PATH + YOUR FILE NAME;// Open the empty db as the output streamOutputStream myOutput =newFileOutputStream(outFileName);// transfer bytes from the inputfile to the outputfilebyte[] buffer =newbyte[1024];int length;while((length = myInput.read(buffer))>0){
myOutput.write(buffer,0, length);}// Close the streams
myOutput.flush();
myOutput.close();
myInput.close();
list (assetPath)?. let {...}, tatsächlich. Es ist nullable.
Gábor
4
Hier ist eine bereinigte Version für aktuelle Android-Geräte, funktionales Methodendesign, damit Sie sie in eine AssetsHelper-Klasse kopieren können, zB;)
/**
*
* 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)publicstaticboolean copyAssets(AssetManager assetManager,File targetFolder)throwsException{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
*/publicstaticboolean copyAssets(AssetManager assetManager,String path,File targetFolder)throwsException{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);returnfalse;}File targetDir =newFile(targetFolder, path);
targetDir.mkdirs();for(String source : sources){String fullSourcePath = path.equals("")? source :(path
+File.separator + source);
copyAssets(assetManager, fullSourcePath, targetFolder);}}returntrue;}privatestaticvoid copyAssetFileToFolder(AssetManager assetManager,String fullAssetPath,File targetBasePath)throwsIOException{InputStreamin= assetManager.open(fullAssetPath);OutputStreamout=newFileOutputStream(newFile(targetBasePath,
fullAssetPath));byte[] buffer =newbyte[16*1024];int read;while((read =in.read(buffer))!=-1){out.write(buffer,0, read);}in.close();out.flush();out.close();}
Unter Verwendung einiger Konzepte in den Antworten auf diese Frage habe ich eine Klasse geschrieben, die aufgerufen wurde AssetCopier, um das Kopieren zu /assets/vereinfachen. Es ist auf github verfügbar und kann mit jitpack.io aufgerufen werden :
Zuerst müssen Sie sicherstellen, dass die Datei unkomprimiert gespeichert wird. Das Verpackungssystem kann sich dafür entscheiden, Dateien mit einer Erweiterung zu komprimieren, die nicht als noCompress gekennzeichnet ist , und komprimierte Dateien können nicht dem Speicher zugeordnet werden. In diesem Fall müssen Sie sich daher auf AssetManager.open verlassen .
Sie können Ihrer Datei die Erweiterung '.mp3' hinzufügen, um zu verhindern, dass sie komprimiert wird. Die richtige Lösung besteht jedoch darin, die Datei app / build.gradle zu ändern und die folgenden Zeilen hinzuzufügen (um die Komprimierung von PDF-Dateien zu deaktivieren).
aaptOptions {
noCompress 'pdf'}
Datei packen
Beachten Sie, dass der Packager immer noch mehrere Dateien in eine packen kann, sodass Sie nicht einfach die gesamte Datei lesen können, die Ihnen der AssetManager zur Verfügung stellt. Sie müssen den AssetFileDescriptor fragen, welche Teile Sie benötigen.
Den richtigen Teil der gepackten Datei finden
Sobald Sie sichergestellt haben, dass Ihre Datei unkomprimiert gespeichert ist, können Sie mit der AssetManager.openFd- Methode einen AssetFileDescriptor abrufen , mit dem Sie einen FileInputStream abrufen können (im Gegensatz zu AssetManager.open , der einen InputStream zurückgibt ), der einen FileChannel enthält . Es enthält auch den Startoffset (getStartOffset) und die Größe (getLength) , die Sie benötigen, um den richtigen Teil der Datei zu erhalten.
Implementierung
Eine beispielhafte Implementierung ist unten angegeben:
Verwenden Sie AssetManager , um die Dateien in den Assets zu lesen. Verwenden Sie dann reguläres Java IO, um die Dateien auf die SD-Karte zu schreiben.
Google ist dein Freund, suche nach einem Beispiel.
Hallo Leute, ich habe so etwas gemacht. Für N-ten Tiefenkopierordner und zu kopierende Dateien. Damit können Sie die gesamte Verzeichnisstruktur kopieren, um sie von Android AssetManager zu kopieren :)
privatevoid manageAssetFolderToSDcard(){try{String arg_assetDir = getApplicationContext().getPackageName();String arg_destinationDir =FRConstants.ANDROID_DATA + arg_assetDir;FileFolderInCache=newFile(arg_destinationDir);if(!FolderInCache.exists()){
copyDirorfileFromAssetManager(arg_assetDir, arg_destinationDir);}}catch(IOException e1){
e1.printStackTrace();}}publicString copyDirorfileFromAssetManager(String arg_assetDir,String arg_destinationDir)throwsIOException{File sd_path =Environment.getExternalStorageDirectory();String dest_dir_path = sd_path + addLeadingSlash(arg_destinationDir);File dest_dir =newFile(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 fileString 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;}publicvoid copyAssetFile(String assetFilePath,String destinationFilePath)throwsIOException{InputStreamin= getApplicationContext().getAssets().open(assetFilePath);OutputStreamout=newFileOutputStream(destinationFilePath);byte[] buf =newbyte[1024];int len;while((len =in.read(buf))>0)out.write(buf,0, len);in.close();out.close();}publicString addTrailingSlash(String path){if(path.charAt(path.length()-1)!='/'){
path +="/";}return path;}publicString addLeadingSlash(String path){if(path.charAt(0)!='/'){
path ="/"+ path;}return path;}publicvoid createDir(File dir)throwsIOException{if(dir.exists()){if(!dir.isDirectory()){thrownewIOException("Can't create directory, a file is in the way");}}else{
dir.mkdirs();if(!dir.isDirectory()){thrownewIOException("Unable to create directory");}}}
Basierend auf der Lösung von Rohith Nandakumar habe ich selbst etwas unternommen, um Dateien aus einem Unterordner von Assets (dh "Assets / MyFolder ") zu kopieren . Außerdem überprüfe ich, ob die Datei bereits auf der SD-Karte vorhanden ist, bevor ich erneut versuche, sie zu kopieren.
privatevoid copyAssets(){AssetManager assetManager = getAssets();String[] files =null;try{
files = assetManager.list("MyFolder");}catch(IOException e){Log.e("tag","Failed to get asset file list.", e);}if(files !=null)for(String filename : files){InputStreamin=null;OutputStreamout=null;try{in= assetManager.open("MyFolder/"+filename);File outFile =newFile(getExternalFilesDir(null), filename);if(!(outFile.exists())){// File does not exist...out=newFileOutputStream(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}}}}}privatevoid copyFile(InputStreamin,OutputStreamout)throwsIOException{byte[] buffer =newbyte[1024];int read;while((read =in.read(buffer))!=-1){out.write(buffer,0, read);}}
Dies ist bei weitem die beste Lösung, die ich im Internet finden konnte. Ich habe den folgenden Link verwendet: https://gist.github.com/mhasby/026f02b33fcc4207b302a60645f6e217 , aber es gab einen einzelnen Fehler, den ich behoben habe, und dann funktioniert es wie ein Zauber. Hier ist mein Code. Sie können es leicht verwenden, da es sich um eine unabhängige Java-Klasse handelt.
Wie Sie sehen können, erstellen Sie einfach eine Instanz von CopyAssetsin Ihrer Java-Klasse, die eine Aktivität hat. Nun ist dieser Teil wichtig für meine Tests und Recherchen im Internet You cannot use AssetManager if the class has no activity. Es hat etwas mit dem Kontext der Java-Klasse zu tun.
Dies c.copyAssets(getApplicationContext())ist eine einfache Möglichkeit, auf die Methode zuzugreifen, wo csich eine Instanz der CopyAssetsKlasse befindet. Gemäß meiner Anforderung erlaubte ich dem Programm, alle meine Ressourcendateien im assetOrdner in das /www/resources/Verzeichnis meines internen Verzeichnisses zu kopieren .
Sie können leicht herausfinden, wo Sie gemäß Ihrer Verwendung Änderungen am Verzeichnis vornehmen müssen. Sie können mich gerne anrufen, wenn Sie Hilfe benötigen.
Befolgen Sie diese Schritte, um zu vermeiden FileUriExposedExceptions, dass der Benutzer die Berechtigung WRITE_EXTERNAL_STORAGEerteilt hat und sich Ihre Datei in befindet assets/pdfs/mypdf.pdf.
private fun openFile(){var inputStream:InputStream?=nullvar outputStream:OutputStream?=nulltry{
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{privateconst val PDF_ASSETS_PATH ="pdfs"privateconst val PDF_FILE_NAME ="mypdf.pdf"}
Antworten:
Wenn jemand das gleiche Problem hat, habe ich es so gemacht
Referenz: Datei mit Java verschieben
quelle
Failed to copy asset file: myfile.txt java.io.FileNotFoundException: myfile.txt at android.content.res.AssetManager.openAsset(Native Method)
in = assetManager.open("images-wall/"+filename);
Basierend auf Ihrer Lösung habe ich etwas Eigenes getan, um Unterordner zuzulassen. Jemand könnte dies hilfreich finden:
...
...
quelle
assetManager.list(path)
kann auf dem Gerät langsam sein, um Assets Pfade Liste im Voraus zu erstellen, kann dieses Snippet ausassets
dir verwendet werden:find . -name "*" -type f -exec ls -l {} \; | awk '{print substr($9,3)}' >> assets.list
finally
Block schließen))Die obige Lösung hat aufgrund einiger Fehler nicht funktioniert:
Hier ist der Code (ich habe die Log-Anweisungen verlassen, aber Sie können sie jetzt löschen):
EDIT: Ein falsches ";" Das warf einen systematischen Fehler "Dir konnte nicht erstellt werden".
quelle
Ich weiß, dass dies beantwortet wurde, aber ich habe eine etwas elegantere Möglichkeit, aus dem Asset-Verzeichnis in eine Datei auf der SD-Karte zu kopieren. Es erfordert keine "for" -Schleife, sondern verwendet stattdessen Dateistreams und Kanäle, um die Arbeit zu erledigen.
(Hinweis) Wenn Sie eine komprimierte Datei, APK, PDF, ... verwenden, möchten Sie möglicherweise die Dateierweiterung vor dem Einfügen in das Asset umbenennen und nach dem Kopieren auf die SD-Karte umbenennen.)
Eine Möglichkeit, eine Datei zu kopieren, ohne sie durchlaufen zu müssen.
quelle
This file can not be opened as a file descriptor; it is probably compressed
- es ist eine PDF-Datei. Wissen Sie, wie Sie das beheben können?Probieren Sie es aus, es ist viel einfacher, dies wird Ihnen helfen:
quelle
Dies wäre in Kotlin prägnant.
quelle
Hier ist eine bereinigte Version für aktuelle Android-Geräte, funktionales Methodendesign, damit Sie sie in eine AssetsHelper-Klasse kopieren können, zB;)
quelle
Diese SO- Antwort wurde von @DannyA geändert
Vorbereitungen
im
src/main/assets
Ordner mit Namen hinzufügenfold
Verwendung
Suchen Sie im externen Verzeichnis alle Dateien und Verzeichnisse, die sich in den Fold-Assets befinden
quelle
Kopieren Sie alle Dateien und Verzeichnisse von Assets in Ihren Ordner!
Zum besseren Kopieren verwenden Sie Apache Commons io
// Dies ist die Hauptmethode für das Kopieren
quelle
Basierend auf der Antwort von Yoram Cohen ist hier eine Version, die nicht statisches Zielverzeichnis unterstützt.
Rechnung mit
copyFileOrDir(getDataDir(), "")
zum Schreiben in den internen App-Speicherordner / data / data / pkg_name /Vermeidet das Kopieren von "Bildern" usw. gefälschten Asset-Ordnern wie
quelle
Unter Verwendung einiger Konzepte in den Antworten auf diese Frage habe ich eine Klasse geschrieben, die aufgerufen wurde
AssetCopier
, um das Kopieren zu/assets/
vereinfachen. Es ist auf github verfügbar und kann mit jitpack.io aufgerufen werden :Weitere Informationen finden Sie unter https://github.com/flipagram/android-assetcopier .
quelle
Es gibt im Wesentlichen zwei Möglichkeiten, dies zu tun.
Zunächst können Sie AssetManager.open und, wie von Rohith Nandakumar beschrieben, verwenden und über den Eingabestream iterieren.
Zweitens können Sie AssetManager.openFd verwenden , mit dem Sie einen FileChannel (mit dem Befehl [transferTo] ( https://developer.android.com/reference/java/nio/channels/FileChannel.html#transferTo(long ,) verwenden können. long, java.nio.channels.WritableByteChannel)) und [transferFrom] ( https://developer.android.com/reference/java/nio/channels/FileChannel.html#transferFrom(java.nio.channels.ReadableByteChannel , long, long)) Methoden), so dass Sie den Eingabestream nicht selbst durchlaufen müssen.
Ich werde die openFd-Methode hier beschreiben.
Kompression
Zuerst müssen Sie sicherstellen, dass die Datei unkomprimiert gespeichert wird. Das Verpackungssystem kann sich dafür entscheiden, Dateien mit einer Erweiterung zu komprimieren, die nicht als noCompress gekennzeichnet ist , und komprimierte Dateien können nicht dem Speicher zugeordnet werden. In diesem Fall müssen Sie sich daher auf AssetManager.open verlassen .
Sie können Ihrer Datei die Erweiterung '.mp3' hinzufügen, um zu verhindern, dass sie komprimiert wird. Die richtige Lösung besteht jedoch darin, die Datei app / build.gradle zu ändern und die folgenden Zeilen hinzuzufügen (um die Komprimierung von PDF-Dateien zu deaktivieren).
Datei packen
Beachten Sie, dass der Packager immer noch mehrere Dateien in eine packen kann, sodass Sie nicht einfach die gesamte Datei lesen können, die Ihnen der AssetManager zur Verfügung stellt. Sie müssen den AssetFileDescriptor fragen, welche Teile Sie benötigen.
Den richtigen Teil der gepackten Datei finden
Sobald Sie sichergestellt haben, dass Ihre Datei unkomprimiert gespeichert ist, können Sie mit der AssetManager.openFd- Methode einen AssetFileDescriptor abrufen , mit dem Sie einen FileInputStream abrufen können (im Gegensatz zu AssetManager.open , der einen InputStream zurückgibt ), der einen FileChannel enthält . Es enthält auch den Startoffset (getStartOffset) und die Größe (getLength) , die Sie benötigen, um den richtigen Teil der Datei zu erhalten.
Implementierung
Eine beispielhafte Implementierung ist unten angegeben:
Diese Antwort basiert auf der Antwort von JPM .
quelle
Ändern Sie Teile des Codes wie folgt:
Das vorige Beispiel ist für Pdfs, im Fall von Beispiel .txt
quelle
Verwenden Sie AssetManager , um die Dateien in den Assets zu lesen. Verwenden Sie dann reguläres Java IO, um die Dateien auf die SD-Karte zu schreiben.
Google ist dein Freund, suche nach einem Beispiel.
quelle
Hallo Leute, ich habe so etwas gemacht. Für N-ten Tiefenkopierordner und zu kopierende Dateien. Damit können Sie die gesamte Verzeichnisstruktur kopieren, um sie von Android AssetManager zu kopieren :)
Am Ende Erstellen Sie eine Asynctask:
Nennen Sie es Von Ihrer Aktivität:
quelle
Leichte Änderung der obigen Antwort, um einen Ordner rekursiv zu kopieren und ein benutzerdefiniertes Ziel zu berücksichtigen.
quelle
Basierend auf der Lösung von Rohith Nandakumar habe ich selbst etwas unternommen, um Dateien aus einem Unterordner von Assets (dh "Assets / MyFolder ") zu kopieren . Außerdem überprüfe ich, ob die Datei bereits auf der SD-Karte vorhanden ist, bevor ich erneut versuche, sie zu kopieren.
quelle
Dies ist bei weitem die beste Lösung, die ich im Internet finden konnte. Ich habe den folgenden Link verwendet: https://gist.github.com/mhasby/026f02b33fcc4207b302a60645f6e217 ,
aber es gab einen einzelnen Fehler, den ich behoben habe, und dann funktioniert es wie ein Zauber. Hier ist mein Code. Sie können es leicht verwenden, da es sich um eine unabhängige Java-Klasse handelt.
Wie Sie sehen können, erstellen Sie einfach eine Instanz von
CopyAssets
in Ihrer Java-Klasse, die eine Aktivität hat. Nun ist dieser Teil wichtig für meine Tests und Recherchen im InternetYou cannot use AssetManager if the class has no activity
. Es hat etwas mit dem Kontext der Java-Klasse zu tun.Dies
c.copyAssets(getApplicationContext())
ist eine einfache Möglichkeit, auf die Methode zuzugreifen, woc
sich eine Instanz derCopyAssets
Klasse befindet. Gemäß meiner Anforderung erlaubte ich dem Programm, alle meine Ressourcendateien imasset
Ordner in das/www/resources/
Verzeichnis meines internen Verzeichnisses zu kopieren .Sie können leicht herausfinden, wo Sie gemäß Ihrer Verwendung Änderungen am Verzeichnis vornehmen müssen. Sie können mich gerne anrufen, wenn Sie Hilfe benötigen.
quelle
Für diejenigen, die auf Kotlin aktualisieren:
Befolgen Sie diese Schritte, um zu vermeiden
FileUriExposedExceptions
, dass der Benutzer die BerechtigungWRITE_EXTERNAL_STORAGE
erteilt hat und sich Ihre Datei in befindetassets/pdfs/mypdf.pdf
.quelle