【问题标题】:BufferedOutputStream not writing to standardIOBufferedOutputStream 未写入标准 IO
【发布时间】:2013-12-11 03:25:02
【问题描述】:

我正在尝试使用 Robert Sedgwick 在他的算法 4E 教科书中提供的 BinaryStdOut.java 类。这个类的代码可以在他的网站上免费获得,但为了方便参考,我将在这里展示它的相关sn-ps。

在上面提到的类中,一个BufferedOutputStream声明如下

    private static BufferedOutputStream out = new BufferedOutputStream(System.out);

如果我的理解是正确的,这应该允许 out.write() 基本上打印到标准输出,就像我要使用 System.out.print() 一样。

为了测试这一点,我构建了一个程序,其主要功能如下

    public static void main(String[] args) {
    BinaryStdOut.write(1);
}

这会将整数 1 传递给 BinaryStdOut 的 write() 方法,如下所示

    public static void write(int x) {
    writeByte((x >>> 24) & 0xff);
    writeByte((x >>> 16) & 0xff);
    writeByte((x >>>  8) & 0xff);
    writeByte((x >>>  0) & 0xff);
}

writeByte() 代码是:

private static void writeByte(int x) {
    assert x >= 0 && x < 256;

    // optimized if byte-aligned
    if (N == 0) {
        try { out.write(x); }
        catch (IOException e) { e.printStackTrace(); }
        return;
    }

    // otherwise write one bit at a time
    for (int i = 0; i < 8; i++) {
        boolean bit = ((x >>> (8 - i - 1)) & 1) == 1;
        writeBit(bit);
    }
}

现在我的问题是测试代码似乎没有做任何事情。它编译并成功运行,但在我的终端中没有打印任何内容,就像我使用相同的整数执行 System.out.print() 一样。

为了查看问题是否出在 BinaryStdOut 类,我将 BufferedOutputStream 声明复制到我的主程序中,然后尝试直接写入该流,结果相同。

我在使用BufferedOutputStream.write() 时有什么遗漏吗?

编辑:我的测试程序的主要功能目前如下所示:

public static void main(String[] args) {
    // TODO Auto-generated method stub
    BufferedOutputStream out = new BufferedOutputStream(System.out);
    try {out.write(16);
    out.flush();
    out.close();}
    catch(IOException e){
        System.out.println("error");
    }
}

【问题讨论】:

  • 别忘了flush()
  • @SotiriosDelimanolis 我该把flush 放在哪里我在BufferedOutputStream.write() 之后立即添加了一个,我把它放在我的主程序中用于测试服务,它似乎仍然没有打印任何东西。
  • 您可以将它放在writeByte 的末尾(以及所有其他写入方法)。 out.flush() 其中out 是您的BufferedOutputStream
  • 您正在打印一个 DLE(十进制 16),它不会出现在标准输出中。
  • 根据@SotiriosDelimanolis 将out.flush() 添加到writeByte 方法并根据@JonLin 将我的测试字符更改为打印(D'Oh!)后,它似乎可以从我的测试代码中工作现在,谢谢先生们!

标签: java printing output bufferedoutputstream


【解决方案1】:

写入缓冲区后需要刷新缓冲区:

// optimized if byte-aligned
if (N == 0) {
    try { 
        out.write(x); 
        out.flush();
    }
    catch (IOException e) { e.printStackTrace(); }
    return;
}

您的测试程序似乎没有打印任何内容的原因是因为您正在打印 DLE,它是一个控制字符,不会出现在标准输出中。

【讨论】:

    【解决方案2】:

    这为我打印了 hello world,您是否选择了一些没有可显示字形的字节?而且您可能不应该那样关闭System.out(在 BuffedOutputStream 上调用 close 会关闭它并释放与流相关的任何系统资源)。

    public static void main(String[] args) {
      BufferedOutputStream out = new BufferedOutputStream(
          System.out);
      String msg = "Hello, World!";
      try {
        for (char c : msg.toCharArray()) {
          out.write(c);
        }
        out.flush();
      } catch (IOException e) {
        System.out.println("error");
      }
    }
    

    【讨论】:

      【解决方案3】:

      是的,您需要flush,为什么需要flush 是因为Buffered 输出流使用:

      BufferedOutputStream:

      public BufferedOutputStream(OutputStream out) {
          this(out, 8192);//default buffer size
          }
      public synchronized void write(int b) throws IOException {
          if (count >= buf.length) {
              flushBuffer();
          }
          buf[count++] = (byte)b;
          }
      

      因此,在缓冲区被 8KB 数据填充之前,内容将保持缓冲状态,不会被输出到控制台。

      write(16) 上,您应该会在控制台看到 print char(至少是 Eclipse IDE),如果您打印 1601 - 1626,您应该会看到 A-Z 打印的字符。

      【讨论】:

        猜你喜欢
        • 2014-12-02
        • 2011-09-21
        • 1970-01-01
        • 2012-03-14
        • 2022-01-14
        • 2012-06-03
        • 2014-10-05
        • 1970-01-01
        • 2012-02-04
        相关资源
        最近更新 更多