向 Java 项目添加 FineReader Engine 库
ABBYY FineReader Engine 包含 com.abbyy.FREngine-%BUILD_ID%.jar 文件,其中包含 FineReader Engine 的 Java 类库。您可以在 Inc\Java 文件夹中找到该文件。可以在命令行的 classpath 参数中以及不同 Java 开发环境的项目设置中指定该文件的路径。示例:
%JDK%\bin\Javac -classpath <path>/com.abbyy.FREngine-%BUILD_ID%.jar Hello.java
%JDK% 是 Java Development Kit 的安装路径。
支持的 Java Development Kit 列表,请参见 系统要求。
您可以使用静态 Engine 类加载 Engine 对象。
Engine 类提供了与 ABBYY FineReader Engine 中用于加载和卸载 Engine 的函数相对应的方法:
| 函数 | Engine 类方法 | Engine 类方法的签名 |
|---|
| InitializeEngine | InitializeEngine | csharp static public IEngine InitializeEngine( String dllFolder, String customerProjectId, String licensePath, String licensePassword, String dataFolder, String tempFolder, boolean isSharedCPUCoresMode ) throws Exception; |
| DeinitializeEngine | DeinitializeEngine | static public void DeinitializeEngine() throws Exception; |
import com.abbyy.FREngine.*;
public class Hello {
public static void main( String[] args )
{
try {
// 使用 Online License 加载 Engine
engine = Engine.InitializeEngine( dllPath, customerProjectId, LicensePath, LicensePassword, "", "", false );
try {
// 加载预定义配置文件
engine.LoadPredefinedProfile( "DocumentConversion_Accuracy" );
// 处理图像
IFRDocument document = engine.CreateFRDocument();
...
} finally {
engine = null;
System.runFinalization();
Engine.DeinitializeEngine();
}
} catch( Exception ex ) {
trace( ex.getMessage() );
}
}
private IEngine engine = null;
...
}
要通过 COM 加载 Engine,请使用 GetEngineInprocLoader 或 GetEngineOutprocLoader 方法。详情请参阅 IEngineLoader 接口的说明。如果您使用 GetEngineOutprocLoader 方法进行加载,则无需调用 IHostProcessControl::SetClientProcessId 方法,因为父进程会自动设置。
如果您在 Windows 上开发应用程序,但打算在 Linux 上运行,请不要使用这些方法加载 Engine。请仅使用上文介绍的 InitializeEngine 方法。之所以有此限制,是因为实现 IEngineLoader 的对象在 Linux 上不可用。
import com.abbyy.FREngine.*;
// 使用 Online License 加载 Engine
engineLoader = Engine.GetEngineInprocLoader();
engine = engineLoader.InitializeEngine( customerProjectId, LicensePath, LicensePassword, "", "", false );
...
// 卸载 Engine
engine = null;
System.runFinalization();
engineLoader.ExplicitlyUnload();
engineLoader = null;
System.runFinalization();
import com.abbyy.FREngine.*;
// 使用 Online License 加载 Engine
engineLoader = Engine.GetEngineOutprocLoader();
engine = engineLoader.InitializeEngine( customerProjectId, LicensePath, LicensePassword, "", "", false );
...
// 卸载 Engine
engine = null;
System.runFinalization();
engineLoader.ExplicitlyUnload();
engineLoader = null;
System.runFinalization();
对于通过引擎加载器创建的 Engine 对象,Engine 类提供了一些方法,用于调用相应的 COM 函数在线程之间封送接口指针:
| 方法 | 签名 | 备注 |
|---|
| MarshalInterface | long MarshalInterface(); | 调用 CoMarshalInterface COM 函数来封送 IEngine 接口。应在创建引擎的线程上调用此方法,以确保在另一线程上创建代理对象所需的数据可用。返回封送数据的句柄。 |
| UnmarshalInterface | csharp IEngine UnmarshalInterface( long handle ); | 调用 CoUnmarshalInterface COM 函数对 IEngine 接口进行反封送,即创建一个代理对象,使客户端进程能够像与引擎本身交互一样与其交互。该方法将封送数据的句柄 (由 MarshalInterface 方法返回) 作为输入参数,并返回指向 IEngine 接口的指针。 |
com.abbyy.FREngine-%BUILD_ID%.jar 文件是一个自解压归档,首次使用 FineReader Engine Java API 时,它会在您的计算机上自动解压。默认情况下,在 Windows 上,归档内容会解压到 Inc\Java 文件夹中。如果您需要使用其他文件夹,请在通过上述任一方法加载 Engine 之前调用 Engine.SetJNIDllFolder 方法。要查看当前设置用于解压归档的文件夹,请调用 Engine.GetJNIDllFolder。
对于多线程 Java 应用程序,您可以使用 EnginesPool 类,该类为创建和管理 FineReader Engine 对象池提供了完整的解决方案。此类实现了 java.lang.Runnable 接口。
public class EnginesPool implements Runnable;
下面列出了 EnginesPool 类的方法。
| 方法 | 签名 | 备注 |
|---|
| constructor | public EnginesPool( int enginesCount, int waitingEngineTimeout, String customerProjectId, String licensePath, String licensePassword, String dataFolder, String tempFolder, boolean isSharedCPUCoresMode ) throws Exception; | 创建一个包含 enginesCount 个 Engine 的新池。waitingEngineTimeout 用于设置 EnginesPool.GetEngine 的等待超时时间。其他参数与 InitializeEngine 中的参数相同。 |
| GetEngine | csharp public IEngine GetEngine() throws Exception; | 从池中获取一个 Engine 实例。如果等待时间超过 waitingEngineTimeout,则会引发异常。 |
| ReleaseEngine | csharp public void ReleaseEngine( IEngine engine, boolean isRecycleRequired ) throws Exception; | 将一个 Engine 实例返回到池中。如果 isRecycleRequired 为 true,则会删除该实例并用一个新实例替换它 (即使尚未达到使用次数限制,或已禁用自动回收) 。 |
| SetAutoRecycleUsageCount | public void SetAutoRecycleUsageCount( int value ); | 设置此池中单个 Engine 实例在被回收前可重复使用的次数;回收时,该实例会被自动删除并替换为新的实例。该计数可设置为 0,表示永不自动回收 (只能通过 ReleaseEngine 手动回收) 。默认值为 0 (永不自动回收) 。 |
| GetAutoRecycleUsageCount | public int GetAutoRecycleUsageCount(); | 获取此池中 Engine 实例的重复使用次数上限。 |
| UnloadEngines | public void UnloadEngines() throws Exception; | 卸载所有 Engine,并取消初始化该池。 |
有关如何使用 EnginesPool 类的示例,请参见 EnginesPool 代码示例。
ABBYY FineReader Engine 可能会抛出以下类型的异常:
- java.lang.OutOfMemoryError
- com.abbyy.FREngine.EngineException
com.abbyy.FREngine.EngineException 异常继承自 java.lang.Exception,并包含一个额外的方法 int getHResult,该方法返回发生的错误的 HRESULT 代码。对于此类异常,您不仅可以使用 getMessage() 方法获取错误消息,还可以获取错误代码。
try {
...
} catch( Exception ex ) {
displayMessage( "Message = " + ex.getMessage() );
if( ex instanceof EngineException ) {
displayMessage( "HResult = " + Integer.toString( ( ( EngineException )ex ).getHResult() ) );
}
}
ABBYY FineReader Engine API 中有几种方法带有 out 参数,这些参数会在方法调用后接收新值,并且必须按引用传递。这些参数会在类型库以及本开发人员帮助中的方法说明里标记为 [out] 或 [in, out]。
在 Java 中使用 ABBYY FineReader Engine 时,必须使用专门的 Ref 类按引用传递参数。请参见下面的示例。
下面的示例中,out 参数通过引用传递给 IFRPage::FindPageSplitPosition 方法:
Ref<PageSplitDirectionEnum> _ps = new Ref<PageSplitDirectionEnum>();
Ref<Integer> _start = new Ref<Integer>();
Ref<Integer> _end = new Ref<Integer>();
page.FindPageSplitPosition( null, null, _ps, _start, _end );
PageSplitDirectionEnum ps = _ps.get();
Integer start = _start.get();
Integer end = _end.get();
下面的示例中,in/out 参数通过引用传递给 ICoordinatesConverter::ConvertCoordinates 方法:
Ref<Integer> _x = new Ref<Integer>( 100 );
Ref<Integer> _y = new Ref<Integer>( 200 );
cnv.ConvertCoordinates( ImageTypeEnum.IT_Modified, ImageTypeEnum.IT_Base, _x, _y );
Integer x = _x.get();
Integer y = _y.get();
以下示例展示了数组 out 参数如何通过引用传递给 IPlainText::GetCharacterData 方法:
Ref<int[]> _leftBorders = new Ref<int[]>();
Ref<int[]> _topBorders = new Ref<int[]>();
Ref<int[]> _rightBorders = new Ref<int[]>();
Ref<int[]> _bottomBorders = new Ref<int[]>();
Ref<int[]> _confidences = new Ref<int[]>();
Ref<boolean[]> _isSuspicious = new Ref<boolean[]>();
plainText.GetCharacterData( _pageNumbers, _leftBorders, _topBorders, _rightBorders, _bottomBorders, _confidences, _isSuspicious );
int[] pageNumbers = _pageNumbers.get();
int[] leftBorders = _leftBorders.get();
int[] topBorders = _topBorders.get();
int[] rightBorders = _rightBorders.get();
int[] bottomBorders = _bottomBorders.get();
int[] confidences = _confidences.get();
boolean[]isSuspicious = _isSuspicious.get();
Ref<int[]> _pageNumbers = new Ref<int[]>();
FineReader Engine 支持 AutoCloseable 接口,因此您可以使用 try 语句来管理为对象分配的资源。这意味着,一旦 try 代码块执行结束,所有已分配的资源都会自动关闭,无需显式调用关闭方法。我们建议您在代码中的所有对象上都使用 try 语句 (请参见下面的示例) :
try( IFRDocument document = engine.CreateDocument() )
{
// 将图像添加到文档
document.AddImageFile( imagePath, null, null );
...
// 将结果保存为 PDF
document.Export( pdfExportPath, FileExportFormatEnum.FEF_PDF, pdfParams );
}
使用 HGLOBAL
ABBYY FineReader Engine API 中的某些方法会将内存块的 HGLOBAL 句柄作为输入参数 (以 __int64 形式传递) 。由于 HGLOBAL 是 Windows 特有的实体,因此在 Java 封装器中,这些方法改为接收内存块的内容,即 byte[]。请参见以下方法列表:
另一方面,那些返回 Handle 对象的方法,在 Java 封装器中同样会返回该对象。
对于接受多个枚举常量组合的方法和属性,需要向相应的方法/属性传递 int 值。要获取枚举常量的 int 值,请使用所有枚举均支持的 getValue 方法。
下面的示例代码演示了如何设置 PDFPictureCompressionParams 对象的 BwPictureFormats 属性:
IPDFExportParams pep = engine.CreatePDFExportParams();
IPDFPictureCompressionParams ppcp = pep.getPictureCompressionParams();
ppcp.setBwPictureFormats(BwPictureFormatsEnum.BWPF_Auto.getValue());
另请参阅
Engine 对象的不同加载方式 (适用于 Windows)
Java 跨平台开发 (适用于 Windows)