Posted on 11-09-2009
Filed Under (软件) by waterlin

Firefox Portable 版本一样,PortableApps 同样也出了 Thunderbird 的便携版:Thunderbird Portable。从方便数据备份、移动等各方面考虑,没有不用的理由!

(1) Comment    Read More   
Posted on 09-09-2009
Filed Under (技术) by waterlin

如果你经常在 Usenet 上留下足迹,那么你可能会收到大量的垃圾邮件。很多垃圾邮件制造程序,会自动收集新闻组里的邮件地址并发送数量可观的垃圾邮件。要解决这个问题,只有对你留在 Usenet 上的邮件地址作文章了。

最常用的办法,就是伪装你的邮件地址!你可以添加一些额外的字母、数字以及词组到你的邮件地址里。这些用于伪装邮件地址的字母、数字以及词组,应该要能很容易地被人识别,但却能让垃圾邮件制造机难以识别。

当然,伪装邮件地址的方法也会带来一个坏处:多年以后,你很可能会忘记你以前用过的伪装方法,这时你再去新闻组里找你以前的帖子,很有可能找不到了。

下面具体地讲讲伪装邮件地址的方法:

1) 添加额外的字母、数字以及词组

在你的邮件地址里添加一些一看就知道需要删除的额外单词,例如”dontsendspam”、”delete_these_letters”、”remove this phrase”等,或是类似下面的一些短语:

john.dontsendspam.smith@twenty.net
john.smith.deletethis@twenty.net
john.why-the-extra-words.smith@twenty.net

这样,需要发邮件给你的人就能根据你的邮件地址,判断出你真正的邮件地址是多少。当然,你不要使用类似于”removethis”或是”nospam”这类很常用的屏蔽词组,因为现在的垃圾邮件制造程序越来越智能了,甚至有可能会自动识别并剔除这些伪装词汇。

2) 任意修改邮件地址,并为伪装邮件地址作辅助说明

更好的伪装方法,是放置一个看起来很普通的邮件地址到你的发件人一栏(在新闻组阅读器里可以设置),但是,你要添加真正的邮件地址到你的帖子未尾或作必要的解释。一个比较好的方法,是写到你自动生成的签名档文件里。下面是一些例子:

johncat.smith@twenty.net
Remove the feline from my address to get my real address.

john.tallsmith@twenty.net
Delete the tall part to get a working address.

john.smith1750@twenty1850.net
Disappear the numbers to get from my actual address

更专业的做法,是把”.invalid”添加到邮件地址后面(这会告诉邮件服务器或是功能比较强大的邮件客户端不要接受这个邮件地址),例如“not@valid.invalid“或是”your_favorite_fake_address@nowhere.invalid”这样的邮件地址。

关于如何设置邮件地址,各个新闻组阅读器有着各自的设置方法,请查阅相关手册。

3) 用马甲邮箱作为发信人地址

相信大家肯定都有一个专门用来到处贴、公布的马甲邮件地址(什么,你没有?那赶紧去申请一个),就像大马路、电线杆上到处贴的办证手机号码一样。用这个邮件地址来发帖子到新闻组,想必你不会担心什么。但是这样有几个潜在的问题:一,还是不可避免会收到大量的垃圾邮件;二,因为垃圾邮件太多,你可能会错过新闻组阅读者发给你的联系邮件;三,你在新闻组里的人气积累,随着你的马甲邮箱的弃用而消逝。

以上这些方法里,我推荐使用第二种方法。顺便提一下,你在新闻组里要发邮件给某个人的时候,不要随手一个邮件就发过去了,请先查一查帖子里的邮件地址有没有按上面的方法进行伪装。不然的话,你可要收到一大堆的退信了!

本文参考和引用了 http://www.livinginternet.com/u/ua_disg.htm 的部分素材。

(1) Comment    Read More   
Posted on 04-09-2009
Filed Under (技术) by waterlin

我在用 C++ 实现一个缓存文件的程序,即把很多远程传输过来的文件作为临时文件存到本地,当然,为了避免文件名的冲突,需要按照一定的规律来重新给这些文件取名称。如果是用 C++,可以有以下几种简单的方法取一个临时的文件名:

