我正在通过线程将文件(大约100-2000个文件,每个大小为100-200KB)从一个文件夹移动到另一个文件夹。一切都很顺利,但在一些三星&;sd卡的LG设备,在复制后突然全部或部分丢失。
这不是每次都发生,但大约每20次发生一次。
到目前为止,我已经尝试了3种方法:
public void copyMethodA(File src, File dst){
if(!dst.exists()){
src.renameTo(dst);
}
}
copyMethodA ();在大多数情况下导致文件丢失。
public void copyMethodB(File sourceFile, File destFile) throws IOException {
if (!destFile.exists()) {
destFile.createNewFile();
}
try {
FileChannel source = new FileInputStream(sourceFile).getChannel();
FileChannel destination = new FileOutputStream(destFile).getChannel();
destination.transferFrom(source, 0, source.size());
} finally {
source.close();
destination.close();
}
}
copyMethodB ();导致文件丢失的次数相对少于A.
public void copyMethodC(File src, File dst) throws IOException {
InputStream in = new FileInputStream(src);
OutputStream out = new FileOutputStream(dst);
byte[] buf = new byte[10240];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
out.close();
}
copyMethodC ();很少导致文件丢失。因此当前使用这个。
在Xperia C上,所有3种方法都工作得很好,没有任何文件丢失;Nexus 5(都使用内部存储)但在LG Optimus One(使用sd卡)和一些三星设备(使用内部或sd卡)上观察到文件丢失
我测试过的设备信息:
- Nexus 5 - Android 4.4.2 Xperia C - Android 4.2.2LG Optimus One - Android 2.3.3
- 三星设备- Android 4.0及以上
(我猜这个问题与使用的Android版本无关)
我避免使用巨大的第三方文件IO API,因为我的Android应用程序的大小只有300KB。使用API,如Apache commons。io将把它膨胀到2.5MB左右
有没有其他安全、可靠的&如何更好地复制文件?
谢谢。
我认为你应该这样写:
-
您应该检查
renameTo
的返回值,因为,正如javadoc所述,有许多原因导致它失败。 -
如果
renameTo
调用失败,使用第三种方法,在读取/写入流时使用try/catch块捕获IOException,并确保只有在复制成功时才删除源文件。然后,您可以检查异常以了解复制失败的原因,并可能稍后重试。
我这样做(与1024字节的缓冲区,就像在@beni回答)复制几百个文件,我从来没有看到任何损失。
我正在使用这个函数并且总是有效。我在Nexus 5上测试了这段代码。in.read(buf)方法在位于文件末尾时返回-1,在其他情况下返回已读取的字节数。所以,试试这个
public static 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);
}
}