我正在尝试通过套接字将图像文件从服务器发送到客户端。 套接字以前用于从服务器向客户端发送一些字符串(带有缓冲的输入/输出流)。
问题是无法正确接收图像文件,“JPEG文件过早结束”错误。
服务器首先将文件大小发送到客户端,然后客户端创建该大小的byte [],并开始接收文件。
以下是代码:
服务器:
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
//Send file size
dos.writeInt((int) file.length());
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
byte[] fileBytes = new byte[bis.available()];
bis.read(fileBytes);
bis.close();
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
bos.write(fileBytes);
bos.flush();
客户端:
DataInputStream dis = new DataInputStream(socket.getInputStream());
//Receive file size
int size = dis.readInt();
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
byte[] fileBytes = new byte[size];
bis.read(fileBytes, 0, fileBytes.length);
更有趣的是,如果我让服务器在发送文件大小和写入字节[]之间休眠约2秒,那么图像就会被正确接收。我想知道服务器和客户端之间是否存在某种竞争条件
答案 0 :(得分:1)
请使用FileUtils
和IOUtils
检查commons-io。这应该会使工作变得更容易。
答案 1 :(得分:1)
错误很可能在这里:
byte[] fileBytes = new byte[bis.available()];
方法available
不会返回文件的大小。它可能只返回输入缓冲区的大小,该大小小于文件的大小。请参阅BufferedInputStream
中的方法的API文档。
此外,以下行中的read
无法保证一次性读取整个文件。它返回实际读取的字节数,可以小于您要求的字节数。在客户端代码中,您以相同的方式使用read
,而不实际检查它是否读取了所有数据。
答案 2 :(得分:0)
在Java中复制流的正确方法如下:
int count;
byte[] buffer = new byte[8192]; // more if you like, but over a network it won't make much difference
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
您的代码在几个点上无法在逻辑上匹配。
同样,available()不是确定文件大小或传入网络传输大小的有效方法 - 请参阅Javadoc。它几乎没有正确的用途,这些不是两个。