1) 用一个整数作为文件名,比如说从 00001 开始一直增加到 99999,再把整数转成字符串作为文件名。

这里要注意的是,如果是多线程程序,考虑到多线程的安全性,需要在取整数的时候,加一个锁,取完整数后,让整数加1,再解锁。

2) 如果是 Windows 平台,则可以考虑用系统的API,比如说 GetTempFileName 这个函数可以很好地完成任务,有兴趣的可以看看 MSDN 里有关这个函数的使用例子

3) 如果是 Unix/Linux 主机上,则可以使用函数 tmpfile 来完成任务。

(0) Comments    Read More   
Posted on 04-09-2009
Filed Under (软件) by waterlin

如果网页没有RSS源,怎么样才能知道网页是否有更新呢?看来是时候总结一下这个小问题了。

第一种方法,纯人肉监视,定期检查,时不时地提醒自己需要到某个网页上看看,以免错过重要的更新。相信大多数人用的是这种方法。

第二种方法,用 RememberTheMilkGoogle Calendar 等个人管理工具,生成定期检查的任务,这样脑袋的神经可以不用绷得太紧,在一定程度上提高了效率,也更不容易错过网页的更新。

第三种方法,制作 RSS 源,再订阅这个源。网页一但有更新,就能及时得到通知,前提是烧录这个 RSS 源的服务商能提供稳定、可靠的服务。

第四种方法,用 Firefox 的扩展 Update Scanner,我在前一篇文章里有仔细讲过这个插件。

以上方法推荐同时使用第三种和第四种,这样保险系数就比较高了。举个例子,我是广东移动的动感地带用户,移动经常出一些优惠,而我很少留意路边的广告,所以我经常会错过移动的优惠。移动的网站又没有提供 RSS 源,我没有办法通过订阅 RSS 来获得更新。现在,我只要用 Update Scanner 来监视移动的优惠信息网页,以及把移动的优惠信息网页烧制为 RSS 源,则移动的网站一有更新,我马上能收到提醒,不会再错过优惠信息了。

通过这样的设置,你就不会错过任何网站的最新更新消息,包括各种打折、优惠信息!信息时代,抢先别人一步,就是胜利!当然,上面的方法,不适合更新太过频繁的网站(比如说 Google 资讯),否则你会被大量的信息给淹没,反而使你的工作效率大大降低。

(0) Comments    Read More   
Posted on 04-09-2009
Filed Under (生活) by waterlin

有一些网页,比如说学校的通知、政府网站公告之类的,大多数没有 RSS 源(它们可能觉得能不能获得更新是你的责任,它没有义务),虽然网页更新是不定期的、不频繁的,但是更新出来的内容比较重要、时效性比较强,需要及时处理,一旦错过,后果很严重。以前读书的时候,我就尽量提醒自己,记住定期去查一查某某网页有没有更新、某某网站有没有最新指示等。可是有时候一贪玩,或是惰性起来了,错过了重要的消息,只有锺胸顿足信誓旦旦以后再也不会忘记去检查这些网页。

人工检查这一大堆网页太麻烦了:一来不容易记得住要去查看,绷紧的弦总有松弛的时候;二来这样做效率并不高,大多数情况下你检查的网页并没有更新,而往往你不检查的时候,网页居然更新了。

当然,我可以用烧录 RSS 源的方式来解决这个问题。只不过烧录 RSS 源并不能完美地解决这个问题,你得时刻担心 RSS 烧录服务是否可靠、RSS 烧制服务商是否会倒闭等。最好的方法,是我可以直接在本地比较网页是否有更新;并且在我想自己确认的情况下,我可以方便地打开网页去查看。

Firefox 的插件 Update Scanner 就提供了在本地监视网页是否有更新的功能,只要给它一个网址列表,它就会根据你设定的检查频率去自动检查网页是否有更新。同时,你也可以很方便地在 Update Scanner 里核对、浏览你需要关注的重要网站。

