更好的 Java 循环?

发布于 2024-11-08 19:51:06 字数 692 浏览 2 评论 0 原文

我有一段代码来读取 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);
}

它可以工作,但我不喜欢它,因为变量 read< /code> 被声明为循环外,并且 read() 方法被写入两次。 修改后的版本:

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

它看起来更好,但还不够好,因为第一次迭代在 read=0 时是无用的(而且可能是有害的)。

您有更好的解决方案吗?

I have a piece of code to read a InputStream and write the content into an 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);
}

It works, but i don't like it since the variable read is declared out of the loop, and read() method is written twice.
The revised version:

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

It looks better but not good enough because the first iteration is useless (and maybe harmful) with read=0.

Do you have a better solution?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

回忆追雨的时光 2024-11-15 19:51:06

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

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

编辑:如上所述,它确实涉及在循环外部声明read,但是它只调用read()一次。我从来没有发现这是一个问题——虽然我通常更喜欢声明范围尽可能小的变量,但这更多的是一个一般的清洁问题。如果您想进一步限制范围,您可以将整个内容放在大括号中,或者将其提取到自己的方法中,就像艾伦的方法一样。以下是我实现它的方法:

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);
  }
}

或者,您可以提供缓冲区长度作为参数。请注意,现在可以将其放入实用程序库中,并且您无需再次编写代码。

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

Personally I break the normal "no side-effect in a condition" rule for this sort of thing:

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

EDIT: As noted, it does involve declaring read outside the loop, but it only calls read() once. I've never found it to be a problem - while I generally prefer to declare variables with as small a scope as possible, that's more a general cleanliness thing. If you want to limit the scope further you can put the whole thing in braces, or extract it to its own method, like Alan's approach. Here's how I'd implement it though:

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);
  }
}

Alternatively you could provide the buffer length as a parameter. Note that this can now go off into a utility library, and you need never write the code again.

Alternatively, you could use the fact that it's already available in other utility libraries, such as Guava as ByteStreams.copy

别再吹冷风 2024-11-15 19:51:06

您可以这样做:

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

while (true) { // can i use for(;;) in Java ???
    int read = in.read(buffer, 0, bufferSize);
    if (read == -1) break;
    outStream.write(buffer, 0, read);
}

不过,它使用 break。有些人说 break 是不好/不太好的风格。

You can do it this way:

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

while (true) { // can i use for(;;) in Java ???
    int read = in.read(buffer, 0, bufferSize);
    if (read == -1) break;
    outStream.write(buffer, 0, read);
}

It uses a break, though. Some people say break is bad/not so good style.

怕倦 2024-11-15 19:51:06

这并不出色,但是通过一个简单的块,您可以阻止稍后在方法中访问 read 变量:

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);
    }
}

// ...rest of your code

...但我同意,我也经常想要一个 while 循环,其中值要测试的内容在循环内初始化。据我所知,这是不可能的。

另一种方法是使用提取方法设计模式将该循环提取到完全独立的方法,即

public void yourMethod() {
    BufferedInputStream in = new BufferedInputStream(...);
    FileOutputStream outStream = new FileOutputStream outStream(...);

    this.writeToOutputStream(in, outStream);
}

private void writeToOutputStream(InputStream in, OutputStream outStream) {
    int read = in.read(buffer, 0, bufferSize);
    while (read != -1)
    {
        outStream.write(buffer, 0, read);
        read = in.read(buffer, 0, bufferSize);
    }
}

It's not brilliant, but with a simple block, you can stop the read variable from being accessed later in the method:

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);
    }
}

// ...rest of your code

...but I agree, I've also often wanted a while loop where the value to be tested is initialized inside the loop. As far as I know, it's not possible.

Another way to do it is to use the extract method design pattern to pull out that loop in to a completely separate method, i.e.

public void yourMethod() {
    BufferedInputStream in = new BufferedInputStream(...);
    FileOutputStream outStream = new FileOutputStream outStream(...);

    this.writeToOutputStream(in, outStream);
}

private void writeToOutputStream(InputStream in, OutputStream outStream) {
    int read = in.read(buffer, 0, bufferSize);
    while (read != -1)
    {
        outStream.write(buffer, 0, read);
        read = in.read(buffer, 0, bufferSize);
    }
}
冰魂雪魄 2024-11-15 19:51:06

这种形式相当常见:

while ((read = in.read(buffer, 0, bufferSize)) != -1) {
  ...
}

但在我看来,不太清晰。

This form is rather usual:

while ((read = in.read(buffer, 0, bufferSize)) != -1) {
  ...
}

but not so good for clarity IMO.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文