Je télécharge des fichiers depuis Internet et enregistre les données en streaming dans un fichier temporaire de la mémoire interne de mon application, fourni par getFilesDir () .
Une fois le téléchargement terminé, je dois déplacer le fichier temporaire dans le répertoire de téléchargement de la mémoire externe (généralement une carte SD). Pour une raison quelconque, File.renameTo () ne fonctionne pas pour cela. Je suppose qu'il y a un problème car il s'agit de deux systèmes de fichiers distincts, mais je peux toujours télécharger directement sur la carte SD et les URI de fichier sont corrects.
Existe-t-il un autre moyen simple et rapide de transférer ce fichier de la mémoire interne vers une mémoire externe ou dois-je copier un flux d'octets et supprimer l'original?
Pour copier des fichiers de la mémoire interne sur une carte SD et inversement, utilisez le code suivant:
public static void copyFile(File 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();
}
}
Et il fonctionne...
La mémoire interne et externe est deux systèmes de fichiers différents. Par conséquent, renameTo () échoue.
Vous devrez copier le fichier et supprimer l’original
Après avoir copié le fichier (comme le montre l'excellente réponse de @barmaley ), n'oubliez pas de l'exposer à la galerie de l'appareil, afin que l'utilisateur puisse l'afficher ultérieurement.
La raison pour laquelle cela doit être fait manuellement est que
Android exécute une analyse complète des médias uniquement au redémarrage et au (ré) montage la carte SD
(comme ce guide montre).
Le moyen le plus simple de le faire est d’envoyer une diffusion pour que le scan soit appelé:
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
intent.setData(Uri.fromFile(outputFile));
context.sendBroadcast(intent);
Et le tour est joué! Vous pouvez maintenant voir votre fichier dans la galerie de l'appareil.
Une alternative à la copie utilisant votre propre fonction consiste à utiliser la classe "FileUtils" de la bibliothèque Apache, dans la fonction appelée copyFile :
FileUtils.copyFile(src, dst, true);
Imaginez que:
Essayez avec ce code:
public void moveIn (String pathInternal, String pathExternal) {
File fInternal = new File (pathInternal);
File fExternal = new File (pathExternal);
if (fInternal.exists()) {
fInternal.renameTo(fExternal);
}
}
Vous pouvez le faire en utilisant des opérations avec byte []
définir dans votre classe:
public static final String DATA_PATH =
Environment.getExternalStorageDirectory().toString() + "/MyAppName/";
puis:
AssetManager assetManager = context.getAssets();
InputStream in = assetManager.open("data/file.txt");
OutputStream out = new FileOutputStream(DATA_PATH + "data/file.txt");
// Transfer bytes from in to out
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
out.close();
Quelques modifications triviales apportées au code de @ barmaley
public boolean copyFile(File src, File dst) {
boolean returnValue = true;
FileChannel inChannel = null, outChannel = null;
try {
inChannel = new FileInputStream(src).getChannel();
outChannel = new FileOutputStream(dst).getChannel();
} catch (FileNotFoundException fnfe) {
Log.d(logtag, "inChannel/outChannel FileNotFoundException");
fnfe.printStackTrace();
return false;
}
try {
inChannel.transferTo(0, inChannel.size(), outChannel);
} catch (IllegalArgumentException iae) {
Log.d(logtag, "TransferTo IllegalArgumentException");
iae.printStackTrace();
returnValue = false;
} catch (NonReadableChannelException nrce) {
Log.d(logtag, "TransferTo NonReadableChannelException");
nrce.printStackTrace();
returnValue = false;
} catch (NonWritableChannelException nwce) {
Log.d(logtag, "TransferTo NonWritableChannelException");
nwce.printStackTrace();
returnValue = false;
} catch (ClosedByInterruptException cie) {
Log.d(logtag, "TransferTo ClosedByInterruptException");
cie.printStackTrace();
returnValue = false;
} catch (AsynchronousCloseException ace) {
Log.d(logtag, "TransferTo AsynchronousCloseException");
ace.printStackTrace();
returnValue = false;
} catch (ClosedChannelException cce) {
Log.d(logtag, "TransferTo ClosedChannelException");
cce.printStackTrace();
returnValue = false;
} catch (IOException ioe) {
Log.d(logtag, "TransferTo IOException");
ioe.printStackTrace();
returnValue = false;
} finally {
if (inChannel != null)
try {
inChannel.close();
} catch (IOException e) {
e.printStackTrace();
}
if (outChannel != null)
try {
outChannel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return returnValue;
}