一个更好的Java循环?

cha*_*nce 4 java loops for-loop while-loop

我有一段代码来读取InputStream并将内容写入OutputStream:

BufferedInputStream in = new BufferedInputStream(...);
FileOutputStream outStream = new FileOutputStream outStream(...);

int read = in.read(buffer, 0, bufferSize);
while (read != -1) {
    outStream.write(buffer, 0, read);
    read = in.read(buffer, 0, bufferSize);
}
Run Code Online (Sandbox Code Playgroud)

它工作,但我不喜欢它,因为变量read是在循环之外声明的,并且read()方法被写入两次.修订版:

 for (int read = 0; read != -1; read = in.read(buffer, 0, bufferSize)) {
      outStream.write(buffer, 0, read);
 }
Run Code Online (Sandbox Code Playgroud)

它看起来更好但不够好,因为第一次迭代对于read = 0来说是无用的(也许是有害的).

你有更好的解决方案吗?

Jon*_*eet 10

就我个人而言,我打破这种事情的正常"无条件副作用"规则:

int bytesRead;
while ((bytesRead = in.read(buffer, 0, bufferSize)) != -1)
{
    outStream.write(buffer, 0, bytesRead);
}
Run Code Online (Sandbox Code Playgroud)

编辑:如上所述,它确实涉及read在循环外声明,但它只调用read()一次.我从来没有发现它是一个问题 - 虽然我通常更喜欢用尽可能小的范围声明变量,这更像是一般的清洁事物.如果你想进一步限制范围,你可以把整个东西放在大括号中,或者把它提取到自己的方法,比如Alan的方法.这是我如何实现它:

public static void copyStream(InputStream input, OutputStream output)
    throws IOException {
  byte[] buffer = new byte[1024 * 16]; // Reasonable general size

  int bytesRead;
  while ((bytesRead = in.read(buffer, 0, buffer.length)) != -1) {
    outStream.write(buffer, 0, bytesRead);
  }
}
Run Code Online (Sandbox Code Playgroud)

或者,您可以提供缓冲区长度作为参数.请注意,这现在可以进入实用程序库,您无需再次编写代码.

或者,您可以使用它已在其他实用程序库中可用的事实,例如Guava asByteStreams.copy