Android FileOutputStream会创建损坏的文件

时间:2011-03-23 02:53:10

标签: java android fileoutputstream

我有一个应用程序,它使用从Socket InputStream获取的字节数组创建多个文件。当我只保存一个文件时,文件保存完美,但如果我保存一个文件然后重新实例化文件流并保存另一个文件,则第一个文件被破坏,第二个文件被完美保存。我在文本编辑器中打开了两个文件,似乎(约......)第一个文件的前1/5是空格但第二个文件已满,它们都具有相同的大小属性(9,128,731字节)。以下示例是senario的重复,但具有相同的损坏结果:

FileOutputStream outStream;
outStream = new FileOutputStream("/mnt/sdcard/testmp3.mp3");
File file = new File("/mnt/sdcard/test.mp3");
FileInputStream inStream = new FileInputStream(file);
byte[] buffer = new byte[9128731];
inStream.read(buffer);
outStream.write(buffer, 0, buffer.length);
inStream.close();
outStream.flush();
outStream.close();
outStream = null;
outStream = new FileOutputStream("/mnt/sdcard/testmp32.mp3");
outStream.write(buffer, 0, buffer.length);
inStream.close();
outStream.flush();
outStream.close();
outStream = null;

我在常规Java应用程序中尝试了这个EXACT代码,并且两个文件都保存没有问题。有谁知道为什么android会这样做?

任何帮助都会非常感激

4 个答案:

答案 0 :(得分:5)

正如jtahlborn所提到的,你不能假设InputStream.read(byte[])将始终读取你想要的字节数。同样,你应该避免使用这么大的字节数组一次写出来。至少没有缓冲,你可能会溢出一些东西。您可以通过复制文件来处理这些问题并节省一些内存:

File inFile = new File("/mnt/sdcard/test.mp3");
File outFile = new File("/mnt/sdcard/testmp3.mp3");
FileInputStream inStream = new FileInputStream(inFile);
FileOutputStream outStream = new FileOutputStream(outFile);
byte[] buffer = new byte[65536];
int len;
while ((len = inStream.read(buffer)) != -1) {
    outStream.write(buffer, 0, len);
}
inStream.close();
outStream.close();

答案 1 :(得分:1)

我看到一些可能让您开始调试的潜在问题:

  1. 在关闭输入流之前写入第一个输出流。这有点奇怪。

  2. 您无法使用文本编辑器准确地衡量两个二进制文件之间的相似性/差异。您需要在十六进制编辑器中查看文件(或更好,Audacity

  3. 我会按照Android文档的建议使用BufferedOutputStreamout = new BufferedOutputStream(new FileOutputStream(file)); http://developer.android.com/reference/java/io/FileOutputStream.html

  4. 作为调试技术,在第一次写入后打印buffer的内容。此外,inStream.read()会返回int。我还要将其与buffer.length进行比较,并确保它们是相同的。无论如何,除非你有充分的理由,否则我只会致电write(buffer)而不是write(buffer, 0, buffer.length)

  5. -tjw

答案 2 :(得分:0)

您假设read()调用将读取所需的字节数。这是不正确的。该方法可以自由地从1读取到buffer.length个字节。这就是为什么总是使用返回值来确定实际读取的字节数的原因。有很多流教程可以向您展示如何正确读取java流(即如何完全填充缓冲区)。

答案 3 :(得分:0)

如果有人遇到同样的问题,并想知道如何修复它,我发现问题是由我的SD卡引起的。我买了一张32gb的金士顿SD卡,就在昨天我决定尝试再次运行相同的代码,接受使用内部存储,而且一切都运行良好。我也试过它附带的2gb SD卡,它也很完美。我很高兴知道我的代码工作得很好但有点沮丧我在有缺陷的存储卡上花了50美元。感谢大家的投入。