之前使用Libreoffice解析Word出现各种问题,这次使用本使用POI库进行解析和操作word,在网上查了查POI是java的jar包提供个的,解析需要使用C++调用jar包,就需要使用java的JNI技术了,详细原理不解释,自己看下,这里是说明如何用C++调用jar包:
- java jak下载,不说了,自己在官网上下.
- 开始配置环境,添加环境变量,在jdk目录下\jre\bin\client,我的是在C:\Program Files (x86)\Java\jdk1.8.0_211\jre\bin\client。
- 配置VS的环境,新建控制台程序,设置包含目录,jdk目录下的\jdk1.8.0_211\include和jdk1.8.0_211\include\win32目录.
- 设置库目录C:\Program Files %28x86%29\Java\jdk1.8.0_211\jre\bin\client和C:\Program Files %28x86%29\Java\jdk1.8.0_211\lib两个目录。
- 设置依赖项,jvm.lib.
// CallJava.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "jni.h"
#include <windows.h>
#include <Shlwapi.h>
#include <string>
using namespace std;
typedef jint(WINAPI *_CreateJavaVM)(JavaVM **, void **, void *);
#pragma comment(lib,"Shlwapi.lib")
/*C字符串转JNI字符串*/
jstring stoJstring(JNIEnv* env, const char* pat) {
jclass strClass = env->FindClass( "Ljava/lang/String;");
jmethodID ctorID = env->GetMethodID( strClass, "<init>",
"([BLjava/lang/String;)V");
jbyteArray bytes = env->NewByteArray(strlen(pat));
env->SetByteArrayRegion(bytes, 0, strlen(pat), (jbyte*)pat);
jstring encoding = env->NewStringUTF("utf-8");
return (jstring)env->NewObject( strClass, ctorID, bytes,
encoding);
}
/*JNI字符串转C字符串*/
char* jstringTostring(JNIEnv* env, jstring jstr) {
char* rtn = NULL;
jclass clsstring =env->FindClass("java/lang/String");
jstring strencode =env->NewStringUTF( "utf-8");
jmethodID mid =env->GetMethodID( clsstring, "getBytes",
"(Ljava/lang/String;)[B");
jbyteArray barr = (jbyteArray)env->CallObjectMethod(jstr, mid,
strencode);
jsize alen =env->GetArrayLength( barr);
jbyte* ba =env->GetByteArrayElements(barr, JNI_FALSE);
if (alen > 0) {
rtn = (char*)malloc(alen + 1);
memcpy(rtn, ba, alen);
rtn[alen] = 0;
}
env->ReleaseByteArrayElements( barr, ba, 0);
return rtn;
}
//创建docx文件压缩包
jobject createOPCPackage(JNIEnv* env, const char* strpath)
{
jclass OPCPackageClass = env->FindClass("org/apache/poi/openxml4j/opc/OPCPackage");
if (OPCPackageClass == NULL) {
fprintf(stderr, "createOPCPackage::FindClass failed\n");
return NULL;
}
else {
fprintf(stderr, "createOPCPackage::FindClass success\n");
}
jmethodID createId = env->GetStaticMethodID(OPCPackageClass, "create",
"(Ljava/lang/String;)Lorg/apache/poi/openxml4j/opc/OPCPackage;");
if (createId == 0) {
fprintf(stderr, "createOPCPackage::GetMethodID failed\n");
return NULL;
}
jstring strPath = stoJstring(env, strpath);
//jobject strencode = env->NewObject(OPCPackageClass, createId, strPath);
//if (!strencode)
// return NULL;
jobject objOPCPac = (jobject)env->CallStaticObjectMethod(OPCPackageClass, createId, strPath);
if (objOPCPac == NULL)
{
fprintf(stderr, "objOPCPac::CallStaticObjectMethod failed\n");
return NULL;
}else{
fprintf(stderr, "objOPCPac::CallStaticObjectMethod success\n");
}
return objOPCPac;
}
int _tmain(int argc, _TCHAR* argv[])
{
int res;
long status;
JavaVMInitArgs vm_args;
JavaVMOption options[3];
JavaVM *jvm = NULL;
JNIEnv *env = NULL;
RtlZeroMemory(&vm_args, sizeof(JavaVMInitArgs));
/*设置初始化参数*/
options[0].optionString = "-Djava.compiler=NONE"; //Disabled JIT
options[1].optionString = "-Djava.class.path=.;F:/poi-4.1.0/poi-4.1.0.jar;F:/poi-4.1.0/poi-ooxml-4.1.0.jar;F:/poi-4.1.0/poi-scratchpad-4.1.0.jar;F:/poi-4.1.0/poi-ooxml-schemas-4.1.0.jar;\
F:/poi-4.1.0/lib/activation-1.1.1.jar;F:/poi-4.1.0/lib/commons-codec-1.12.jar;F:/poi-4.1.0/lib/commons-collections4-4.3.jar;F:/poi-4.1.0/lib/commons-compress-1.18.jar;\
F:/poi-4.1.0/lib/commons-logging-1.2.jar;F:/poi-4.1.0/lib/commons-math3-3.6.1.jar;F:/poi-4.1.0/lib/jaxb-api-2.3.0.jar;F:/poi-4.1.0/lib/jaxb-core-2.3.0.1.jar;\
F:/poi-4.1.0/lib/jaxb-impl-2.3.0.1.jar;F:/poi-4.1.0/lib/junit-4.12.jar;F:/poi-4.1.0/lib/log4j-1.2.17.jar;F:/poi-4.1.0/ooxml-lib/curvesapi-1.06.jar;F:/poi-4.1.0/ooxml-lib/xmlbeans-3.1.0.jar;";
options[2].optionString = "-verbose:NONE";
vm_args.version = JNI_VERSION_1_8;
vm_args.nOptions = 3;
vm_args.options = options;
vm_args.ignoreUnrecognized = JNI_TRUE;
// Load jvm.dll
DWORD dwErr1 = GetLastError();
HINSTANCE hInstance = LoadLibrary("C:\\Program Files (x86)\\Java\\jdk1.8.0_211\\jre\\bin\\client\\jvm.dll");
DWORD dwErr = GetLastError();
if (hInstance == NULL)
return false;
_CreateJavaVM m_CreateJavaVM = (_CreateJavaVM)GetProcAddress(hInstance, "JNI_CreateJavaVM");
res = (*m_CreateJavaVM)(&jvm, (void**)&env, &vm_args);
if (res < 0)
return -1;
// Find the class
jclass XWPFDocument = env->FindClass("org/apache/poi/xwpf/usermodel/XWPFDocument");
jclass XWPFParagraph = env->FindClass("org/apache/poi/xwpf/usermodel/XWPFParagraph");
jclass OPCPackage = env->FindClass("org/apache/poi/openxml4j/opc/OPCPackage");
jclass XWPFRun = env->FindClass("org/apache/poi/xwpf/usermodel/XWPFRun");
jclass FileInputStream = env->FindClass("java/io/FileInputStream");
jclass FileOutputStream = env->FindClass("java/io/FileOutputStream");
jclass InputStream = env->FindClass("java/io/InputStream");
jclass POIXMLDocument = env->FindClass("org/apache/poi/ooxml/POIXMLDocument");
if (InputStream == NULL) {
fprintf(stderr, "InputStream::FindClass failed\n");
}
else {
fprintf(stderr, "InputStream::FindClass success\n");
}
if (FileOutputStream == NULL) {
fprintf(stderr, "FileOutputStream::FindClass failed\n");
}
else {
fprintf(stderr, "FileOutputStream::FindClass success\n");
}
//获取方法FileInputStream的ID
jmethodID streammid = env->GetMethodID(FileInputStream, "<init>", "(Ljava/lang/String;)V");
if (streammid == 0) {
fprintf(stderr, "FileInputStream::GetMethodID failed\n");
return -1;
}
else {
fprintf(stderr, "FileInputStream::GetMethodID success\n");
}
jstring strPath2 = stoJstring(env, "F:/CallPoi.docx");
jobject fileStreamObj = env->NewObject(FileInputStream, streammid, strPath2);
if (fileStreamObj == NULL) {
fprintf(stderr, "fileStreamObj failed\n");
jvm->DestroyJavaVM();
fprintf(stdout, "Java VM destory.\n");
return -1;
}
else {
fprintf(stderr, "StreamObj success\n");
}
// jobject inStreamObj = env->NewObject(InputStream, streammid, strPath2);
//获取方法createParagraph的ID
jmethodID mid = env->GetMethodID(XWPFDocument, "createParagraph", "()Lorg/apache/poi/xwpf/usermodel/XWPFParagraph;");
//if (mid == 0) {
// fprintf(stderr, "createParagraph::GetMethodID failed\n");
// return -1;
//}
//else {
// fprintf(stderr, "createParagraph::GetMethodID success\n");
//}
//获取方法XWPFDocument构造ID
jmethodID gzmid = env->GetMethodID(XWPFDocument, "<init>", "(Ljava/io/InputStream;)V");
if (env->ExceptionCheck()) {
// 检查JNI调用是否有引发异常
env->ExceptionDescribe();
env->ExceptionClear(); // 清除引发的异常,在Java层不会打印异常的堆栈信息
env->ThrowNew(env->FindClass("java/lang/Exception"), "JNI抛出的异常!");
return -1;
}
//创建一个文件包
jobject packageObj = createOPCPackage(env, "F:/callPoiOpreate.docx");
//新建一个文档
jobject docxObj = env->NewObject(XWPFDocument, gzmid, fileStreamObj);
//创建一个段落
jobject paragraphObj = (jobject)env->CallObjectMethod(docxObj, mid);
jmethodID setTextId = env->GetMethodID(XWPFRun, "setText", "(Ljava/lang/String;)V");
//一个XWPFRun代表具有相同属性的一个区域。
jmethodID createRunId = env->GetMethodID(XWPFParagraph, "createRun", "()Lorg/apache/poi/xwpf/usermodel/XWPFRun;");
if (env->ExceptionCheck()) {
// 检查JNI调用是否有引发异常
env->ExceptionDescribe();
env->ExceptionClear(); // 清除引发的异常,在Java层不会打印异常的堆栈信息
env->ThrowNew(env->FindClass("java/lang/Exception"), "JNI抛出的异常!");
return -1;
}
jobject XWPFRunObj = (jobject)env->CallObjectMethod(paragraphObj, createRunId);
if (XWPFRunObj == NULL) {
fprintf(stderr, "paragraphObj CallObjectMethod failed\n");
jvm->DestroyJavaVM();
}
else {
fprintf(stderr, "paragraphObj CallObjectMethod success\n");
}
//设置文档内容
jstring textStr = stoJstring(env, "222223333 hello");
env->CallObjectMethod(XWPFRunObj, setTextId, textStr);
if (XWPFRunObj == NULL) {
fprintf(stderr, "paragraphObj failed\n");
jvm->DestroyJavaVM();
}
else {
fprintf(stderr, "3333 succcess\n");
}
jmethodID writemid = env->GetMethodID(XWPFDocument, "write", "(Ljava/io/OutputStream;)V");
if (env->ExceptionCheck()) {
// 检查JNI调用是否有引发异常
env->ExceptionDescribe();
env->ExceptionClear(); // 清除引发的异常,在Java层不会打印异常的堆栈信息
env->ThrowNew(env->FindClass("java/lang/Exception"), "JNI抛出的异常!");
return -1;
}
fprintf(stdout, "writemid success.\n");
jstring strsavePath2 = stoJstring(env, "F:/CallPoi.docx");
jmethodID FileOutputStreammid = env->GetMethodID(FileOutputStream, "<init>", "(Ljava/lang/String;)V");
jobject fileoutStreamObj = env->NewObject(FileOutputStream, FileOutputStreammid, strsavePath2);
env->CallObjectMethod(docxObj, writemid, fileoutStreamObj);
if (env->ExceptionCheck()) {
// 检查JNI调用是否有引发异常
env->ExceptionDescribe();
env->ExceptionClear(); // 清除引发的异常,在Java层不会打印异常的堆栈信息
env->ThrowNew(env->FindClass("java/lang/Exception"), "JNI抛出的异常!");
return -1;
}
jmethodID closemid = env->GetMethodID(XWPFDocument, "close", "()V");
env->CallObjectMethod(docxObj, closemid);
/*释放虚拟机资源*/
jvm->DestroyJavaVM();
FreeLibrary(hInstance);
return 0;
}
其中options[1].optionString = "-Djava.class.path=需要改为自己下载的poi的jar包路径,HINSTANCE hInstance = LoadLibrary(“C:\Program Files (x86)\Java\jdk1.8.0_211\jre\bin\client\jvm.dll”);需要改为自己的java下的路径。可以在新的文本中写入2222222.