经过我自己的一些研究和与 tuProlog 开发人员的进一步讨论后,我有一个解决这个问题的方法,我认为值得与这个社区分享......
这个问题的整体背景是让任何Prolog 实现在“正确”的 Android 上工作,作为以后更有趣的应用程序(专家系统、游戏 AI 和自然语言接口)的基础架构。
最大的障碍是Prolog 是一个基于“控制台”的解释性环境,它打印到 STDOUT,虽然 Android 允许控制台打印活动,但默认情况下它将所有这些活动都发送到/dev/null。
因此,有两组问题需要解决:(1)是否有任何Prolog 可移植到 Android 环境,以及(2)如何“正确”处理路由到/dev/null时捕获控制台输出的问题。
解决方法(1):我们选择了tuProlog 网站,官方来源可以找到:Google Code Repository - tuProlog。他们将 prolog 设计为嵌入到单个 JAR 文件中,特别适用于 Android。他们是我们发现的唯一一个这样做的人,他们对开发人员“响应”。他们的东西是开源 Java/Android并且他们有一个Android Prolog 应用程序即将推出更新。询问他们的代码对于找到合适的解决方案是非常宝贵的。
寻址(2):为这项研究增加最大价值的链接是:从 PrintStream 读取,将 Java OutputStream 转换为 InputStream,最终将最有用的StreamWriter 转换为 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“写入”命令的捕获以及其他问题。
通过仔细阅读用户指南中建立的首选方法,可以很容易地解决严格的 Prolog 查询……开发人员可以从中快速找到他们需要的东西。
这是对 Prolog 引擎功能的捕获,例如Write、Spy和Error事件,这些功能更难以确定(我最终咨询了开发人员)。为此,您需要询问他们的CUIConsole的 Android 实现(与他们的CUIConsole的控制台实现相反,后者“不同”)。
简而言之,答案是:(a) 建立一个 Listener,然后(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”感兴趣的人,我很乐意提供我编写的任何代码或我拥有的资源,以便在此过程中为您提供帮助。请不要犹豫,问。