(来者有分)关于提取目录下eml文件或txt或xls文件中的电子邮件地址

sunsun123123 2005-07-22 12:51:32
如题,能否用vc代码实现,主要是算法问题。在vckbase中(http://www.vckbase.com/code/listcode.asp?mclsid=1&sclsid=103)也提到,不过经我测试漏洞很多,提取的地址很多是错误的。我的疑问有以下几个:
1、提取算法,最好有代码,没有代码有思路也不错。
2、递规搜索目录可能较慢,有不有更好的搜索目录下所有文件的算法。
3、用CFile打开eml文件或xls文件可以提取到正确的邮件地址吗?会不会不可读?
希望高手为我指点迷津。万分感谢!
...全文
516 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
AntonlioX 2005-07-22
  • 打赏
  • 举报
回复
试试正在表达式的类啊? vckbase里面有个人自己写的 boost开发库里面也有
realmiss 2005-07-22
  • 打赏
  • 举报
回复
这类对速度要求比较高的 建议直接采用API操作 不用mfc的类
sunsun123123 2005-07-22
  • 打赏
  • 举报
回复
今晚12:00以前结贴,没有实质内容的就平均散发喽。
sunsun123123 2005-07-22
  • 打赏
  • 举报
回复
顶一下,盼关注!
lake_wave 2005-07-22
  • 打赏
  • 举报
回复
我写的(主要是对上的修改)

void CMYDlg::BrowseDir(CString strDir)
{
CString strEffectMail(".-_0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
//以上是邮件@两边正确的字符集。当然还要考虑@右边是否有".";@左边是否为空等等情况。

m_list.ResetContent();

CFileFind finder;
CString szDir = strDir;

if(szDir.Right(1) != "\\")
szDir += "\\";

szDir += "*.*";

BOOL res = finder.FindFile(szDir);
while( res )
{
res = finder.FindNextFile();
if(finder.IsDirectory() && !finder.IsDots())
//为目录,IsDot不能少,好像是..或.目录。
{
CString strPath = finder.GetFilePath();
CString strFileName = finder.GetFileName();
BrowseDir( strPath );
}
else if(!finder.IsDirectory() && !finder.IsDots())
//不是目录,当然是文件了,处理关键。
{
CString strFileName = finder.GetFileName();
CString strFilePathName = finder.GetFilePath();
CString name = strFileName.Right(4);
if((name.Find(".eml") != -1) ||
(name.Find(".txt") != -1) ||
(name.Find(".dbx") != -1) )
{
CFile file;
if(!file.Open(strFilePathName,CFile::modeRead)) continue;
CString fstring = "";
char *readbuf ;
readbuf = fstring.GetBuffer(file.GetLength());
file.Read(readbuf ,file.GetLength());
file.Close();
fstring = readbuf;
fstring.ReleaseBuffer();
//fstring此时为要处理的文本文件等的内容了

CString s1 = "",s2 = "",s3 = "",s4 = "";

int pos1=0, pos2=0, pos3=0;

while((pos1 = fstring.Find("@")) != -1)
{
s1 = fstring.Left(pos1);
fstring.Delete(0,pos1+1);

s1.MakeReverse();

int s1size = s1.GetLength();
while(pos2 < s1size)
{
if(strEffectMail.Find(s1.GetAt(pos2)) == -1)
break;
pos2++;
}
s2 = s1.Left(pos2);
s2.MakeReverse();
//完成@左边,注意还要判断s1为空的情况,最后一起处理吧。

int fstringsize = fstring.GetLength();
while(pos3 < fstringsize)
{
if(strEffectMail.Find(fstring.GetAt(pos3)) == -1)
break;
pos3++;
}
s3 = fstring.Left(pos3);
// fstring.Delete(0,pos3);
//上句不删会出现异常错误,为什么?完成右边
//下面连接整个email帐号了,注意几个异常情况,看if判断条件
//s2为@左边,s3为@右边
if(s2!="" && (s3.Find(".")!=-1) && (s3.GetAt(0)!='@') && (s3.Right(1)!='.'))
{
s4 = s2 + "@" + s3;
if(s4.Find('@') == s4.ReverseFind('@'))
{
m_list.AddString(s4);
}
}
}

}
}
}
finder.Close();//关闭文件,不要忘了哟
}
lake_wave 2005-07-22
  • 打赏
  • 举报
回复
关注!
sunsun123123 2005-07-22
  • 打赏
  • 举报
回复
vckbase上的(http://www.vckbase.com/code/listcode.asp?mclsid=1&sclsid=103):我已稍加注释!

void CEAPDlg::BrowseDir(CString strDir)
{
CString flagstr(" \t\"<>\r\n[]{}:;=,'?#!`^$*%()");
//以上是不匹配帐号的值,基于错误值的判断
int bufsize = m_list.GetCount();
CString *Word = new CString [bufsize];
for(int i=0;i<bufsize;i++)
{
m_list.GetText(i,Word[i]);
//m_list是自建对话框类的成员:CListBox m_list;
}
//以上将M_list清空,感觉很笨,不如m_list.ResetContent();

//以下就和AntonlioX(做人要厚道)差不多了
CFileFind finder;
CString szDir = strDir;

if(szDir.Right(1) != "\\")
szDir += "\\";//路径最后加\
szDir += "*.*";

BOOL res = finder.FindFile(szDir);
while( res )
{
res = finder.FindNextFile();
if(finder.IsDirectory() && !finder.IsDots())
//为目录,IsDot不能少,msdn说好像是..或.目录。高手能否解释以下其细节。
{
CString strPath = finder.GetFilePath();
CString strFileName = finder.GetFileName();
BrowseDir( strPath );
}
else if(!finder.IsDirectory() && !finder.IsDots())
//不是目录,当然是文件了,处理关键
{
CString strFileName = finder.GetFileName();
CString strFilePathName = finder.GetFilePath();
CString name = strFileName.Right(4);
if((name.Find(".eml") != -1) ||
(name.Find(".txt") != -1) ||
(name.Find(".dbx") != -1) )
{
CFile file;
if(!file.Open(strFilePathName,CFile::modeRead)) continue;
CString fstring = "";
char *readbuf ;
readbuf = fstring.GetBuffer(file.GetLength());
file.Read(readbuf ,file.GetLength());
file.Close();
fstring = readbuf;
CString s1 = "",s2 = "",s3 = "",s4 = "";

int pos1=0,pos2=0,pos3=0,pos4=0;
while((pos1 = fstring.Find("@")) != -1)
{
s1 = fstring.Left(pos1);
fstring.Delete(0,pos1+1);
s1.MakeReverse();
if((pos2=s1.FindOneOf(flagstr)) != -1)
{
s2 = s1.Left(pos2);
s2.MakeReverse();
}
//以上处理@左边,将其倒置查找离@最近的不匹配值
if((pos3=fstring.FindOneOf(flagstr)) != -1)
{
s3 = fstring.Left(pos3);
}
//以上处理@右边,直接查找离@最近的不匹配值,我觉得应该在if的执行体中加fstring.Delete(0,pos3);
//但我加上后有时程序会出现异常错误
if(s2!="" && (s3.Find(".")!=-1))
{
s4 = s2 + "@" + s3;
m_list.AddString(s4);
}
//连接整个email帐号,加入到m_list中
}
}
}
}
finder.Close();//关闭文件
delete []Word;//释放new空间
}
sunsun123123 2005-07-22
  • 打赏
  • 举报
回复
邮件帐号的有效值
1、ChinaRen用户名长度为4-25位,可以是数字、字母(小写)、下划线,必须以字母开头。
2、网易163.com用户名由a~z的英文字母(不区分大小写)、0~9的数字、点、减号或下划线组成,长度为3~18个字符,例如:kyzy_001。
3、Yahoo! ID只能由 英文字母a~z、数字0~9、下划线 组成。Yahoo! ID的 起始字符 必须是 英文字母。如: example_2005。
4、sina不能用汉字,限用英文小写、数字、下划线、不区分大小写,不能单独使用数字,4-25个字符(包括4、25)

总结:
由上可知最合理的提取邮件帐号范围为:
emailaccounts == 45, 46, 95 ;
48 <= emailaccounts <= 57 ;
65 <= emailaccounts <= 90 ;
97 <= emailaccounts <= 122 。
于是查ASCII码表:
CString strEffectMail(".-_0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz") ;
sunsun123123 2005-07-22
  • 打赏
  • 举报
回复
感谢 AntonlioX(做人要厚道)!
不过你的这个算法我已经找到了^_^,跟vckbase上一样,我现在用的就是它,并且将其中提取邮件帐号的细节改了一下,但还是有些问题。
以下我把vckbase中的和我写的都贴出来,应该我的提取正确率要高一些,但是经我测试还是有些问题,在多个目录中查找时还有些该过滤的帐

号没过滤掉,估计是有些边界细节我没有注意到。希望高手予以斧正,谢谢!
xqk 2005-07-22
  • 打赏
  • 举报
回复
jf
sunsun123123 2005-07-22
  • 打赏
  • 举报
回复
算了,10点以前结贴
sunsun123123 2005-07-22
  • 打赏
  • 举报
回复
感谢各位!
to:teli_eurydice(哭泣的仙人掌。。。。)
查找关键字 com net 之类
我已经考虑过,这样会漏掉很多地址,因为很多地址并不一定是标准的。

to:AntonlioX(做人要厚道)
试试正则表达式的类啊? vckbase里面有个人自己写的 boost开发库里面也有
感谢多次关注,虽然这只是字符串查找的问题,但要较完美的实现,并不容易。利用正则表达式并不重要,关键是算法。我想网上应该有较为成熟的吧,可惜我找了很久没找到。

to:realmiss(边缘)
这类对速度要求比较高的 建议直接采用API操作 不用mfc的类
所以我不想用递规的方法遍历目录,又找不到更好的方法。

AntonlioX 2005-07-22
  • 打赏
  • 举报
回复
其实就是个 字符串 查找功能的实现
teli_eurydice 2005-07-22
  • 打赏
  • 举报
回复
查找关键字 com net 之类
AntonlioX 2005-07-22
  • 打赏
  • 举报
回复
jf
AntonlioX 2005-07-22
  • 打赏
  • 举报
回复


2、递规搜索目录可能较慢,有不有更好的搜索目录下所有文件的算法。


void CFileTreeDlg::BrowseFile(CString strFile)
{

CFileFind ff;
CString szDir = strFile;

if(szDir.Right(1) != "\\")
szDir += "\\";

szDir += "*.*";

BOOL res = ff.FindFile(szDir);
while(res)
{
res = ff.FindNextFile();
if(ff.IsDirectory() && !ff.IsDots())
{
//如果是一个子目录,用递归继续往深一层找
CString strPath = ff.GetFilePath();
// CString strTitle = ff.GetFileTitle();

BrowseFile(strPath);
}
else if(!ff.IsDirectory() && !ff.IsDots())
{
//显示当前访问的文件
// CString strPath;
// CString strTitle;
// strPath = ff.GetFilePath();
// strTitle = ff.GetFileTitle();

}
}
ff.Close();//关闭
}
ziyetingxue 2005-07-22
  • 打赏
  • 举报
回复
期待结果

16,551

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Creator Browser
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