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

By Minidxer | January 10, 2008

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帮助论坛发贴寻找帮助。该模块可用于任何商业和非商业的用途,如果你愿意的话,可以发一个邮件给我告诉我这一模块被用在了你的项目中,那么当你取得成功的时候,我也可以向我的朋友们吹嘘一下,当然这不是必需的,:)

Topics: Minidx相关 | 80 Comments » | Tags: , , , , , , , , , ,

你可能还对下列文章感兴趣:

80 comments | Add One

  1. sofish - 01/10/2008 at 6:45 pm

    有时候这里访问变得很慢…

  2. Minidxer - 01/10/2008 at 7:02 pm

    @sofish
    国内的国际带宽限制吧。
    我这里一直都是很快的……非常快

  3. !CnSoLoer - 01/10/2008 at 8:29 pm

    绝对的高手,因为我一点都看不懂,啊哈哈,服务器跟人都在日本?

  4. Minidxer - 01/10/2008 at 8:37 pm

    @!CnSoLoer
    失败……绝对的失败,呵呵
    服务器在美国,Godaddy的,开始的时候拜托朋友们测试过一些国家和地区的访问速度,都说速度很快……
    人在东京

    @sofish
    你那里每次访问这里速度都很慢吗?

  5. sorryle - 01/10/2008 at 9:48 pm

    我国内网通的,一直都很快。

  6. !CnSoLoer - 01/10/2008 at 10:06 pm

    东京好啊,听同学说日本人从来不穿衣服的,因为丫长这么大还没有见过穿衣服的日本人,啊哈哈

  7. Minidxer - 01/10/2008 at 10:43 pm

    @sorryle
    网通的国际出口好像比较快,我访问网通的站点速度也不错.

    @!CnSoLoer
    从来不穿衣服…美女的话当然没问题,dafeipo或者laotaitai,那可让人受不了……

  8. Qipeng Tian - 03/20/2008 at 9:14 am

    不晓得windows 2003是否支持,我在xp上测试没问题,但是在windows 2003上开发时,报以下错误

    未处理 System.Runtime.InteropServices.COMException
    Message=”检索 COM 类工厂中 CLSID 为 {A2083621-FD63-4F37-ABF3-A4A4FEB0EFD4} 的组件时失败,原因是出现以下错误: 80040154。”
    Source=”TQP.ExtractText”
    ErrorCode=-2147221164
    StackTrace:
    在 TQPExtractText.MyIFilter..ctor()
    在 DataDig.MainFrm.运行ToolStripMenuItem1_Click(Object sender, EventArgs e) 位置 D:\Mike的程序\数据挖掘\DataDig\DataDig\MainFrm.cs:行号 122
    在 System.Windows.Forms.ToolStripItem.RaiseEvent(Object key, EventArgs e)
    在 System.Windows.Forms.ToolStripMenuItem.OnClick(EventArgs e)
    在 System.Windows.Forms.ToolStripItem.HandleClick(EventArgs e)
    在 System.Windows.Forms.ToolStripItem.HandleMouseUp(MouseEventArgs e)
    在 System.Windows.Forms.ToolStripItem.FireEventInteractive(EventArgs e, ToolStripItemEventType met)
    在 System.Windows.Forms.ToolStripItem.FireEvent(EventArgs e, ToolStripItemEventType met)
    在 System.Windows.Forms.ToolStrip.OnMouseUp(MouseEventArgs mea)
    在 System.Windows.Forms.ToolStripDropDown.OnMouseUp(MouseEventArgs mea)
    在 System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
    在 System.Windows.Forms.Control.WndProc(Message& m)
    在 System.Windows.Forms.ScrollableControl.WndProc(Message& m)
    在 System.Windows.Forms.ToolStrip.WndProc(Message& m)
    在 System.Windows.Forms.ToolStripDropDown.WndProc(Message& m)
    在 System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
    在 System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
    在 System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
    在 System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
    在 System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
    在 System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
    在 System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
    在 System.Windows.Forms.Application.Run(Form mainForm)
    在 DataDig.Program.Main() 位置 D:\Mike的程序\数据挖掘\DataDig\DataDig\Program.cs:行号 17
    在 System.AppDomain.nExecuteAssembly(Assembly assembly, String[] args)
    在 System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
    在 Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
    在 System.Threading.ThreadHelper.ThreadStart_Context(Object state)
    在 System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
    在 System.Threading.ThreadHelper.ThreadStart()

  9. Minidxer - 03/20/2008 at 9:57 am

    @Qipeng Tian
    看错误信息应该是找不到这个Com组件,上面的第一步注册时是否正常?

  10. pp - 03/25/2008 at 5:06 pm

    正在生成代码…
    正在编译…
    ExtractText_i.c
    e:\lab\\ExtractText_i.c(66) : warning C4005: “MIDL_DEFINE_GUID” : 宏重定义
    e:\lab\ExtractText_i.c(43) : 参见“MIDL_DEFINE_GUID”的前一个定义
    e:\lab\ExtractText_i.c(83) : fatal error C1010: 在查找预编译头指令时遇到意外的文件结尾
    在vc2005上测试没有问题,在2003上却冒出这个问题。
    不知道哪里没设置好。包含”stdfax.h”也不行。

  11. Minidxer - 03/25/2008 at 5:23 pm

    这个错误一般就是没有包含#include “stdafx.h”吧。
    cpp文件中都已经 #include “stdafx.h” 还是一样的错误的话,那在 ExtractText_i.c 中也加入试试看。

  12. Minidxer - 03/25/2008 at 5:27 pm

    还有一个方法是
    工程的 “创建\使用预编译头”属性改为“不使用预编译头”

  13. pp - 03/25/2008 at 10:03 pm

    谢谢,vc2003中加入stdafx.h后,ExtractText_i.c(23):fatal error C1853: “Debug/desktop-search4w.pch”预编译头文件来自编译器的早期版本,或者预编译头为 C++ 而在 C 中使用它(或相反)
    是不是vs2003中少了什么设置,ExtarctTetx_i.c这个文件在vs2005中貌似不参加编译的,因为build中没有complie选项,但是在vs2003中却参加了编译。不知是怎么回事。

  14. Minidxer - 03/25/2008 at 10:28 pm

    “不使用预编译头”的设置呢?也不可行吗?
    这个其实纯粹是编译器上的区别,和Com组件应该没有关系的……
    还是不行的话过两天我抽空做一个VS2003的DEMO放出来吧。

  15. Minidxer - 03/29/2008 at 9:34 pm

    VS2003的工程请参照:
    http://blog.minidx.com/2008/03/29/655.html

  16. pp - 04/2/2008 at 8:37 pm

    我在程序中使用抽取文本的com组件在函数中能能够能够使用,因为要多次调用现在我想在一个类中封装使用以减少初始化的开销
    ITextExtractor *te = NULL;
    HRESULT hr;
    hr = CoInitialize(0);

    if(SUCCEEDED(hr))
    {
    hr = CoCreateInstance( CLSID_TextExtractor, NULL, CLSCTX_INPROC_SERVER, IID_ITextExtractor, (void**) &te);
    }
    被封装进类的构造函数中,hr,te为成员变量
    CoUninitialize();
    hr = te->Release();
    被封装进析构函数中。
    但是我在其它成员函数中调用 hr = te->ExtractText(fileName, (long)lFileSize, &cval);失败,调试的时候te指向一个地址。但是抽取
    不了内容,不知为何。
    我猜想是不是CoCreateInstance()调用后,te指向的地址是不是变动了,是不是需用重新使用什么queryinterface()函数?还望指教?谢谢!

  17. Minidxer - 04/2/2008 at 9:00 pm

    是不是你的封装类中stack和heap问题?
    方便的话把你写的这个部分代码让我看看

  18. pp - 04/3/2008 at 9:41 am

    CScan::CScan(void)
    {
    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);
    }
    }
    CScan::~CScan(void)
    {
    m_hr =m_pTE->Release();
    // Uninitialize COM
    CoUninitialize();
    }
    提取文本的成员函数:
    bool CScan::extractText(const tchar* path,char** content)
    {
    CString strFileName(path);

    BSTR fileName = strFileName.AllocSysString();
    BSTR cval = NULL; // extracted text
    // Now we will intilize COM
    m_hr = m_pTE->ExtractText(fileName, (long)1000, &cval);
    if (cval)
    {
    *content = _com_util::ConvertBSTRToString(cval);
    SysFreeString(cval);
    return true;
    }
    else return false;
    }
    调试到m_hr = m_pTE->ExtractText(fileName, (long)1000, &cval)时
    cval是空指针。

  19. Minidxer - 04/4/2008 at 8:54 am

    问题应该出在CoCreateInstance上吧,CoCreateInstance是系统只保存一个COM实例的时候使用的,并且Com组建只要初始化一次就可以了。创建多个的应该是CoGetClassObject,或者你可以用单一模式/单态模式(Singleton)实现试试看

    上面的分析我没有动手实际确认过,所以期待你的反馈。有时间的话我会做一个封装类的Sample发布。

  20. pp - 04/4/2008 at 11:49 am

    强烈赞扬老大这种精神。
    我就是用的单件模式实现cscan类的。实例通过静态public函数返回
    static CScan* getInstance()
    {
    static CScan INSTANCE;
    return &INSTANCE;
    }
    现在就是说:
    bool CScan::extractText(const tchar* path,char** content)
    {
    CString strFileName(path);
    BSTR fileName = strFileName.AllocSysString();
    BSTR cval = NULL; // extracted text

    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);
    }
    m_hr = m_pTE->ExtractText(fileName, (long)1000, &cval);

    m_hr =m_pTE->Release();
    // Uninitialize COM
    CoUninitialize();
    if (cval)
    {
    *content = _com_util::ConvertBSTRToString(cval);
    SysFreeString(cval);
    return true;
    }
    else return false;
    }
    这样是可以成功的,但是由于扫描调用函数太频繁。由于com对象不断创建释放。慢的难以忍受。
    所以想一次初始化,重复使用。从道理上讲是可以的,因为dll已经载入到进程内。但是简单把初始话封装到构造和析构函数行不通。问题肯定是出在cocreateInstance()函数身上。可能就是每次调用函数结束,cocreateInstance()返回的函数指针指向的空间被释放了?也就是上述中m_pTE指向的地址被释放了?
    不知道有没有其他的api防止这一点。
    还请指教。

  21. Minidxer - 04/13/2008 at 11:00 pm

    @pp
    参考下面的文章吧:

    http://blog.minidx.com/2008/04/13/712.html
    重复使用并没有问题.

  22. Zuckle8181 - 08/29/2008 at 4:34 pm

    我使用它,对eml中的文本信息进行提取,中文效果很好,可是日文,却显示乱码,请问怎么能使日文正常显示

  23. Minidxer - 08/29/2008 at 4:40 pm

    @Zuckle8181
    显示的时候你是用什么编码显示的?
    抽取出来的文本是Unicode编码的,ASCII模式下的话将会是乱码

  24. mybvc - 12/10/2008 at 2:40 pm

    你好,我用这个代码可以抽取office系列和文本系列,但不能抽取pdf,请问是什么原因呢?

    小弟最近被pdf抽取给难住了,试了很多种方法,pdfbox、itext、xpdf等等,都存在各种问题。承蒙指教,谢谢

  25. Minidxer - 12/10/2008 at 2:46 pm

    @mybvc
    可能你的机器上没有安装PDF的Ifilter吧
    到这里下载就可以了:
    http://www.adobe.com/support/downloads/detail.jsp?ftpID=2611

  26. go - 03/3/2009 at 11:56 am

    24#一样的问题,用c#实现了pdf的抽取,但是为什么装了PDF的Ifilter以后,您的Minidx File Manager还是无法实现预览呢?

  27. Minidxer - 03/3/2009 at 12:46 pm

    @go

    该组件是一个COM组件,如文中第一步那样,COM组件是需要注册才可以被调用的。
    Minidx File Manager的安装程序中自动执行了注册操作。 您可以尝试一下Minidx File Manager中是否可以读取DOC,XLS等文件的文本,如果可以读取DOC而无法读取PDF,那问题应该出在PDF的IFilter中,如果DOC也不可以读取,那可能您执行了卸载该COM组件的操作或者您的系统中注册COM的时候出了什么错误。

    如果是PDF的IFilter的问题,尝试着卸载系统中的PDF的IFilter,再重新安装一下应该就可以正常使用了。或者也可以尝试安装其他版本的PDF的IFilter

  28. go - 03/4/2009 at 9:18 am

    Minidx File Manager里面的doc,xls文档都可以读的,然后用c#的那个sample试了下(估计也是您写的),是可以读取pdf文档的。怀疑是不是版本问题了

  29. minidxer - 03/4/2009 at 9:54 am

    那有可能是两个COM的DLL冲突了。卸载掉Minidx File Manager再重新安装一下试试看~

  30. go - 03/4/2009 at 10:14 am

    果然可以了,谢谢。
    另外minidx.dat里面是纪录的文件的路径,还是把文件都放进去了阿?
    加载到application里的文件删掉了或者路径变了还是能看到的。

  31. minidxer - 03/4/2009 at 10:25 am

    二进制数据文件也是登陆到系统中的。 Minidx系统中使用了特殊的压缩算法,存储了二进制文件数据加上索引整体容量也不会很大

  32. go - 03/4/2009 at 10:47 am

    是把整个文件都压缩了存储的吗?我试了下把硬盘中的文件删掉了或者移到其他地方,还是可以查看文档内容,也可以用相应的软件打开的

  33. Minidxer - 03/4/2009 at 10:51 am

    是的,二进制文件,抽取出来的文本内容等,都分别进行了压缩处理。 原文件删除不影响系统中内容的。

  34. go - 03/4/2009 at 12:20 pm

    文件压缩好强大阿,只占了很少的空间。

    公司让我做的好象只记录路径,用了您这个突然想起这个路径变更的问题。。。
    难道要时刻监控这些文件,太没效率了吧。

  35. Minidxer - 03/4/2009 at 12:30 pm

    如果仅仅是纪录文件路径的话,可以对磁盘进行映射,一旦发生变动就可以捕捉到,处理效率还是挺高的。

  36. go - 03/4/2009 at 2:11 pm

    磁盘映射没做过啊,能不能说下大概的思路?

    minidx这个程序里面导入的文件都做了索引吗?检索文件内容好快啊

  37. Minidxer - 03/4/2009 at 2:24 pm

    各种开发语言都有自己的实现,Windows系统的话也可以调用系统API,不过没有尝试过,不知道效率怎么样,Windows系统大概下面这几个API可以用吧(没试过,需要确认)。用C或者C++的话自己创建磁盘映射表可能效率更高一些。
    FindFirstChangeNotification( );
    FindNextChangeNotification( );
    WaitForSingleObject( );

    minidx对可以提取文本的文件都作了索引

  38. Minidxer - 03/4/2009 at 2:26 pm

    忘记说了,原理都是先将磁盘中的文件作一个映射MAP,再监测这一MAP的改变情况

  39. go - 04/1/2009 at 11:54 am

    不知道为什么这两天读取pdf内容,关闭项目的时候就会出现”メモリはreadになることができませんでした”,读其他的文档好像就没事阿

  40. Minidxer - 04/1/2009 at 12:18 pm

    @go
    你用的应该是PDF IFilter 6.0吧, Adobe官方有申明这个版本的IFilter中存在内存释放的问题。

  41. go - 04/1/2009 at 12:24 pm

    好像是的,在网上就找到这个版本的下载。您知道有哪个版本可以解决这个问题吗?

  42. Minidxer - 04/1/2009 at 12:27 pm
  43. Minidxer - 04/1/2009 at 12:28 pm

    好像最新的8.0也没有这个问题,不过我没有尝试过

  44. go - 04/1/2009 at 3:27 pm

    谢谢,之前找了半天就找到6.0的,以为都差不多。
    英语不好太不方便了..

  45. Gump - 05/21/2009 at 9:53 am

    首先感谢Minidx,这个控件处理速度很快,不过在使用中有些小问题:

    对Word中带表格的内容提取有时会漏,有的漏近一半
    (word是用MS Office Word2003生成的,其中表格略带格式,如字体大小不一,颜色不一,有换行)。

    是否控件中有欠考虑的地方,期待答复^^

  46. Minidxer - 05/21/2009 at 9:24 pm

    @Gump
    可以做特殊处理,不过目前这个项目基本上已经停滞状态…

  47. Gump - 05/22/2009 at 8:17 am

    但是在大量文档中无法判断哪一个Word文档转换会漏,就无法进行特殊处理(除非一个一个打开看,汗…)

  48. Minidxer - 05/22/2009 at 8:48 am

    @Gump
    呃。。。我的意思是,可以在组件内增加这样的特殊处理,应该不会发生遗漏现象

  49. paodan - 08/19/2009 at 10:32 am

    只是打开文本,图片和表格打不开。

  50. long - 01/14/2010 at 4:45 pm

    在win7下 无法使用!
    没有返回值

  51. yuanyang - 02/27/2010 at 10:53 am

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

  52. Minidxer - 02/27/2010 at 10:57 am

    @yuanyang
    这个可以你自己实现的,调用的时候封装一下就可以了

  53. baypm - 04/14/2010 at 10:47 am

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

  54. cj - 04/23/2010 at 11:28 am

    为什么我读取doc文档可以成功,但是读取pdf文件的时候字符串为空了?

  55. Minidxer - 04/23/2010 at 11:30 am

    pdf需要安装PDF的iFilter

  56. ald - 04/23/2010 at 8:54 pm

    我运行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;
    }

  57. ald - 04/23/2010 at 8:57 pm

    上面的有几个地方拷贝到这里时错了
    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”);

    但不是这些问题引起的,

  58. Minidxer - 04/23/2010 at 9:02 pm

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

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

  59. Minidxer - 04/23/2010 at 9:05 pm

    另外,重复释放也有可能出这个错误

  60. ald - 04/23/2010 at 10:06 pm

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

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

    程序可以一直运行下去,但是连续做到第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;
    }

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

  61. ald - 04/26/2010 at 12:27 am

    好像与ifilter 的版本有关系

  62. teshorse - 04/26/2010 at 10:19 am

    : ) 正是我需要的,非常感谢!!

  63. ald - 04/26/2010 at 8:18 pm

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

    请多指教!!

  64. ald - 04/26/2010 at 8:21 pm

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

    有什么办法?

  65. minidxer - 04/26/2010 at 8:29 pm

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

  66. ald - 04/26/2010 at 8:31 pm

    用的是citeknet.rar.ifilter.setup-1.5.3.msi

  67. ald - 04/26/2010 at 8:33 pm

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

  68. minidxer - 04/26/2010 at 8:39 pm

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

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

  69. ald - 04/26/2010 at 8:52 pm

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

  70. cj - 04/27/2010 at 3:36 pm

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

  71. minidxer - 04/27/2010 at 3:40 pm

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

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

  72. cj - 05/3/2010 at 8:29 pm

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

  73. cj - 05/3/2010 at 8:35 pm

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

  74. cj - 05/3/2010 at 11:26 pm

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

  75. LYK - 05/6/2010 at 10:16 am

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

  76. LYK - 05/7/2010 at 3:21 pm

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

  77. Minidxer - 05/7/2010 at 3:23 pm

    @LYK
    该控件已经在成熟产品中应用了. 存在内存没释放的可能性非常小.

  78. conan - 07/26/2010 at 9:25 am

    你好,我在使用过程中发现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[]进行释放。

  79. wind - 03/27/2011 at 7:19 pm

    老大,什么时候放一个支持win7/windows 2008 server版的呢?期待中。。。

Trackbacks

Leave a Comment

Name(*):

E-Mail(*) :

Website :

Comments :

Search Posts