Java 爪哇。从 BufferedInputStream 读取并写入 FileOutputStream

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18779654/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 10:59:17  来源:igfitidea点击:

Java. Reading from BufferedInputStream and write to FileOutputStream

javaclientfileoutputstreambufferedinputstream

提问by sanatik

I'm trying to write client and server side on java. Server side is ok (checked on several clients).

我正在尝试在 Java 上编写客户端和服务器端。服务器端没问题(在几个客户端上检查)。

So, the problem is on client side. I allocate memory for bytearray, read from BufferedInputStreamand write to that bytearray. Then writing from bytearrayto FileOutputStream. Everything is ok but free space of bytearrayis filling by NULLs, so received file is not correct(e.g. images).

所以,问题出在客户端。我为 分配内存bytearray,从中读取BufferedInputStream和写入bytearray。然后从写入bytearray到 FileOutputStream。一切正常,但可用空间bytearray被 NULL 填充,因此接收到的文件不正确(例如图像)。

I found 2 decision of that problem:

我发现了该问题的 2 个决定:

  1. Read to bytearraytill the end of file(but I don't know where the end of file)
  2. Read from BufferedInputStreamto FileInputStream, but it doesn't work:
  1. 读到bytearray文件结尾(但我不知道文件结尾在哪里)
  2. BufferedInputStreamto读取FileInputStream,但它不起作用:

I actually need receive header and file. Output header to console and write the file to the disc.

我实际上需要接收头文件和文件。输出头到控制台并将文件写入光盘。

Full Source

完整来源

public class SClient {
private static int bufferSize = 8192;
/**
 * @param args the command line arguments
 */
public static void main(String[] args) {
    System.out.println("Enter the address:");
    BufferedReader bufferRead = new BufferedReader
                (new InputStreamReader(System.in));

    try {
        String address = bufferRead.readLine();
        System.out.println("Enter the extention of receiving file:");
        String fileExt = bufferRead.readLine();
        // TODO code application logic here
        Socket socket = new Socket(address,4040);
        BufferedInputStream bis = new BufferedInputStream
                (socket.getInputStream());

        BufferedOutputStream bout = new BufferedOutputStream
                (socket.getOutputStream());
        System.out.println("Enter the request:");
        String message = bufferRead.readLine();// GET /index.html HTTP/1.0

        System.out.println("Header read");
        if(message!=null){
            bout.write(message.getBytes());
        }
        FileOutputStream fout = new FileOutputStream("out"+fileExt);
        String s1 = "\r\n\r\n";
        bout.write(s1.getBytes());
        bout.flush();
        System.out.println("Header sent");

        byte[] res = new byte[bufferSize];
        int got;
        while((got = bis.read(res))!=-1){
            fout.write(res,0,got);
        }
        fout.close();
        bout.flush();
        socket.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
  }
}

Server side source:

服务器端源码:

    String endLine = "\r\n";
    File f = new File(fileName);
    FileInputStream fstream;
    fstream = new FileInputStream(f);
    response = "HTTP/1.0 200 OK" + endLine;
    header = "Content-type: "+ contentType + endLine + "Content-length: " + f.length() + endLine + endLine;
    bout.write(response.getBytes());
    bout.write(header.getBytes());
    while(fstream.read(buffer) != -1) {
        bout.write(buffer);
    }
    System.out.println("Message sent");
    bout.flush();
    socket.close();

采纳答案by Matthias

You have to remember the amount of bytes you read into your buffer and must only write those bytes back. Like this here:

您必须记住读入缓冲区的字节数,并且只能将这些字节写回。像这里这样:

int got;
while ((got = bis.read(res)) != -1) {

    fout.write(res, 0, got);
}

回答by user207421

Memorize the canonical way to copy streams in Java:

记住在 Java 中复制流的规范方法:

while ((count = in.read(buffer)) > 0)
{
    out.write(buffer, 0, count);
}

Use any buffer size greater than zero, typically 4k or 8k.

使用任何大于零的缓冲区大小,通常为 4k 或 8k。

回答by MadProgrammer

Not the answer, but a suggestion...

不是答案,而是建议……

This doesn't look right. Basically, you are reading a an array of bytes up to a maximum of bufferSize, but then just writing a single byteto the output stream. You are also risking an index out of bounds error because you are incrementing the ion each loop unbound...

这看起来不对。基本上,您正在读取一个最多为 的字节数组bufferSize,然后只将一个字节写入byte输出流。您还冒着索引越界错误的风险,因为您正在增加i每个未绑定的循环......

while (bis.read(res) != -1) {
    fout.write(res[i]);
    i++;
}

Instead you should be using something more like...

相反,你应该使用更像......

int bytesRead = -1;
while ((bytesRead = bis.read(res)) != -1) {
    fout.write(res, 0, bytesRead);
}

Which will write a the byte array up to the number of bytes read...

这将写入一个字节数组,直到读取的字节数...

The next problem is, you need some way to know when the you've reached the end of the file.

下一个问题是,您需要某种方式知道何时到达文件末尾。

Now, you can put in some kind of terminator character but that could, potentially, corrupt the output file.

现在,您可以放入某种终止符,但这可能会损坏输出文件。

Now, because I'm a UI developer, I like to know how much I'm downloading. So, the first then you could send down the stream is the number of bytes to expect, then you can simply keep a count of the bytes read and stop when you've reached your limit...

现在,因为我是一名 UI 开发人员,所以我想知道我下载了多少。因此,您可以向流中发送的第一个字节数是预期的字节数,然后您可以简单地记录读取的字节数并在达到限制时停止......

This would require a slight change to your server, it would need to be able to send a longvalue, indicating the size of the image (in bytes) to be read and a \n

这将需要对您的服务器稍作更改,它需要能够发送一个long值,指示要读取的图像的大小(以字节为单位)和\n

BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String header = br.readLine();
long expectedBytes = Long.parseLong(header);

Then you would simply loop until you have the required number of bytes...

然后您只需循环,直到您获得所需的字节数...

int bytesRead = 0;
int totalBytes = 0;
while (totalBytes < expectedBytes) {
    bytesRead = bis.read(res);
    fout.write(res, 0, bytesRead);
    totalBytes += expectedBytes;
}

// Flush and close your steams as required.

I did something simular for a screen sharing question

我为屏幕共享问题做了一些类似的事情