Java FileInputStream FileOutputStream差异在运行



谁能告诉我为什么1。跑错了吗?(返回码为0,但写入的文件只有原始文件的一半。

提前感谢!

public class FileCopyFisFos {
public static void main(String[] args) throws IOException {
FileInputStream fis = new FileInputStream("d:/Test1/OrigFile.MP4");
FileOutputStream fos = new FileOutputStream("d:/Test2/DestFile.mp4");
// 1. run
//        while (fis.read() != -1){
//            int len = fis.read();
//            fos.write(len);
//        }
// 2. run
//        int len;
//        while ((len = fis.read()) != -1){
//            fos.write(len);
//        }
fis.close();
fos.close();
}
}

FileInputStreamread()方法遵循以下逻辑:

读取一个字节的数据从这个输入流。如果没有可用的输入,该方法将阻塞。

因此将其返回值赋给一个变量,例如:

while((len = fis.read())!= -1) 

是避免数据字节刚刚从流中读取被遗忘,因为每个read()调用将被分配给您的len变量。


相反,这段代码绕过了流中每两个字节中的一个,因为在while条件下执行的read()从未被赋值给变量。因此,流在没有读取一半字节(分配给len)的情况下继续前进:

while (fis.read() != -1) {      // reads a byte of data (but not saved)
int len = fis.read();        // next byte of data saved
fos.write(len);              // possible -1 written here    
}

@aran和其他人已经指出了解决你问题的方法。

然而,还有更多的方面,所以我扩展了你的例子:

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileCopyFisFos {
public static void main(final String[] args) throws IOException {
final File src = new File("d:/Test1/OrigFile.MP4");
final File sink = new File("d:/Test2/DestFile.mp4");
{
final long startMS = System.currentTimeMillis();
final long bytesCopied = copyFileSimple(src, sink);
System.out.println("Simple copy transferred " + bytesCopied + " bytes in " + (System.currentTimeMillis() - startMS) + "ms");
}
{
final long startMS = System.currentTimeMillis();
final long bytesCopied = copyFileSimpleFaster(src, sink);
System.out.println("Simple+Fast copy transferred " + bytesCopied + " bytes in " + (System.currentTimeMillis() - startMS) + "ms");
}
{
final long startMS = System.currentTimeMillis();
final long bytesCopied = copyFileFast(src, sink);
System.out.println("Fast copy transferred " + bytesCopied + " bytes in " + (System.currentTimeMillis() - startMS) + "ms");
}
System.out.println("Test completed.");
}
static public long copyFileSimple(final File pSourceFile, final File pSinkFile) throws IOException {
try (
final FileInputStream fis = new FileInputStream(pSourceFile);
final FileOutputStream fos = new FileOutputStream(pSinkFile);) {
long totalBytesTransferred = 0;
while (true) {
final int readByte = fis.read();
if (readByte < 0) break;
fos.write(readByte);
++totalBytesTransferred;
}
return totalBytesTransferred;
}
}
static public long copyFileSimpleFaster(final File pSourceFile, final File pSinkFile) throws IOException {
try (
final FileInputStream fis = new FileInputStream(pSourceFile);
final FileOutputStream fos = new FileOutputStream(pSinkFile);
BufferedInputStream bis = new BufferedInputStream(fis);
BufferedOutputStream bos = new BufferedOutputStream(fos);) {
long totalBytesTransferred = 0;
while (true) {
final int readByte = bis.read();
if (readByte < 0) break;
bos.write(readByte);
++totalBytesTransferred;
}
return totalBytesTransferred;
}
}
static public long copyFileFast(final File pSourceFile, final File pSinkFile) throws IOException {
try (
final FileInputStream fis = new FileInputStream(pSourceFile);
final FileOutputStream fos = new FileOutputStream(pSinkFile);) {
long totalBytesTransferred = 0;
final byte[] buffer = new byte[20 * 1024];
while (true) {
final int bytesRead = fis.read(buffer);
if (bytesRead < 0) break;
fos.write(buffer, 0, bytesRead);
totalBytesTransferred += bytesRead;
}
return totalBytesTransferred;
}
}
}

随代码而来的提示:

  • 这是java。nio包通常做这些事情更快,代码更少。
  • 复制单个字节比批量复制慢1'000-40'000倍。使用try/resource/catch是避免保留/锁定资源(如文件等)问题的最好方法。
  • 如果你解决了一些很平常的事情,我建议你把它放在你自己的实用程序类中,甚至是你自己的库。
  • 有像BufferedInputStream和BufferedOutputStream这样的帮助类,可以极大地提高效率;查看示例copyFileSimpleFaster().
  • 但和往常一样,概念的质量对实施的影响最大;参见示例copyFileFast()。
  • 甚至还有更高级的概念(类似于java.nio),它考虑了操作系统缓存行为等概念,这将给性能带来另一个提升。

检查我的输出,或者自己运行它,看看性能的差异:

Simple copy transferred 1608799 bytes in 12709ms
Simple+Fast copy transferred 1608799 bytes in 51ms
Fast copy transferred 1608799 bytes in 4ms
Test completed.

最新更新