如果你想把自己从监视网页更新的纯体力劳动里解放出来,不妨试试 Update Scanner

(1) Comment    Read More   
Posted on 03-09-2009
Filed Under (技术) by waterlin

在 C++ 里,如果需要把 int 的数值直接转成字符串(例如对于整数123,我能得到字符串”123″),我们可以用很多种方法来实现:

1) 用 C++ 里的流控制,可以轻松地实现整数转成字符串的功能:

#include <sstream>
#include <iostream>

main()
{
    int abc = 123;
    std::ostringstream out;
    out << abc;
    std::cout << out.str() << std::endl;
}

下面是宽字符版本的演示程序,稍微有点不同,则可以用下面的方法:

int current = 111;
std::wostringstream int2string;
int2string << current;

wstring temp_file = int2string.str().c_str();
wprintf(L”current filename is: %s\n”, temp_file.c_str());
wprintf(L”current filename is: %s\n”, int2string.str().c_str());

2) Boost 是 C++ 的准标准库,我们当然应该尝试学习使用 Boost 来完成这个转换,例子如下:

#include <boost/lexical_cast.hpp>

main()
{
    int abc = 123;
    std::string s = boost::lexical_cast<std::string>(abc);

    printf("test for string: %s",s.c_str());
}

3) 用 C 标准库里的 sprintf 或是 swprintf 函数,注意,sprintf 需要头文件 <stdio.h>,而 swprintf 需要 <stdio.h> 或者 <wchar.h> 头文件,可以看看MSDN里的例子

#include <stdio.h>

int main( void )
{
    char  buffer[200], s[] = "computer", c = 'l';
    int   i = 35, j;
    float fp = 1.7320534f;

    /* Format and print various data: */
    j  = sprintf( buffer,     "   String:    %s\n", s );
    j += sprintf( buffer + j, "   Character: %c\n", c );
    j += sprintf( buffer + j, "   Integer:   %d\n", i );
    j += sprintf( buffer + j, "   Real:      %f\n", fp );

    printf( "Output:\n%s\ncharacter count = %d\n", buffer, j );
}

4) 用 C 标准库的 itoa 函数也可以实现从字符串到数字的转换,itoa的例子代码:

/* itoa example */
#include <stdio.h>
#include <stdlib.h>

int main ()
{
    int i;
    char buffer [33];
    printf ("Enter a number: ");
    scanf ("%d",&i);
    itoa (i,buffer,10);
    printf ("decimal: %s\n",buffer);
    itoa (i,buffer,16);
    printf ("hexadecimal: %s\n",buffer);
    itoa (i,buffer,2);
    printf ("binary: %s\n",buffer);
    return 0;
}

同样,用 C 标准库的 atoi 函数可以实现从字符串到数字的转换,atoi的例子代码:

/* atoi example */
#include <stdio.h>
#include <stdlib.h>

int main ()
{
    int i;
    char szInput [256];
    printf ("Enter a number: ");
    fgets ( szInput, 256, stdin );
    i = atoi (szInput);
    printf ("The value entered is %d. The double is %d.\n",i,i*2);
    return 0;
}

一般来讲,就上面这么四种常用的方法就够用了。

(0) Comments    Read More   
Posted on 03-09-2009
Filed Under (技术) by waterlin

Boost 被人们誉为 C++ 的准标准库,尝试着为 C++ 提供一个可跨平台使用的、大而全的库。作为一个软件工程师,一直没有机会对 Boost 进行了解与学习,现在正是迎头赶上的时候了!

今天在 Cygwin 下试着编译与安装了 Boost 库(boost_1_40_0版本),非常的简单与方便,大体步骤如下:

1) 下载源代码,解压到任何你想要的地方,我是放在 ~/source_code 目录下,解压后所有 Boost 的文件都在文件夹 boost_1_40_0 里面。

2) 编辑一段最简单的、只需要用到头文件的例子代码。在目录 ~/source_code/boost_1_40_0 下新建一个名叫 example.cpp 的文件,复制下面的代码:

#include <boost/lambda/lambda.hpp>
#include <iostream>
#include <iterator>
#include <algorithm>
int main()
{
    using namespace boost::lambda;
    typedef std::istream_iterator<int> in;
    std::for_each(
    in(std::cin), in(), std::cout << (_1 * 3) << " " );
}

从命令行编译:

$ g++ -I /home/water/source_code/boost_1_40_0/ example.cpp -o example

上面 -I 后的参数,请根据 Boost 解压后所在的目录填写。编译成功后,运行 ./example,试着输入几个数字看看。

这里补充说明一下有关 C++ 头文件包含问题:如果在上面的命令中,你不想使用 -I 选项,可以把 Boost 的头文件放到 Cygwin 的 #include 目录里去,一般来讲,是 /usr/local/include 或是 /usr/include 目录。你可以把 Boost 源码包里的 Boost 文件夹,一股脑地拷贝到 /usr/local/include 目录下(当然,不支持手动这样做)。

如果你用了下面的命令:

$ g++ example.cpp -o example

而又没有按上面说的把 Boost 的头文件复制到 #include 目录,则会提示类似下面的错误:

$ g++ example.cpp -0 exmaple
g++: exmaple: No such file or directory
g++: unrecognized option `-0′
example.cpp:1:35: boost/lambda/lambda.hpp: No such file or directory
example.cpp: In function `int main()’:
example.cpp:8: error: `boost’ has not been declared
example.cpp:8: error: expected namespace-name before ‘;’ token
example.cpp:8: error: `<type error>’ is not a namespace
example.cpp:12: error: `_1′ undeclared (first use this function)
example.cpp:12: error: (Each undeclared identifier is reported only once for each function it appears in.)

3) 编译与安装 Boost 库的最简单方法

先生成命令行工具 bjam,它是专门负责编译、安装 Boost 库的工具。可以先查看一下相关帮助信息:

$ cd path/to/boost_1_40_0
$ ./bootstrap.sh –help

执行下面的命令就可以生成 bjam:

$ ./bootstrap.sh –prefix=path/to/installation/prefix

最后再利用 bjam 自动编译库文件:

$ ./bjam install

Boost 的编译与安装时间比较长,编译完成后,默认配置下头文件会安装到 /usr/local/include/boost 目录下,而生成的库文件会放到 /usr/local/lib 目录下。更详细的安装可以看看官方文档

4) 以后写完 Boost 代码,就可以直接编译代码了。现在可以试着不指定 Boost 头文件的路径,再编译一把上面的 example.cpp 的例子:

$ g++ example.cpp -o example

现在 g++ 就能自动找到相关的头文件。

如果是 Linux 的话,编译与安装 Boost 的步骤应该大体上差不多;推荐使用各 Linux 发行版编译好的二进制版本,直接下载安装更省事。

(0) Comments    Read More   
Posted on 02-09-2009
Filed Under (技术) by waterlin

之前文章中提到的通过 Windows 注册表来实现开机时文件替换的方法,好像只对位于同一个文件分区的两个文件有效,而对于两个处在不同文件分区的文件,则没有办法。

举例来讲,我想用 E 盘下的 test1.txt 文件来替换掉 C 盘下的 test2.txt 文件,按之前的方法,在注册表里写入下面的值:

\??\e:\test1\test1.txt
!\??\c:\test2\test2.txt

重启电脑后,test1.txt 文件不见了,但文件 test2.txt 的内容并没有被 test1.txt 成功替换掉。

我反复试验了很多次都不行,最后的结论是,这种通过 Windows 注册表来实现开机时文件替换的方法,的确不能应用于不同的文件分区。以后在使用前面介绍过的方法的时候,一定要注意这一点。

我唯一想的原因是:在重启的时候,Windows 并不是真正的在做复制、删除文件等操作,它很有可能只是把被替换文件链接到替换文件上并修改名称,硬盘分区里的大部分数据其实没有移动,因此,在两个不同的分区里,就自然没有办法了。

有谁知道原因的,不妨告诉我,多谢了~~

(0) Comments    Read More