试图覆盖文件会导致空白文件

时间:2013-12-30 18:53:47

标签: java android file

在我正在处理的应用程序中,部分功能是将保存在设备上的数据写入通过USB-OTG适配器连接的闪存驱动器。具体来说,该设备是运行4.2.2的有根据的Motorola Xoom。我可以成功地将文件写入驱动器并在我的计算机上读取它们。那部分工作正常。但是,当我尝试用新信息替换现有文件时,生成的文件为空。我甚至在写入新数据之前删除了现有文件。奇怪的是,在将我的内部文件的内容复制到闪存驱动器后,我记录了生成的文件的长度。它始终与输入文件匹配,并且始终为非0数字,但该文件在我的计算机上仍显示为空白。有人可以帮忙解决这个问题吗?我正在做这项工作的AsyncTask的相关代码如下。

@Override
protected Void doInBackground(Void... params) {

    File[] files = context.getFilesDir().listFiles();

    for (File file : files) {
        if (file.isFile()) {
            List<String> nameSegments = Arrays.asList(file.getName().split(
                    "_"));

            Log.d("source file", "size: " + file.length());

            String destinationPath = "/storage/usbdisk0/"
                    + nameSegments.get(0) + "/" + nameSegments.get(1) + "/";

            File destinationPathFile = new File(destinationPath);

            if (!destinationPathFile.mkdirs()) {
                destinationPathFile.mkdirs();
            }

            File destinationFile = new File(destinationPathFile,
                    nameSegments.get(2));

            FileReader fr = null;
            FileWriter fw = null;
            try {
                fr = new FileReader(file);
                fw = new FileWriter(destinationFile, false);
                int c = fr.read();
                while (c != -1) {
                    fw.write(c);
                    c = fr.read();
                }
                fw.flush();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    fr.close();
                    fw.close();
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
            Log.d("destination file", "size: " + new File(destinationFile.getPath()).length());
        }
    }
    return null;
}

编辑: 根据@ Simon的建议,我在代码中添加了output.flush()。这不会改变结果。

编辑#2:编辑#2: 我做了一些进一步测试,发现了一些有趣的东西。如果我在写入闪存驱动器之后但在将其从OTG适配器中移除之前进入设置 - >存储 - >卸载USB存储器,则一切正常。但是,写入后无法弹出驱动器会导致数据未被写入。奇怪的是,文件夹结构和文件本身是在驱动器上创建的,但文件始终为空。还有一件事:如果我在删除驱动器之前转到文件管理器应用程序并打开文件,那么这些文件都应该存在。但是,即使删除设备,将其直接插回平板电脑并打开任何文件也会导致文件显示为空。我不能对此做出正面或反面,这令人非常沮丧。任何人都可以帮忙吗?

编辑#3:编辑#3: 我还改为使用FileReaderFileWriter来改变将要发生的事情。我现在不关心效率,我只是希望文件写入能够可靠地工作。此更改不会影响此问题。更新的代码已在上面发布。

4 个答案:

答案 0 :(得分:0)

听起来文件系统正在缓存您的更改,但实际上并没有将它们写入闪存驱动器,直到您将其弹出。我认为没有办法刷新文件系统缓存,所以最好的解决方案似乎只是卸载然后重新安装闪存驱动器。

答案 1 :(得分:0)

在FileReader.read()调用之前尝试使用FileReader.ready()方法, 并确保你的FileReader确实有一些字节。

答案 2 :(得分:0)

试试这个,使用缓冲读写器进行编写

try
{
  fw = new FileWriter(destinationFile);
  BufferedWriter writer=new BufferedWriter(fw);
  writer.append(yourText); // Append can be changed to write or something if you want to overwrite
  writer.close();
} 
catch (Exception e) {
  throw new RuntimeException(e);
} 
finally {
  if (fw != null) {
try {
  fw.flush();
  fw.close();
} 
 catch (IOException e) {
}

答案 3 :(得分:0)

我找到了解决问题的方法。似乎Android系统从SD卡/闪存驱动器缓冲一些文件,然后在弹出时将它们写入闪存驱动器。我的文件操作之后的以下代码将缓冲区与文件系统同步,并允许立即从设备中删除闪存驱动器而不会丢失数据。值得注意的是,这个DOES需要root访问权限;它不适用于非root设备。

try {
    Process p = Runtime.getRuntime().exec("su");
    DataOutputStream os = new DataOutputStream(p.getOutputStream());
    os.writeBytes("sync; sync\n");
    os.writeBytes("exit\n");
    os.flush();
} catch (Exception e) {
    e.printStackTrace();
}

我的解决方案来源:Android 2.1 programatically unmount SDCard