繁体   English   中英

将图像作为字节数组传输

[英]Transfer an image as byte array

我正在尝试从“服务器”发送图像,该服务器的目的是将图像发送到作为Android设备的“客户端”。 两者之间的插槽保持打开状态,并且图像不断出现。 问题是:

  1. 我不知道图像的大小(它可以改变);
  2. 图像不是BMP格式。

在下面的代码中:

  1. 传输图像后,客户端不会停止读取(读取时我不会收到-1 ),它将在套接字关闭时停止。
  2. 完成读取后,不会清除输入流,并且一次又一次地读取同一图像。

最初,我尝试发送2个我知道大小(均相同)的BMP图像。 这是服务器代码:

    public static void main(String[] args) {
        try {
            ServerSocket s = new ServerSocket(4488);
            System.out.println("Waiting for a connection . . . . ");
            Socket socket = s.accept();
            System.out.println("Connected!");
            DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
            Thread.sleep(2000);

            File myImageFile = new File("c:\\1\\a.bmp");
            FileInputStream fis = new FileInputStream(myImageFile);
            byte[] data = new byte[(int) myImageFile.length()];
            byte[] tmp = new byte[0];
            byte[] myArrayImage = new byte[0];
            int len = 0 ;
            int total = 0;

            while( (len = fis.read(data)) != -1 ) {
                total += len;
                tmp = myArrayImage;
                myArrayImage = new byte[total];
                System.arraycopy(tmp,0,myArrayImage,0,tmp.length);
                System.arraycopy(data,0,myArrayImage,tmp.length,len);
            }

            //

            fis.close();

            dataOutputStream.write(myArrayImage);
            dataOutputStream.flush();
            Thread.sleep(2000);

            myImageFile = new File("c:\\1\\b.bmp");
            fis = new FileInputStream(myImageFile);
            data = new byte[(int) myImageFile.length()];
            tmp = new byte[0];
            myArrayImage = new byte[0];
            len = 0 ;
            total = 0;

            while( (len = fis.read(data)) != -1 ) {
                total += len;
                tmp = myArrayImage;
                myArrayImage = new byte[total];
                System.arraycopy(tmp,0,myArrayImage,0,tmp.length);
                System.arraycopy(data,0,myArrayImage,tmp.length,len);
            }

            fis.close();

            dataOutputStream.write(myArrayImage);
            dataOutputStream.flush();
            Thread.sleep(2000);

            socket.close();
            s.close();

这是客户端代码:

    @Override
public void run() {
    ByteArrayOutputStream buffer = new ByteArrayOutputStream();
    byte[] byteChunk = null;
    int c;

    if (_dataInputStream != null) {
        while (true) {
            try {
                Thread.sleep(200);
            } catch (Exception e) {
            }

            try {
                byteChunk = new byte[1024];

                while ((c = _dataInputStream.read(byteChunk)) != -1){
                    buffer.write(byteChunk, 0, byteChunk.length);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }



            final Bitmap bitmap = BitmapFactory.decodeByteArray(buffer.toByteArray(), 0, buffer.size());

            if (bitmap != null) {
                _handler.post(new Runnable() {
                    public void run() {
                        _iv.setImageBitmap(bitmap);
                        _iv.invalidate();
                    }
                }); 
            }

                buffer.reset();
        }
    }
}

现在,正如我所说,客户端一直停留在while循环中,直到套接字关闭为止,然后(无论我发送多少图像,因为我在客户端创建了仅适合1个图像的字节数组),它一直在读取一直都是第一张图片。

有什么想法我做错了吗?

Ps如果图像不是BMP,我在客户端代码中编写的解码是否可以工作? 我要发送的真实图像是PNG。

除非使用某种机制指示输入结束,否则客户端无法知道何时停止从流中读取。

一个简单的解决方法是使用固定长度(四个字节,一个int可以满足大多数图像)的标头,该标头写入流中,该值告诉客户端以下数据的长度。 然后,客户端从流中读取该字节数,然后停止并等待另一个报头或关闭流。

另一种方法是使用文件结尾定界符来通知客户端已遇到输入结尾。

除非在输入后关闭流,否则您将不得不在流中除了图像本身之外还要写入一些其他数据(元数据)。

只查看了您的客户端代码,但这不适合注释。 您需要重新考虑自己在做什么; 您的想法( 第一次尝试做的是相同的事情)是基于人的而非基于计算机的。 换句话说,您的代码对 (人类) 来说是有意义的,但是我真的不知道为什么,并且对计算机也没有意义。

要点: while (true)循环没有退出-它是无限的。 我希望它会重复重复最后一次读入“位图”的操作。

首先,我要摆脱sleep代码。 现在,这个问题令人困惑,如果有帮助,您可以稍后再放回去。 (我认为不会,您的读取将完成所有必要的阻塞操作。)然后,当读取完完整的图像后,您需要一个图像结束标记或某些东西来使您脱离读取循环。 (或者让它触发放置此循环内的图像处理代码。)

最后,您需要一个文件结尾或图像结尾标记来将您踢出while (true)循环。 (返回到“要点”。)

嗨,但是,如果您想读取jpeg文件,则可以使用此代码

byte[] bytes = new byte[1024 * 1024];
int count = 0;
do
{
    count += in.read(bytes, count, bytes.length - count);
}while (!(count > 4 && bytes[count - 2] == (byte) -1 && bytes[count - 1] == (byte) -39));

但我不明白如何读取PNG格式

您可以先发送图像字节数组的大小,然后在while循环中读取字节,直到达到如下大小:

DataInputStream in = conn.openDataInputStream();

            // read a length first
            int length = in.readInt();


            if (length <= 0) {
                throw new IOException("Can't read a length");
            }

            // read the image now
            imgData = new byte[length];
            length = 0;

            while (length != imgData.length) {
                int n = in.read(imgData, length, imgData.length - length);

                if (n == -1) {
                    throw new IOException("Can't read a image data");
                }

                length += n;
            }

            in.close();

这是这个的编辑版本

请注意,图像的大小为int且具有多个字节,那么您需要使用writeint。

如果要发送PNG,请阅读有关格式的一些信息( Wiki )。 每个块都有前缀长度,因此您可以通过网络将其原始发送,并知道何时完成!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM