利用Minidx Extract-Text Com组件从doc,Xls,Pdf……等读取文本内容VC Demo

folder-find-48x48利用Minidx Extract-Text Com组件从Word,Xls,Pdf……等文件中读取文本内容》中具体的说明了Vb.Net中调用Minidx Extract-Text Com组件对Word,Excel,Pdf等各种文件进行文本抽取的用法。结果很多人都发邮件过来询问C++中如何调用(一些邮件会被Gmail判断为垃圾邮件……强烈建议有问题直接在本文后面留言或在这里提问,这样也可以减轻一点我的工作量,不必挨个回复)。抽空作了一个VC的Demo,工程用VS2005创建的,Unicode版本。下面对Demo稍微做一些说明,一些基本原理直接参照《利用Minidx Extract-Text Com组件从Word,Xls,Pdf……等文件中读取文本内容》就可以了,这里不再重复。

●Demo(VC++)源代码从这里下载(相关文档资料分类中的“Doc,Xls,Pdf等文件中抽取文本的Com组件及Demo(VC++)源代码”)

●执行Demo

①、双击run.bat执行,注册Com组件

DllRegisterServer

②、双击demo_vc\release或者demo_vc\debug目录下的demo_vc.exe

demo-Vc

③、点“File”,选择对象文件(ex: 从demo_vc\test-data中选择)

select-File

④、选中文件,查看抽取文本结果。(下面分别是中日英Word的抽取结果)

Chinese Japanese

English

注意:抽取文本对象文件需要有读写权限,正在编辑中的文件抽取文本时可能会出错。

●实际调用方法:

①、复制下面三个文件到自己工程的相应目录下

・ExtractText.dll
・ExtractText.h
・ExtractText_i.c

②、在需要的文件中用下面的代码引入

#include “ExtractText.h”
#include “ExtractText_i.c”

③、抽取文本部分代码:

   1:  ITextExtractor *te = NULL;
   2:  // Declare and HRESULT and a pointer to the Simple_ATL interface
   3:  HRESULT            hr;
   4:   
   5:  // Now we will intilize COM
   6:  hr = CoInitialize(0);
   7:  BSTR fileName = ::SysAllocString(strFileName);
   8:  if(SUCCEEDED(hr))
   9:  {
  10:  hr = CoCreateInstance( CLSID_TextExtractor, NULL, CLSCTX_INPROC_SERVER,
  11:  IID_ITextExtractor, (void**) &te);
  12:   
  13:  hr = te->ExtractText(fileName, (long)lFileSize, &cval);
  14:  if( cval ) txt_extract_text.SetWindowText(cval);
  15:              
  16:  hr = te->Release();
  17:  }
  18:  // Uninitialize COM
  19:  CoUninitialize();

当然,也可以通过GetProcAddress的方式导入函数,函数的接口请参照ExtractText.h,LoadLibrary方式的使用方法也很简单,有兴趣的可以自己做着试试看,这里不再重复说明了。同样的,有什么问题可以直接在这里留言或者在Minidx帮助论坛发贴寻找帮助。该模块可用于任何商业和非商业的用途,如果你愿意的话,可以发一个邮件给我告诉我这一模块被用在了你的项目中,那么当你取得成功的时候,我也可以向我的朋友们吹嘘一下,当然这不是必需的,:)

