简体   繁体   English

读取InputStream并写入文件

[英]Read InputStream and Write to a File

This is related to my previous question - DataInputStream giving java.io.EOFException 这与我之前的问题-DataInputStream提供java.io.EOFException有关

In that Client-Server app there is method to retrieve file sent from server and save to a file. 在该客户端-服务器应用程序中,有一种方法可以检索从服务器发送的文件并将其保存到文件中。

Client.java - Client.java-

 public void receiveFile(InputStream is, String fileName) throws Exception {
        int filesize = 6022386;
        int bytesRead;
        int current = 0;
        byte[] mybytearray = new byte[filesize];

        System.out.println("Receving File!");
        FileOutputStream fos = new FileOutputStream("RECEIVED_"+fileName);
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        bytesRead = is.read(mybytearray, 0, mybytearray.length);
        current = bytesRead; 
        System.out.println(bytesRead);
        do {
            bytesRead = is.read(mybytearray, current,
                    (mybytearray.length - current));
            System.out.println(bytesRead);
            if (bytesRead >= 0)
                current += bytesRead;
        } while (bytesRead > -1);
        System.out.println("Loop done");
        bos.write(mybytearray, 0, current);
        bos.flush();
        bos.close();
    }
}

Server.Java Server.Java

public void sendFile(OutputStream os, String fileName) throws Exception {
    File myFile = new File(fileName);
    byte[] mybytearray = new byte[(int) myFile.length() + 1];
    FileInputStream fis = new FileInputStream(myFile);
    BufferedInputStream bis = new BufferedInputStream(fis);
    bis.read(mybytearray, 0, mybytearray.length);
    System.out.println("Sending File!");
    os.write(mybytearray, 0, mybytearray.length);
    os.flush();
    bis.close();
}

As you can see there are several stranded outs in client's receiveFile method. 如您所见,客户端的receiveFile方法中存在多个receiveFile here is the output i received. 这是我收到的输出。

在此处输入图片说明

The issue is that method don't complete its task and never reached to System.out.println("Loop done"); 问题在于该方法无法完成其任务,并且永远不会到达System.out.println("Loop done");

What's the issue ? 有什么问题?

I'll come to the loop error later. 稍后我将介绍循环错误。

There is one little byte too much at the source: 源头有一个小字节太多:

public void sendFile(OutputStream os, String fileName) throws Exception {
    File myFile = new File(fileName);
    if (myFile.length() > Integer.MAX_VALUE) {
        throw new IllegalStateException();
    }

Either

    byte[] mybytearray = Files.readAllBytes(myFile.toPath());

Or 要么

    byte[] mybytearray = new byte[(int) myFile.length()]; // No +1.
    // BufferedInputStream here not needed.
    try (BufferedInputStream bis = new BufferedInputStream(
            new FileInputStream(myFile))) {
        bis.read(mybytearray);
    } // Always closed.

and then 接着

    System.out.println("Sending File!");
    os.write(mybytearray);
    os.flush();
}

Alternatively I have added the java 7 Files.readAllBytes . 另外,我添加了java 7 Files.readAllBytes It could even be simpler using Files.copy . 使用Files.copy甚至可能更简单。

I just see the main error is mentioned already. 我只是看到已经提到了主要错误。 Basically there is a misconception: you may read a byte array in its entirety. 基本上有一个误解:您可能会完整读取一个字节数组。 It will block till the end is read. 它将阻塞直到读完结尾。 If there is less to read ("end-of-file" reached), then the number of bytes is returned. 如果要读取的内容更少(达到“文件尾”),则返回字节数。 So to all purposes you might read it in a whole. 因此,出于所有目的,您可能会完整阅读它。

One often sees similar code to read a fixed size (power of 2) block (say 4096) repeated and written to the output stream. 人们经常看到类似的代码来读取固定大小(为2的幂)的块(例如4096)重复并写入输出流。

Again java 7 Files simplifies all: 同样,java 7 Files简化了所有操作:

    Files.copy(is, Paths.get("RECEIVED_" + fileName));

In Short: 简而言之:

public void receiveFile(InputStream is, String fileName) throws Exception {
    Files.copy(is, Paths.get("RECEIVED_" + fileName),
        StandardCopyOption.REPLACE_EXISTING);
}

public void sendFile(OutputStream os, String fileName) throws Exception {
    Files.copy(Paths.get(fileName), os);
}

You probably want your condition to read: 您可能希望您的条件显示为:

} while (bytesRead > -1 && current < mybytearray.length);
//                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

At the moment, when you have read the entire file, your read statement keeps reading zero bytes ( mybytearray.length - current ) which succeeds and returns zero, so your loop never terminates. 目前,当您读取了整个文件时,您的read语句将继续读取零字节( mybytearray.length - current ),该字节成功并返回零,因此循环永远不会终止。

It would be much simpler to not keep appending to the input buffer 不保持附加到输入缓冲区会更简单

public void receiveFile(InputStream istream, String fileName) throws Exception {
  System.err.println("Receving File!");
  try (BufferedOutputStream ostream = new BufferedOutputStream(
      new FileOutputStream("RECEIVED_" + fileName))) {
    int bytesRead;
    byte[] mybytearray = new byte[1024];

    do { 
      bytesRead = istream.read(mybytearray);
      if (bytesRead > 0) {
        ostream.write(mybytearray, 0, bytesRead);
      }
    } while (bytesRead != -1);
    System.err.println("Loop done");
    ostream.flush();
  }
}

If you can use Guava, you can use ByteStreams.copy(java.io.InputStream, java.io.OutputStream) ( Javadoc ) 如果可以使用Guava,则可以使用ByteStreams.copy(java.io.InputStream, java.io.OutputStream)Javadoc

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM