Java的。从BufferedInputStream读取并写入FileOutputStream

时间:2013-09-13 06:31:21

标签: java client fileoutputstream bufferedinputstream

我正在尝试在java上编写客户端和服务器端。服务器端正常(在多个客户端上检查)。

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

我找到了2个问题的决定:

  1. 读到bytearray直到文件结尾(但我不知道文件末尾的位置)
  2. BufferedInputStream阅读FileInputStream,但不起作用:
  3. 我实际上需要接收标头和文件。输出标题到控制台并将文件写入光盘。

    完整来源

    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();
        }
      }
    }
    

    服务器端来源:

        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();
    

3 个答案:

答案 0 :(得分:4)

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

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

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

答案 1 :(得分:3)

不是答案,而是建议......

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

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

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

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

将字节数组写入读取的字节数...

接下来的问题是,你需要一些方法知道你何时到达文件的末尾。

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

现在,因为我是一名UI开发人员,我想知道我正在下载多少。那么,第一个然后你可以向下发送流是预期的字节数,然后你可以简单地保持读取的字节数,并在达到你的限制时停止......

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

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

然后你只需循环直到你有所需的字节数......

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.

我为screen sharing question

做了类似的事情

答案 2 :(得分:1)

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

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

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