86 thoughts on “利用Minidx Extract-Text Com组件从doc,Xls,Pdf……等读取文本内容VC Demo”

  1. 这个程序的确很强大,非常感谢。我的vs2005完全可以提取pdf的内容,现在我想把您上面写的文本内容提取部分的代码修改成一个函数,这个函数:以文件路径为参数,能够把文件中的文本内容提取出来然后保存到一个文本文档中去。能不能帮我写一下,非常感谢!

  2. 为什么我运行的时候总是出现这个错误呢?
    demo_vc.exe 中的 0x004ecabb 处未处理的异常: 0xC0000005: 读取位置 0x00000000 时发生访问冲突

  3. 我运行demo_vc.exe 时候。
    也有 0×004ecabb 处未处理的异常: 0xC0000005: 读取位置 0×00000000 时发生访问冲突
    这个问题。

    并且,我把上述代码封装成一个函数或类,连续做一个目录下的很多文件时,一般做到第4~5个文件时,提取的文本就不对了,请多指教!!

    代码如下:

    int CToTxtDlg::GetTxt(wchar_t *infile,char *TxtBuf)
    {
    ITextExtractor *m_pTE;
    HRESULT m_hr;
    BSTR cval = NULL; // extracted text
    ULONGLONG lFileSize = 0; // file size
    CString strFileName;
    DWORD dwnum=0;

    /////////////////
    m_pTE = NULL;
    m_hr = CoInitialize(0);
    if(SUCCEEDED(m_hr))
    {
    m_hr = CoCreateInstance( CLSID_TextExtractor, NULL, CLSCTX_INPROC_SERVER,IID_ITextExtractor, (void**) &m_pTE);
    }
    if(SUCCEEDED(m_hr))
    {
    m_hr = CoCreateInstance( CLSID_TextExtractor, NULL, CLSCTX_INPROC_SERVER,
    IID_ITextExtractor, (void**) &m_pTE);
    }

    /////////
    strFileName=infile;
    BSTR fileName =::SysAllocString(strFileName);

    if( m_pTE != NULL )
    {
    m_hr = m_pTE->ExtractText(fileName, (long)lFileSize, &cval);
    ///当多次连续做多个文件提取时,这个cval值就不对了。

    if(cval!= NULL )
    {
    DWORD dwnum=WideCharToMultiByte(CP_OEMCP,NULL,cval,-1,NULL,0,NULL,FALSE);
    // char *txt=new char[dwnum+1];
    WideCharToMultiByte(CP_OEMCP,NULL,cval,-1,TxtBuf,dwnum,NULL,FALSE);
    }
    m_hr =m_pTE->Release();
    }

    CoUninitialize();

    return dwnum;
    }

    int CToTxtDlg::GetNextData(wchar_t *filename)
    {
    CFileFind finder_path;
    bool flag_getdata=0;
    CString gsh_path;
    CString zt_out;

    gsh_path.Format(_T(“%s\\*.*”),”d:\\data);
    flag_getdata = finder_path.FindFile((LPCTSTR)gsh_path);
    while(flag_getdata)
    {
    flag_getdata= finder_path.FindNextFile();
    if(finder_path.IsDots())continue;
    if(!finder_path.IsDirectory())
    {
    swprintf(filename,_T(“d:\\data\\%s”),finder_path.GetFileName());

    char *buf=new char[10240000];
    memset(buf,0,sizeof(buf));
    GetTxt(filename,buf);
    ///当多次连续做多个文件提取时,这个BUF值就不对了。

    free(buf);
    }
    }
    finder_path.Close();

    return 1;
    }

  4. 上面的有几个地方拷贝到这里时错了
    int CToTxtDlg::GetNextData(wchar_t *filenamee)
    {
    CFileFind finder_path;
    bool flag_getdata=0;
    CString gsh_path;
    CString zt_out;

    gsh_path.Format(_T(”%s\\*.*”),”d:\\data”);

    但不是这些问题引起的,

  5. 你先检查一下是否其他什么地方内存没有释放?
    因为dll本身应该没什么问题,我的一个应用中一次性处理过几十万个文件,并没有出错。

    如果检查下来还是有问题的话请留言, :)

  6. 还是不行,我做了个简单的连续调用,问题及代码全部在下面:

    在调试时,输出窗口还是报两个警告问题:
    (1)test.exe 中的 0x7c812aeb 处最可能的异常: Microsoft C++ 异常: 内存位置 0x071bef34 处的 _ASExceptionInfo
    (2)test.exe 中的 0x7d44bfe4 处最可能的异常: 0xC0000005: 读取位置 0x07031ef0 时发生访问冲突

    程序可以一直运行下去,但是连续做到第4~5个文件时,获取的cval值错误(见下面代码行注释)
    代码全部如下:
    // test.cpp : 定义控制台应用程序的入口点。
    #include “stdafx.h”
    #include “test.h”
    #include “ExtractText_i.c”
    #include “ExtractText.h”
    int GetFileTxt(wchar_t *infile,char *TxtBuf)
    {
    BSTR cval = NULL; // extracted text
    BSTR fileName= NULL;
    ULONGLONG lFileSize = 0; // file size
    CString strFileName;
    DWORD dwnum=0;
    ITextExtractor *m_pTE=NULL;
    HRESULT m_hr=NULL;
    m_pTE = NULL;
    m_hr = CoInitialize(0);
    if(SUCCEEDED(m_hr))
    {
    m_hr = CoCreateInstance( CLSID_TextExtractor, NULL,CLSCTX_INPROC_SERVER,IID_ITextExtractor, (void**) &m_pTE);
    }
    /////////
    strFileName=infile;
    fileName =::SysAllocString(strFileName);
    if( m_pTE != NULL )
    {
    m_hr = m_pTE->ExtractText(fileName, (long)lFileSize, &cval);
    /////连续做到第4~5个文件时,获取的cval值错误
    if(cval!= NULL )
    {
    dwnum=WideCharToMultiByte(CP_OEMCP,NULL,cval,-1,NULL,0,NULL,FALSE);
    WideCharToMultiByte(CP_OEMCP,NULL,cval,-1,TxtBuf,dwnum,NULL,FALSE);
    }
    }
    m_hr =m_pTE->Release();
    CoUninitialize();
    return dwnum;
    }
    int main(int argc, char* argv[])
    {
    wchar_t inname[256];
    CFileFind finder_txtpath;
    BOOL flag_gettxtdata=0;
    int buf_len=0,buff_len=0;
    CString gsh_txtpath;
    char *buf=new char[102400000];
    memset(buf,0,sizeof(buf));
    gsh_txtpath=_T(“D:\\data\\ToTxtPath\\*.*”);
    flag_gettxtdata = finder_txtpath.FindFile((LPCTSTR)gsh_txtpath);
    while(flag_gettxtdata)
    {
    flag_gettxtdata= finder_txtpath.FindNextFile();
    if(finder_txtpath.IsDots())continue;

    if(!finder_txtpath.IsDirectory())//非目录
    {
    swprintf(inname,_T(“D:\\data\\ToTxtPath\\%s”),finder_txtpath.GetFileName());
    buff_len=GetFileTxt(inname,buf);
    }
    }
    finder_txtpath.Close();
    free(buf);
    return 0;
    }

    能不能把上述代码帮我测一下,非常感谢!

  7. 还有一个问题,我现在要提取office文档、RAR文档。
    但装了RAR过滤插件后,所有的office文档提取全部错误,好像文件加载不上去。

    请多指教!!

  8. 如果单纯做word/XLS/ppt/TXT/HTM等文件,我现在已经知道了问题所在,都可以实现没问题,现在就是加上RAR就会出问题。

    有什么办法?

  9. 你用的是什么RAR插件?
    像这样的问题一般都是iFilter插件引起的,可以从这方面着手。

  10. 另外,我试了一下,插件rarfiltereval1_0.exe。
    好像好一点,但装上去了以后,还是有好多word不能加载

  11. 我这边用的都是自己开发的iFilter,所以挺难给你什么建议的

    RAR要处理的东西其实相对还是挺多的,有可能的话自己开发一个那样会方便很多,功能上自己可以控制的也会多很多。

  12. 我也是自己写的啊,不过是调用的windows/rar提供的接口函数,但就是有这个问题,如果启用两个进程处理这两类,就不会有这个问题

  13. 请问下,我下载了iFilter,但是我公司的经理说最好不要客户安装额外的软件,所以我想直接注册解压后有个DLL:PDFFilt.dll,我直接注册这个dll文件,而不安装iFilter软件,这样子可以吧?

  14. 程序的实现上只要文件齐全自己注册不会有什么问题

    不过最好察看一下人家的License条款是否允许你捆绑发布。

  15. 你好,我发现一个问题:我在读取一些字符数比较小的文本时,能够调用成功,但是我由于要测试多模字符串匹配算法的效率的时候用到了300多M的文本,发现hr = pIte->ExtractText(bFileName, lTextSize, &p_tFileText);的p_tFileText总是为NULL,是否需要分隔文档?TCHAR* p_tFileText = new TCHAR[MAX_PATH * 2];或者不断增加p_tFileText 的宽度?

  16. 有没有提供循环遍历的方式啊?能够记录指针位置,每次从指针位置开始读取。这样就不用分割文档了。。。

  17. 看了你的vc2005的源代码,我改为声明TCHAR* p_tFileText;不再为一个静态数组,但是一样返回空指针哦

  18. 你的这个控件,在读取doc,pdf时有时候内存增长了,却不释放。一直这样读下去内存不停的增长,有没有什么好的办法解决,还有一个问题?有没有支持office2007的docx读取控件

  19. 能否把ExtractText.dll控件的源码提供我们学习学习。谢谢
    这个里面好像有内存申请了没有释放,

  20. 你好,我在使用过程中发现ExtractText.dll好像有内存泄露问题,这是我源码:
    BSTR cval; // extracted text
    LPTSTR re;
    ULONGLONG lFileSize; // file size
    ITextExtractor *te = NULL;
    HRESULT hr; // Declare and HRESULT and a pointer to the Simple_ATL interface

    hr = CoInitialize(0); // Now we will intilize COM
    BSTR fileName = _com_util::ConvertStringToBSTR(strFileName);
    if(SUCCEEDED(hr))
    {
    hr = CoCreateInstance( CLSID_TextExtractor, NULL, CLSCTX_INPROC_SERVER,IID_ITextExtractor, (void**) &te);//尝试调用COM组件
    if (hr == REGDB_E_CLASSNOTREG)//如果组件未注册则使用MyCoCreateInstance直接调用
    {
    hr = MyCoCreateInstance(“ExtractText.dll”, CLSID_TextExtractor, NULL,IID_ITextExtractor, (void**) &te);
    }
    hr = te->ExtractText(fileName, (long)lFileSize,&cval);
    hr = te->Release();
    }
    CoUninitialize();
    ::SysFreeString(fileName);
    if(cval)
    {
    re = _com_util::ConvertBSTRToString(cval);
    ::SysFreeString(cval);
    return re;
    }
    return NULL;
    }
    其中当debug到 hr = te->ExtractText(fileName, (long)lFileSize,&cval);这一步时系统出现first exception Access Violation错误,当进行全盘搜索所有文件时,内存会占用的几百M,请您帮忙看一下,谢谢。其中re已经在函数外部用delete[]进行释放。

  21. 请问楼主, 我在windows 7里vs2010,编译,
    bat注册不了,试着写一个测试例子,显示 access violation 。
    楼主能指点下吗?

    #include “stdafx.h”
    #include

    #include “ExtractText.h”
    #include “ExtractText_i.cpp”

    int main(int argc, char *argv[])
    {

    TCHAR *cval = NULL; // extracted text
    ULONGLONG lFileSize = 0; // file size

    ITextExtractor *te = NULL;
    // Declare and HRESULT and a pointer to the Simple_ATL interface
    HRESULT hr;
    // Now we will intilize COM
    hr = CoInitialize(0);

    const OLECHAR* file = L”English.doc”;
    //typedef wchar_t WCHAR; // wc, 16-bit UNICODE character
    BSTR fileName = ::SysAllocString(file);
    if(SUCCEEDED(hr))
    {
    hr = CoCreateInstance( CLSID_TextExtractor, NULL, CLSCTX_INPROC_SERVER,
    IID_ITextExtractor, (void**) &te);

    hr = te->ExtractText(fileName, (long)lFileSize, &cval);

    if( cval ) //txt_extract_text.SetWindowText(cval);
    std::cout<< "extracted text: "<< cval <Release();
    }
    // Uninitialize COM
    CoUninitialize();

    return 0;
    }

  22. Unhandled exception at 0x774515de in word2text.exe: 0xC0000005: Access violation reading location 0x00000000.

    (void**) &te 这里te的指针指向 : 0x0046f8bc

  23. 请问楼主能不能指点 下, 如何在windows 2008server R2或者windows7中注册ExtractText.dll这个组件。

    因为注册的时候显示:
    make sure the binary is stored at the specific path or debug it to check for problems with the binary or dependent .DLL files
    The specific module could not be found

  24. 多谢楼主,还有个问题想请教下。
    在windows7上运行,测试没问题。
    但是整合的时候出现个exception:

    hr = te->ExtractText(fileName, (long)lFileSize, &cval); // trace 到这行都没问题。但是函数return value是,class not registered.
    指针的位置是0x80040154.

    下一步捕获exception.
    __try {
    return siteExtractOneIni(inSiteIniFilename);
    }
    __except(EXCEPTION_EXECUTE_HANDLER )
    {
    ULONG rv = GetExceptionCode (); //– Code:$%08x
    error(“EXCEPTION calling siteExtractOneIni(%s) Code:$%08x”,inSiteIniFilename,rv);
    }
    return false;

    好像是和以前注册的com冲突了? 不知道具体是为啥。能不能指点下?
    是与singleton有关吗? 多谢

Leave a Reply

Your email address will not be published. Required fields are marked *