当前位置: 首页 > 知识库问答 >
问题:

While循环在文件下载后不退出

胡景澄
2023-03-14

我有以下代码来下载通过TCP传输的文件:

        try (OutputStream out = new FileOutputStream(path); InputStream is = socket.getInputStream();) {
            byte[] bytes = new byte[1024];
            int count, xp = 0;
            while ((count = is.read(bytes)) > 0) {      // TODO after upload the service doesn't leave while loop
                out.write(bytes, 0, count);
            }
            System.out.println("hello");
         ...
if (ready.equalsIgnoreCase(CdnResponse.READY.getContext())){
    int read = 0;
    byte[] bytes = new byte[1024];
    while ((read = inputStream.read(bytes)) != -1) {
        out.write(bytes, 0, read);
    }

}

一旦所有的字节都被处理了(它们总是被处理的,它像正常的一样工作,只是不退出循环),文件就被创建了,没有一个问题,但是,循环没有退出。

共有1个答案

商夜洛
2023-03-14

TCP/IP连接被设计为长期流式连接(构建在无序、无保证、基于数据包的IP协议之上)。

这意味着is.read(bytes)完全按照规范的要求执行:它将等待至少一个字节可用,或者“流结束”信号进入。只要这两种情况都不发生(没有字节到达,但流没有关闭),它就会自动阻塞。如果有必要的话永远。

解决方法是[A]预先发送文件的大小,然后调整循环,使其只在收到该数量的字节后退出,或者[B]关闭流。

// upload side
void upload() {
  Path p = Paths.get("/path/to/file/you/want/to/send");
  long fileSize = Files.size(p);
  out.write(longToBytes(fileSize);
  try (InputStream in = Files.newInputStream(p)) {
    in.transferTo(out);
  }
}

public static byte[] longToBytes(long x) {
    ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
    buffer.putLong(x);
    return buffer.array();
}

此代码具有以下属性:

  • 它首先发送8个字节,按大字节顺序发送,这是将要发送的数据的大小。
  • 它使用新的java.nio.fileAPI。
  • 它在InputStream中使用了新的TransferTo方法,这避免了必须声明一个字节数组作为缓冲区的rigamarole和一个while循环。

然后在下载端:

void download() {
  long size = bytesToLong(in.readNBytes(8));
  Path p = Paths.get("/file/to/store/data/at");
  // Generally network transfer sizes are a bit higher than 1k;
  // up to 64k in fact. Best to declare a larger buffer!
  byte[] bb = new byte[65536];
  try (OutputStream out = Files.newOutputStream(p)) {
    while (size > 0) {
      int count = in.read(bb);
      if (count == -1) throw new IOException("Unexpected end of stream");
      out.write(bb, 0, count);
      size -= count;
    }
  }
}

public static long bytesToLong(byte[] bytes) {
    ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
    buffer.put(bytes);
    buffer.flip();//need flip 
    return buffer.getLong();
}
    null
  • 发送一个大小,以2字节的形式,按大字节顺序发送,不带符号。随后是许多字节,然后发送另一个大小,无限大。
  • 当流完成时,将发送大小为0的大小(因此,值为02个字节),这表示文件已完成。

如果您需要的话,我将把它作为一个练习,让您来实现上行和下载端。

 类似资料:
  • 问题内容: 在下面的代码中,我希望循环在+ + =时立即退出。但是,使用语句进行测试表明它一直持续到循环完成为止。我尝试过,然后在语句集中进行设置,但这会导致无限循环。我认为使用然后设置可能有效,但也可以一直运行到循环结束为止。什么是最优雅,最快的退出方式?谢谢。 问题答案: 该循环将只匹配条件时,当控制返回到它,即循环完全执行。因此,这就是即使满足条件也不会立即退出程序的原因。 但是,如果条件没

  • 出现的问题是,当用户确实输入了一个正数时,它仍然忽略输入,并要求用户再次输入一个正整数。我想我只是没有正确退出循环,但我不确定是如何退出的。

  • //在下面的程序中,在内部,当用户收到指令时,他可以简单地进入哨兵退出while循环,但是,当您得到希望购买的票的结果时,按999并不退出程序

  • 问题内容: 在Java中退出/终止while循环的最佳方法是什么? 例如,我的代码当前如下: 问题答案: 用途: 但是,如果您的代码看起来 完全 像您指定的那样,则可以使用普通循环并将条件更改为:

  • 所以我这里有一个程序,它只是简单地模仿跳棋(但不是跳,而是一个棋子简单地“吃掉”另一个棋子)。我有一个简单的类,它实现了一个“checkers”类对象,并创建了一个名为“chips”的int数组变量。还有一个“while”语句,它在chip[0]和chips[1]整数大于0时创建了一个循环。看起来是这样的: Checkers类中的count方法如下所示: 板是8 x 8(这就是board.leng

  • 问题内容: 我正在尝试通过按键盘上的键来使while循环中断。我的代码是: 问题答案: 请勿使用循环获取输入,或。您真正想要的是一行输入,然后将其拆分为一个双打列表。因此,请使用,拆分并解析每个项目。像这样: 这忽略了任何形式的输入验证,但显示了一种通用方法。 这将起作用,因为一旦您单击“ enter”(输入),它将结束第一行,这意味着扫描程序可以越过进入代码的大部分。由于您再也不会尝试阅读任何内