将图像作为字节数组传输

时间:2012-06-12 05:01:45

标签: java android image sockets bytearray

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

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

    1. 客户端在图像传输后不会停止读取(读取时我没有得到-1),它会在套接字关闭时停止;
    2. 读完后,输入流不会被清除,一遍又一遍地读取相同的图像。
    3. 起初我尝试发送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个图像的bytearray)不断阅读第一张图片。

      任何想法我做错了什么?

      P.S。如果图像不是BMP,我在客户端代码中编写的解码会起作用吗?我要发送的真实图像是PNG。

5 个答案:

答案 0 :(得分:0)

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

一个简单的修复方法是使用一个固定长度(四个字节,一个int就足以满足大多数图像)的标头,你写入流,告诉客户端下列数据的长度。然后,客户端在停止并等待其他标头或关闭流之前从流中读取该字节数。

另一种方法是使用文件结束分隔符来通知客户端已经遇到输入结束。

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

答案 1 :(得分:0)

只查看了您的客户端代码,但这不符合评论。你需要重新思考你在做什么;你的想法(我在我的第一次尝试时做同样的事情)是基于人的而不是基于计算机的。换句话说,你的代码对人类来说是 me 是有意义的,但我真的不知道为什么,这对计算机来说没有意义。

要点:你的while (true)循环没有退出 - 它是无限的。我希望它能重复上次读到“位图”。

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

最后,您需要一个文件结束或图像结束标记来帮助您摆脱while (true)循环。 (回到“主要观点”。)

答案 2 :(得分:0)

嗨,但如果您想阅读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格式

答案 3 :(得分:0)

你可以先发送图像字节数组的大小,然后在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();

this is an edited version of this

注意图像的大小是int并且它有多个字节,那么你需要使用writeint。

答案 4 :(得分:-1)

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