有人玩过NIO管道来过滤/拦截System.out吗?

2023-12-09

按照建议here我想在选择器循环内执行此操作。我真正想要的是在选择器循环内读取写入系统的内容。

EDIT1:我编写了一个完整的解决方案,只是为了发现您无法使用 System.setOut 重定向 GC 日志。它只是直接转到 FD 或其他东西。显示塞子!除非我重定向到一个文件并将该文件通过管道传输到我的选择器中。很多工作!看here.


一种方法如下:

  • 创建 OutputStream 的子类,将其输出重定向到 Pipe 的接收通道
  • 使用此类重定向 System.out:System.setOut(new PrintStream(new MyOutputStream(pipe));
  • 使用选择器注册管道的源通道,并获取选择器循环中写入 System.out 的所有内容,即源通道的相应 SelectionKey 被选择为 Readable()

以下实现是一个简单但有效的实现,它只是将写入 System.out 的所有内容重定向到 System.err:

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;

public class SystemOutPipe extends Thread {

  public static void main(String[] args)
  {
    try {
      SystemOutPipe sop = new SystemOutPipe();
      sop.start();
      System.out.println("This message should be redirected to System.err\nNow waiting 5 seconds ...");
      Thread.sleep(5000L);
      sop.setStopped(true);
      sop.join();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  private Selector selector;
  private Pipe pipe;
  private boolean stopped = false;

  public SystemOutPipe() throws IOException {
    super("SystemOutPipe");
    pipe = Pipe.open();
    System.setOut(new PrintStream(new PipeOutputStream(pipe)));
    selector = Selector.open();
    pipe.source().configureBlocking(false);
    pipe.source().register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));
  }

  @Override
  public void run() {
    try {
      while (!isStopped()) {
        int n = selector.select(1L);
        if (n > 0) {
          Iterator<SelectionKey> it = selector.selectedKeys().iterator();
          while (it.hasNext()) {
            SelectionKey key = it.next();
            it.remove();
            if (key.isReadable()) {
              new ReadHandler(key).run();
            }
          }
        }
      }
    } catch (Exception e) {
      e.printStackTrace(); // writes to System.err !
    }
  }

  public synchronized boolean isStopped() {
    return stopped;
  }

  public synchronized void setStopped(final boolean stopped) {
    this.stopped = stopped;
  }

  public class ReadHandler implements Runnable {
    private final SelectionKey key;

    public ReadHandler(final SelectionKey key) {
      this.key = key;
    }

    @Override
    public void run() {
      ByteBuffer bbuf = (ByteBuffer) key.attachment();
      ReadableByteChannel channel = (ReadableByteChannel) key.channel();
      try
      {
        int count = 0;
        do {
          bbuf.clear();
          count = channel.read(bbuf);
          if (count > 0) System.err.write(bbuf.array(), 0, count);
        } while(count > 0);
      } catch (IOException e) {
        e.printStackTrace();
        key.cancel();
      }
    }
  }

  public class PipeOutputStream extends OutputStream {
    private final Pipe pipe;

    public PipeOutputStream(final Pipe pipe) {
      this.pipe = pipe;
    }

    @Override
    public void write(final int b) throws IOException {
      write(new byte[] { (byte) b });
    }

    @Override
    public void write(final byte[] b) throws IOException {
      write(b, 0, b.length);
    }

    @Override
    public void write(final byte[] b, final int off, final int len) throws IOException {
      ByteBuffer bbuf = ByteBuffer.wrap(b, off, len);
      bbuf.position(len);
      bbuf.flip();
      int count = 0;
      while (count < len) {
        int n = pipe.sink().write(bbuf);
        if (n == 0) {
          // let's wait a bit and not consume cpu
          try {
            Thread.sleep(1L);
          } catch (InterruptedException e) {
            throw new IOException(e);
          }
        }
        else count += n;
      }
    }
  }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

有人玩过NIO管道来过滤/拦截System.out吗? 的相关文章

随机推荐

  • “类型错误:没有编码的字符串参数”,但字符串已编码?

    我正在努力转换现有计划从Python2到Python3 该程序中的方法之一通过远程服务器对用户进行身份验证 它将提示用户输入密码 def handshake self timestamp int time time token md5has
  • 我们可以将电子邮件 ID 作为 Firebase 数据库中的键吗? [复制]

    这个问题在这里已经有答案了 我想创建一个登录系统 当用户登录时 基于 在登录用户的电子邮件 ID 上 我想检索 EID 我想要的 JSON 结构是 email protected EID 0153 S email protected EID
  • ggplot2:如何绘制正交回归线?

    我已经在两项不同的视觉感知测试中对大量参与者进行了测试 现在 我想看看这两项测试的表现有多大程度的相关性 为了可视化相关性 我使用 R 绘制了散点图ggplot 我拟合了一条回归线 使用stat smooth 然而 由于我的两个x and
  • 传递匿名函数作为参数

    为什么以下工作有效 foo lt function x x curve foo plots the identity function between 0 and 1 这并不 curve function x x 曲线错误 函数 x exp
  • Android:仅适用于非数字字符的输入类型

    我有一个 EditText 我想让用户仅输入非数字字符 例如 A Z 或 a z 有没有办法做到这一点 我使用的所有组合 文本 文本用户名等 都允许用户选择数字 我认为您必须编写自己的 InputFilter 并将其添加到 EditText
  • 从 Active Directory 组获取用户

    我创建了一个 Active Directory 域名 ADDOMAIN2 其组名为 CommonUsers 有 8 个用户 但是当我对 CommonUsers 组中的用户进行目录搜索时 它返回零结果 她是我的代码 DirectorySear
  • countplot() 与频率

    我有一个 Pandas DataFrame 其中有一列名为 AXLES 它可以采用 3 12 之间的整数值 我正在尝试使用 Seaborn 的 countplot 选项来实现以下绘图 左 y 轴显示这些值在数据中出现的频率 轴延伸范围为 0
  • XML 中的 PHP 代码?

    是否可以将 PHP 代码放入 XML 文档中以便稍后执行 例如 我可以说
  • Chrome、Firefox 调试器未在 React 应用程序中显示“this”的正确值

    这是 React 组件类中的一些代码 使用 CRA 2 搭建脚手架 click gt console log this hello let x 1 1 This is just here to let chrome put a break
  • 为 sqldatasource 分配参数

    我试图从 SQL Server 获取数据并在表单视图中使用它 但表单视图控件不会从数据源获取任何数据 数据源在页面加载时获取参数 输出只是 这里没有什么可看的 和一个空表 这是数据源和表单视图标签
  • hg忘记和hg删除有什么区别?

    我希望 Mercurial 从存储库的当前状态中删除多个文件 但是 我希望这些文件存在于以前的历史记录中 How do forget and remove不同 他们能做我想要的吗 hg forget 只是 的简写hg remove Af 来
  • Visual Studio 2022:防止解决方案资源管理器中折叠文件夹(2)

    这是对中报告的问题的后续行动这个问题同名 我在 Visual Studio 2022 中遇到同样的问题 对象在几秒钟后或单击另一个对象时崩溃 提供的答案是更改 CodeMaid 中的设置 但我尚未加载 CodeMaid 并且遇到了相同的问题
  • R 中有处理命令行选项的包吗?

    R 中有处理命令行选项的包吗 I know commandArgs 但这太基础了 其结果基本上相当于argc and argv in C 但除此之外我还需要一些东西 就像boost program options in C or GetOp
  • 如何将外部文件中的 Fortran 代码插入到单独的代码中?

    我想让我的代码获取在另一个文档中编写的代码 阅读它 然后像在代码中编写一样使用它 假设我们有以下内容 MODULE samplemod CONTAINS FUNCTION sillysum boudary function RESULT c
  • 使用 Trigger.IO/PhoneGap 在 UIWebView 中通过 focus() 事件自动显示键盘

    据推测 自 iOS 6 以来 这是不可能的 您可以在 iOS 6 中设置 UIWebView 的 KeyboardDisplayRequiresUserAction NO 我正在使用 html 5 webview Trigger IO 并构
  • 为什么 foreach 循环不适用于 JSON 数组

    当我尝试的时候解析 json 数组 工作室给了我一个编译错误 指出foreach 不适用于 json 数组 虽然我知道如何获取所有对象并解析 我只是想知道为什么foreach不适用即使 json 数组是一个数组 对于每个循环的工作方式如下
  • 如何在大型排序数组中高效地找到最接近另一个值 X 的值

    对于已排序的列表 如何找到接近给定数字的最小数字 例如 mysortedList 37 72 235 645 715 767 847 905 908 960 如何找到小于或等于700的最大元素quickly 如果我有1000万个元素 那么线
  • 如何在 Laravel 中显示 GIF

    我正在使用 Firefox 浏览器 尝试了所有PNG s JPG一切都在工作 除了GIF 事情是这样的 如果我测试一下http localhost pepsi gif GIF实际上正在工作并显示 但当我在里面尝试时HTML 图片标签它不显示
  • 匹配两个不同标记之间的任意字符串

    我正在尝试匹配两个不同标记之间的字符串的一部分 它们可能是字符串中多次出现的标记 示例文本 标记为斜体 要匹配的文本为粗体 This is 开始比赛 示例文本 结束比赛 和一些 开始比赛 代币和普通 结束比赛 text 我有以下正则表达式
  • 有人玩过NIO管道来过滤/拦截System.out吗?

    按照建议here我想在选择器循环内执行此操作 我真正想要的是在选择器循环内读取写入系统的内容 EDIT1 我编写了一个完整的解决方案 只是为了发现您无法使用 System setOut 重定向 GC 日志 它只是直接转到 FD 或其他东西