在java中通过套接字发送时,JPG图像被损坏或损坏

时间:2014-10-13 16:31:31

标签: java sockets io javax.imageio

我正在尝试通过套接字将JPEG图像从客户端发送到java中的服务器。我将图像写入File-object然后使用FileInputStream我将它读入Byte []数组,然后通过套接字发送数组。以下是客户的代码。

class TestingClient {
    Socket s;
    public TestingClient () {
        try {
            s = new Socket("localhost", 666);
        }catch (UnknownHostException e){
            e.printStackTrace();
        }catch (IOException e){
            e.printStackTrace();
        }
        String imgPath = "C:/Users/huehuehue/Documents/Uni/D0036D/prick1.JPG";
        File file = new File(imgPath);
        byte[] bFile = new byte[(int) file.length()];
        try {
            FileInputStream fin = new FileInputStream(file);
            fin.read(bFile);
            fin.close();
            OutputStream os = s.getOutputStream();
            os.write(bFile, 0, bFile.length);
            os.close();
            System.out.println();
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}

服务器将收到的字节写入两个单独的“.JPG”文件,然后将收到的字节读入缓冲图像,在将JLabel添加到简单JFrame时实例化JLabel时调用该缓冲图像。这些文件本身是通过Windows照片查看器无法查看的,这表明它们“无法打开此图片,因为文件似乎已损坏,损坏或太大”。当程序尝试使用缓冲的图像实例化JLabel时,抛出未处理的异常“java.lang.NullPointerException”。代码中的所有控制台消息都应该打印出来。下面是服务器的代码。

public class TestingServer {

    InetAddress serverAddr;
    BufferedImage img;

    private class frame extends JFrame {

        JLabel test;

        private class aspectRatio {
            int w = 16, h = 9;
        }

        public frame (BufferedImage y) {
            aspectRatio aR = new aspectRatio ();
            this.setVisible(true);
            this.setSize(50*aR.w, 50*aR.h);
            this.setTitle("TESTING");
            this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            this.setLayout(null);
            this.getContentPane().setBackground(Color.DARK_GRAY);

            this.add(test = new JLabel(new ImageIcon(y)));
            test.setBounds(25*aR.w, 13*aR.h, 15*aR.w, 10*aR.h);
        }

    }

    public TestingServer () {
        ServerSocket serverSocket;
        try {
            serverSocket = new ServerSocket(666);
            Socket connect = serverSocket.accept();

        System.out.println("So we read");
        InputStreamReader ir = new InputStreamReader(connect.getInputStream());
        FileOutputStream fos1 = new FileOutputStream(new File("C:/Users/huehuehue/Documents/Uni/D0036D/test1.JPG"));
        int c=0;
        while ((c = ir.read()) != -1) {
            fos1.write(ir.read());
        }
        fos1.close();
        System.out.println("finito1");

        FileOutputStream fos2 = new FileOutputStream(new File("C:/Users/huehuehue/Documents/Uni/D0036D/test2.JPG"));
        byte[] barr = new byte[34534];
        int i = 0;
        c = 0;
        while ((c = ir.read()) != -1) {
             barr[i] = (byte) c;
             i++;
        }
        fos2.write(barr,0,i+1);
        fos2.close();
        System.out.println("finito2");

        img = ImageIO.read(ImageIO.createImageInputStream(new ByteArrayInputStream(barr, 0, i)));
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("image buffered");

        frame f = new frame(img);

    }

}

我有点卡住了,感谢任何帮助或指导:)提前致谢!

1 个答案:

答案 0 :(得分:2)

您正在使用InputStreamReader,它尝试将图像的字节转换为字符。您应该直接使用InputStream,而无需使用Reader。或者最好使用BufferedInputStream

此外,在填充第二个文件时,您继续从输入流中读取,尽管它已经给出-1表示流的结束。相反,您应该在循环之前打开这两个文件,并将您从输入流中读取的字节写入两次 - 一次进入第一个文件,一次进入第二个文件。

另一个问题是你在循环内再次调用ir.read()(填充第一个文件)。这会丢弃您已读取的字节,并读取下一个字节。所以从本质上讲,你正在阅读每一个字节。

所以你需要做一些事情:

iStream = new BufferedInputStream(connect.getInputStream());

FileOutputStream fos1 = new FileOutputStream(new File("C:/Users/huehuehue/Documents/Uni/D0036D/test1.JPG"));
FileOutputStream fos2 = new FileOutputStream(new File("C:/Users/huehuehue/Documents/Uni/D0036D/test2.JPG"));
int c=0;
while ((c = iStream.read()) != -1) {
    fos1.write(c);
    fos2.write(c);
}
fos1.close();
fos2.close();
iStream.close();