【问题标题】:Need to Capture selective STDOUT from Android for display in listview需要从 Android 捕获选择性 STDOUT 以在列表视图中显示
【发布时间】:2012-02-09 16:56:39
【问题描述】:

我正在使用自定义逻辑库在 Android 中运行嵌入式库 [tuProlog (2p.jar)] Prolog 推理引擎,我可以在 Android ListView 中成功查询和显示(部分)结果。

显示的只是推理引擎本身的结果,而不是像 Prolog 'write' 语句(默认情况下)写入 STDOUT 的辅助命令。

我需要在 Android 变量中捕获“写入”打印到 STDOUT 的结果,以显示给用户。总的想法(我没有与 ListView 结婚来实现)是模拟命令行交互,如果他们运行基于 Java 的 Prolog Interpreter 终端界面,则会进行该交互。

为了完成这个项目,我想坚持知识工程领域而不是进入系统工程领域,所以我将不胜感激任何对此问题的见解。

我的研究使我here 成为进一步研究的途径,但系统方面的东西很快就超出了我的经验。

提前非常感谢....

【问题讨论】:

  • 很好的问题,也是我遇到并解决的问题....简而言之,tuProlog 小巧、快速(如果设置正确)且高效。它的设计正是如此。我的应用程序加载引擎,以及 2 个独立且大小合适的知识库以及它所在的 Android 应用程序,内存为 0.89MB。考虑到这一点的一个因素是,我实现了一个线程的大内存猪来保存 2 个逻辑基......大多数应用程序可能不需要......在设置 Prolog 引擎和生成的线程以确保其正常工作...如果您需要,我会与您分享它们。
  • 还有一件事......我使用了 2p.jar 库,其中包括所有东西和厨房水槽,包括 Android 平台远程不需要的东西。正确的库是 tuprolog.jar 包含核心 API、代理应用程序和默认库,我怀疑这使它更小。
  • 它们在这里... (1) 将其放在您的 Activity 的类定义下方,以便在应用程序屏幕之前对其进行实例化 .... // 实例化 Prolog 引擎的实例。 // 只做一次,因为它非常昂贵。序言引擎 = 新序言(); (2) 这就是我使用外部文件加载逻辑库的方式... LoadLogicBase family_LoadLogicBase = new LoadLogicBase(theory_family, "add");您必须使用线程,并且 100000 参数是关键: Thread thread_B = new Thread(new ThreadGroup("B"), family_LoadLogicBase, "Load LogicBase" ,100000); thread_B.start();
  • 不是真的...... 2p.jar 句柄可以很好地容忍这一点。最大的问题是 prolog 'write' 语句的控制台输出...... Android 将所有 STDOUT 重新路由到 /dev/null 所以根本没有。我现在正在研究一种解决方法,但我还没有完全做到。 :-(
  • 经过数小时的研究和向 tuProlog 开发团队提出的问题,我确实有一个解决方案,可以让写入在 Android 系统中工作,他们将所有 STDOUT 路由到 /dev/null。但是它太大而无法包含在评论中,所以我将尝试回答我自己的问题并在其中制定如何做到这一点。简而言之,tuProlog 的基础架构考虑到了这个问题,并以侦听器/事件对的形式对其进行了一些非常优雅的调整,该对使用 STDOUT 但逃脱了 Android 锁定。在 Android 中可以捕获 N 次使用 STDOUT,稍后会详细介绍。

标签: android terminal command stdout tuprolog


【解决方案1】:

经过我自己的一些研究和与 tuProlog 开发人员的进一步讨论后,我有一个解决这个问题的方法,我认为值得与这个社区分享...

问题的总体背景是ANY Prolog 实现在“正确”的 Android 上工作,作为以后更有趣的应用程序(专家系统、游戏 AI 和自然语言界面)的基础架构下线。

最大的障碍是 Prolog 是一个基于“控制台”的解释性环境,它打印到 STDOUT,虽然 Android 允许控制台打印活动,但默认情况下它将所有这些都发送到 /dev /null。

所以有 组问题需要解决:(1) 是否有 ANY Prolog 可移植到Android 环境,以及(2)当控制台输出路由到 /dev/null 时,如何“正确”处理捕获控制台输出的问题>。

寻址 (1):我们选择了 tuProlog Site,其官方来源可以找到:Google Code Repository - tuProlog。他们将 prolog 设计为嵌入到单个 JAR 文件中,特别适用于 Android。他们是我们发现的唯一一个这样做的人,他们对开发人员“响应”。他们的东西是Open Source Java/Android,他们有一个Android Prolog 应用程序,很快就会更新。 询问他们的代码对于找到合适的解决方案非常宝贵。

地址 (2):为这项研究增加最大价值的链接是:Reading from PrintStreamConvert Java OutputStream to InputStream,最终是最有用的StreamWriter to OutputStream

具体来说,需要做的是

  • 创建一个 ByteArrayOutputStream 对象来捕获二进制数据 从打印过程到控制台(System.out)。
  • 在中创建 PrintStream 对象(使用 ByteArrayOutputStream) 设置 System.setOut(控制控制台输出 [System.out.println] 的位置)
  • 重新路由系统输出
  • 将所需的控制台打印输出捕获到字符串变量
  • 将该字符串添加(在此 Android 项目的情况下)到列表视图的一行
  • 通知 Listview 数据已更改
  • 重置 ByteArrayOutputStream 对象(以避免串联)

这是代码

   // OutPutStream I/O Experimental Stuff
   PrintStream orgStream   = System.out;

   // ByteArray Sub Experimental Stuff
   ByteArrayOutputStream baos = new ByteArrayOutputStream();
   PrintStream psout = new PrintStream(baos, Boolean.TRUE); // Using autoFlush


   // Instantiate an instance of the Prolog Engine. 
   //Do this only once because it's VERY expensive.
   Prolog engine;


    // ReRouting Print Streams 
    // (Inside method we need to capture console output)
    System.setOut(orgStream);           // Set the System Output Stream  


    String myResult = baos.toString();      // returns the actual text 
    myChatListItems.add(myResult);          // Add Text to New ListView Row  
    chatBotAdapter.notifyDataSetChanged();  // notify the Adapter to Refresh
    baos.reset();                           // Reset the ByteArrayOutputStream

      System.setOut(orgStream);  // RESET the System Output Stream 

最后说明: tuProlog 考虑了控制台打印问题并围绕它设计了这个特定的实现,使用侦听器和事件的组合来正确解决 Prolog“Write”命令的捕获以及其他问题。

Strict Prolog Queries 的解决可以通过仔细阅读他们的用户指南中建立的首选方法相当容易地完成......开发人员可以从中快速找到他们需要的东西。

这是对 Prolog Engine 函数的捕获,例如 WriteSpyError 事件,这些事件更难以确定(我最终咨询了 w /开发人员)。为此,您需要询问他们的 CUIConsole 的 Android 实现(与他们的 CUIConsole 的控制台实现相反,后者“不同”)。

简而言之,答案是:(a) 建立一个监听器,然后(b) 为事件做准备 发生。

代码如下:

    // Establish Prolog engine and it's appropriate listeners
    // [Warning, Output, and Spy] 
    engine = new Prolog();
    engine.addWarningListener(this);
    engine.addOutputListener(this);
    engine.addSpyListener(this); 

//// PROLOG CONSOLE OUTPUT MECHANISMS *******************************

@Override
public void onSpy(SpyEvent e) {
    Log.d(TAG, "** LG'd onSpy => SpyEvent Occured ** " );
    System.out.println("** onSpy => SpyEvent Occured ** \n ");
    myChatListItems.add( e.getMsg() );
    chatBotAdapter.notifyDataSetChanged();

}


@Override
public void onOutput(OutputEvent e) {
    Log.d(TAG, "** LG'd: onOutput => OutputEvent Occured ** " );
    System.out.println("** onOutput => OutputEvent Occured ** \n ");
    myChatListItems.add( e.getMsg() );
    chatBotAdapter.notifyDataSetChanged();

}


@Override
public void onWarning(WarningEvent e) {
    Log.d(TAG, "** LG'd: onWarning => WarningEvent Occured ** " );
    System.out.println("** onWarning => WarningEvent Occured ** \n ");
    myChatListItems.add( e.getMsg() );
    chatBotAdapter.notifyDataSetChanged();

}

结束说明: 对于那些有兴趣的人 “Android 上的 Prolog”,我很乐意提供我编写的任何代码或我拥有的资源,以便在此过程中为您提供帮助.请不要犹豫。

【讨论】:

  • 您好 ProfVersaggi,您能分享一个简单的 Prolog+android 项目吗?我通读了这个线程并实现了你所写的,但仍然没有得到任何输出。这是我在 Android 中的 tuProlog 简单测试项目,但我得到 System.err: FileNotFoundException。链接:stackoverflow.com/questions/10166942/running-prolog-in-android,使用监听器也不起作用,可能是我在错误的地方使用监听器。我需要 tuProlog 来为应用导出我的 NL 界面。
  • 我将源代码发布到我的 Android 开发网站供您下载如何?那有用吗?
  • 谢谢,感谢您的帮助。
  • 我会尽快完成这项工作,如果运气好的话,我会在明天之前完成并在此处发布指向该站点的链接。敬请关注! ;-)
  • 下载Eclipse(Helios)项目源码,转到:versaggi.biz,下载Adrea,TuProlog Dev Project,Eclipse(Helios)Java Source Project,最后到TuProlog Android Eclipse Project Source。那应该让你开始。请记住,这只是概念验证代码,将在最终版本发布之前完全重写。鉴于此,它的效果确实足以让您深入了解我是如何做我所做的事情的。如果您需要任何帮助,请直接与我联系,我很乐意为您提供帮助。 :-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多