【问题标题】:sending image from java server to android app将图像从 java 服务器发送到 android 应用程序
【发布时间】:2011-08-13 12:40:29
【问题描述】:

我想使用此代码将图像文件从 java 服务器发送到 android 应用程序:

服务器(Java):

File file = new File("./clique.jpg");

FileInputStream stream = new FileInputStream(file);

DataOutputStream writer = new DataOutputStream(socket.getOutputStream());        

byte[] contextB = new byte[4096];

int n;
int i = 0;
while ( (n=stream.read(contextB))!=-1 ){
    writer.write(contextB, 0, n);
    writer.flush();
    System.out.println(n);
    i+=n;
}
writer.flush();
stream.close();

安卓应用:

DataInputStream reader = new DataInputStream(socket.getInputStream());
            byte[] buffer = new byte[4096];
            ByteArrayOutputStream content = new ByteArrayOutputStream();

            int n;
            int i = 0;
            reader = new DataInputStream(socket.getInputStream());
            while ( (n=reader.read(buffer)) != null){                
                content.write(buffer, 0, n);
                content.flush();

            }

            Utility.CreateImageFile(content.toByteArray());

我注意到的是,在我从 4096 大小的服务器字节块发送时,在 android 应用程序 n 中读取字节数不是 4096,我也无法得到 n=-1,这是流的结尾,它会阻塞,直到我关闭应用程序然后我得到 n=-1。

【问题讨论】:

  • 请问你为什么做的这么复杂?您可以使用 http 来传输该文件,这非常简单。您应该在循环之后调用 writer.close() 而不是 writer.flush()。不接收确切的 4k 数据包应该没问题,因为您正在通过不支持大数据包的互联网传输。
  • 我也尝试了 128 个字节,它每次也传输 8 个字节
  • 我有没有提到,你真的应该使用 http?
  • 是的,但使用 http 不会使其流畅和迅速。是的,这种方式有点复杂,但很有效
  • 嗯,http 的开销在大多数情况下是可以的,而且它的扩展性更好。

标签: java android sockets


【解决方案1】:

关于您一次读取的字节数与您写入的字节数无关 - 它在很大程度上取决于网络条件,并且会随着每个块而变化(基本上与设法传输的字节数一样多)读取之间的短时间间隔,您将在读取块中获得尽可能多的时间。

关于流的结束 - 在您的服务器代码中,您忘记关闭输出流(您只关闭作为输入流的流 - 您还应该关闭编写器,这反过来将关闭底层输出流。

两个cmets:

1) 我真的建议使用缓冲读取器/写入器来包装写入/读取器 - 您将获得的代码会更好,您不必自己创建/管理缓冲区。

2) 使用 try {} finally 并在 finally 子句中关闭您的流 - 这是确保您关闭流并释放资源的最佳做法,即使在读/写时出现问题。

【讨论】:

  • 你能给我一个关于我的问题的读者作家的例子吗?这将是一个很大的帮助,非常感谢
  • 在服务器端关闭写入器根本不是解决方案,它会在 android 设备完成从写入器接收到所有数据之前关闭,因为服务器比 android 设备快。
  • 并非如此。您应该仍然可以读取未完成的数据...-1。
  • 真的不给我-1
【解决方案2】:

你的安卓代码有问题:

while ( (n=reader.read(buffer)) != null) {

n 不能为空。

在服务器上循环之后使用 writer.close() 而不是 writer.flush()。

【讨论】:

  • 很抱歉 while ( (n=reader.read(buffer)) != -1) { 不是我做错了,而是同样的问题。如果我关闭 writer,我的套接字将被关闭。我在 android 应用程序中得到的所有块都小于 4096
  • 通过关闭 writer 来关闭 socket 是否有效?由于网络延迟,您的 android 端循环可能会在所有数据传输之前在 .read() 上收到 -1,因为接收器缓冲区中没有数据(因为数据仍在路由到您的手机)。您应该为循环尝试另一种退出条件。
  • 我在服务器 sde 中的循环关闭并移至下一行但是在 android 应用程序中它根本没有收到 -1 并且它停止在应该完成它的最后一个块中,我的意思是在 android app 它错过了最后一个块然后得到 n = -1 来完成所有。通过关闭作者,我丢失了所有内容(客户端套接字,并丢失了路由上的其余数据)
猜你喜欢
  • 1970-01-01
  • 2015-10-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多