使用datainput / -outputstream在java套接字上发送jpg-image的问题

时间:2014-10-15 02:04:52

标签: java sockets file-io iostream bufferedimage

我希望通过TCP套接字连接从客户端向服务器发送JPG图像。我将文件转换为客户端中的字节数组,然后在发送数组长度后将其发送到服务器。服务器一次一个字节地从socketinputstream读取数据到新的bytearray,然后将其写入jpg文件。但是数据已损坏,无法查看此图像。下面是客户端和服务器的核心Java代码。

客户端:

Socket s = new Socket("localhost", 666);
DataOutputStream dos = new DataOutputStream(s.getOutputStream());
String imgPath = "C:/Users/huehuehue/Documents/Uni/D0036D/prick1.JPG";
File file = new File(imgPath);
byte[] b = new byte[(int) file.length()];
FileInputStream fis = new FileInputStream(file);
fis.read(b);
fis.close();
dos.writeInt((int) file.length());
dos.flush();
dos.write(b, 0, b.length);
dos.flush();

服务器:

ServerSocket serverSocket = new ServerSocket(666);
Socket connect = serverSocket.accept();
DataInputStream dis = new DataInputStream(connect.getInputStream());
File file = new File("C:/Users/huehuehue/Documents/Uni/D0036D/PLAYERprick.JPG");
FileOutputStream fos = new FileOutputStream(file);
int arrlen = dis.readInt();
byte[] b = new byte[arrlen];
int i = 0;
for(i = 0; i < arrlen; i++) {
    b[i] = dis.readByte();
    i++;
}
fos.write(b, 0 , b.length);

我无法理解为什么这不起作用,我们非常感谢任何帮助或建议。

2 个答案:

答案 0 :(得分:1)

int arrlen = dis.readInt();
byte[] b = new byte[arrlen];
int i = 0;
for(i = 0; i < arrlen; i++) {
    b[i] = dis.readByte();
    i++;
}

您将i递增两次,以便忽略输入的一半,并将您不会忽略的内容写入错误的广告位。幸运的是,有一种更简单的方法,也更有效:

int arrlen = dis.readInt();
byte[] b = new byte[arrlen];
dis.readFully(b);

NB fis.read(b);无效。你不能假设它填充了缓冲区。你也应该在这里使用DataInputStream.readFully()

答案 1 :(得分:0)

您需要匹配套接字的两端,而您的客户端并未完全填充byte[];相反,您的客户端可以在读取时发送每个字节。而且,由于Java提供BufferedInputStream,您不必直接手动使用和调整byte[]缓冲区。相反,你可以做类似的事情,

Socket s = new Socket("localhost", 666);
String imgPath = "C:/Users/huehuehue/Documents/Uni/D0036D/prick1.JPG";
File file = new File(imgPath);
try (InputStream is = new BufferedInputStream(new FileInputStream(file));
        DataOutputStream dos = new DataOutputStream(s.getOutputStream());) {
    dos.writeLong(file.length()); // <-- remember to read a long on server.
    int val;
    while ((val = is.read()) != -1) {
        dos.write(val);
    }
    dos.flush();
}

此外,您的服务器可以使用类似的BufferedOutputStream来获得像

这样的缓冲区的好处
ServerSocket serverSocket = new ServerSocket(666);
File file = new File("C:/Users/huehuehue/Documents/Uni/D0036D/PLAYERprick.JPG");
try (Socket s = serverSocket.accept();
        DataInputStream dis = new DataInputStream(
                s.getInputStream());
        OutputStream fos = new BufferedOutputStream(
                new FileOutputStream(file));) {
    long arrlen = dis.readLong();
    for (long i = 0; i < arrlen; i++) {
        fos.write(dis.read());
    }
    fos.flush();
}

无需手动管理。请注意,上面使用BufferedInputStreamBufferedOutputStream来管理缓冲作为优化。您可以删除它们并直接从File流进行读写。