如何中文显示我的PHP-GTK程序
官方没有出台正式方案之前,暂时先用这个(学习中,高手有更好的解决方案请跟贴):
在php.ini的[PHP-GTK]部分
加入php-gtk.codepage = gb2312 ;将php格式保存为ansi格式
php-gtk.codepage = uft-8 ;将php格式保存为utf8格式
在你创建的窗口时
$window = &new GtkWindow();
$window->style->font =
gdk::font_load("-unknown-宋体-normal-r-normal-*-*-120-*-*-p-*-gb2132-0");
这里调用gdk::font_load函数载入字体,注意是“GDK”,不是“GTK”
(顺便抗议一下,程序一长,居然自动截断掉,只好这样写了)
2、我的PHP-GTK程序为什么那么单调,而演示程序确有颜色?
首先要感谢hisunweb大师的耐心指导,本文才得以完成。
文章的开始,我要更正一下上次的笔误(没有人有意见吧 )
gdk::font_load("-unknown-simsun-normal-r-normal-*-*-120-96-96-p-*-gb2312-0");
同时,本文将给出中文化的更好的方法:
(1)、将PHP.INI中的[PHP-GTK]模块下
php-gtk.codepage = "gb2312"
(2)、在原PHP-GTK程序目录下新建mygtkrc文件,内容如下:
style "defaultfont"
{
font = "-unknown-simsun-normal-r-normal-*-*-120-96-96-p-*-gb2312-0"
}
class "GtkWidget" style "defaultfont"
(3)、在你的PHP-GTK程序的Gtk::main();之前加入
Gtk::rc_parse(dirname($argv[0]).'/mygtkrc');
现在你的PHP-GTK能够很顺利的现实中文了。
上面是开胃菜,下面开始重点:大家都看到了,我们在上面新建了一个文件(名字自己爱怎么写就怎么写,以下简称资源文件),这个文件有点类似HTML的 CSS样式,能够对PHP-GTK程序的风格进行解析,如字体、颜色等。如果我们需要鼠标移动到按钮上时,按钮显示颜色,可以在你的资源文件中这样定义:
style 'button_list' = 'button'
{
bg[PRELIGHT] = { 0, 0.75, 0x00 }
}
widget "main window.*GtkScrolledWindow.*GtkButton*" style "button_list"
同时,在你的程序中,我们要这样定义一个标志“main window”,就有点像HTML中的ID
$window = &new GtkWindow();
$window->set_name('main window');
这样一来,你的GtkScrolledWindow下的GtkButton鼠标经过时都有颜色,详见附带gtk.php程序。
资源文件如何定义了?我们前只有这些信息:
如假如一行
widget "main window.*GtkButton*" style "main_button"
该定义把"主窗口"中的所有按钮构件设置为资源文件中定义的"main_buttons"风格。
有几个指令用于改变一个构件的属性。
fg - 设置构件的背景色。
bg - 设置构件的前景色。
bg_pixmap - 设置构件的背景为一幅像素图。
font - 设置构件使用的字体。
另外,一个构件可以有几种状态,你可以为每种状态设置不同的颜色,图像和字体。这些状态是:
NORMAL - 构件的一般状态,如鼠标不位于构件上方,键未按下时构件所处的状态。
PRELIGHT - 当鼠标移到构件上方,在此状态下定义的颜色生效。
ACTIVE - 当处于构件上的鼠标键被按下或点击时,该构件被激活,相应的属性值将生效。
INSENSITIVE - 当构件被设置为不敏感(insensitive)时,它不能被激活,相应属性值起作用。
SELECTED - 选中一个对象时,取相应的属性值。
当用"fg"和"bg"关键字设置构件的颜色时,其格式是:
fg[<STATE>] = { Red, Green, Blue }
这里STATE是前述状态(PRELIGHT,ACTIVE,...)之一,Red,Green,Blue是范围0-1.0间的数值, {1.0,1.0,1.0}表示白色。这些数值必须是浮点型的,否则将被存为0,因此写为"1"的数值是无效的,应写为"1.0".0值写为"0"却不错,因为即使系统认不出也没关系。所有系统不认识的数值都会被设为0。
bg_pixmap除了用一个文件名取代颜色名外和以上格式很相似。
pixmap_path是一个由‘:’分隔开的路径表。当搜索你定义的图像文件时选择这些路径。
最后,可能你对font的定义很感兴趣,我把定义方法转过来,原汁原味,就不翻译啦~~(每一行对应一个参数)
foundry xxx (where the font was created. 'unknown' is okay)
family xxx (e.g. Arial)
weight xxx (e.g. bold, medium)
slant x (r - roman, i = italic, o = oblique)
setwidth xxx (e.g. normal, condensed)
addedstyle xxx (e.g. serif, sans. Leave blank for none)
pixelsize N (set either this or pointsize, not both)
pointsize N (point size, e.g. 120)
resx N (x res the font was created for, in dots per inch)
resy N (y res the font was created for, in dots per inch)
space x (m = monospaced, p = proportional, c = cell)
averagewidth N (average character width in pixels. 0 if unknown)
registry xxx (e.g. utf, iso8859 or adobe)
encoding xxx (e.g. 1 or 2 (for iso8859) or fontspecific)
例如:$font = gdk::font_load('-unknown-Arial-normal-r-normal--*-120-96-96-p-0-iso8859-1');
3、PHP-GTK的相关资源
作者:Verdana
http://kromann.info/php4-gtk.php
这里有从 CVS 源码编译的 php-gtk 的版本,每天更新
类似 php snaps, 不过容易出问题。
还有 php5 的 gtk 版本。
http://www.cweiske.de/phpgtk.htm
德国网站,但内容是英文的,很容易看懂
提供了 PHP-GTK AppWizard 下载
非常不错的软件,帮你自动生成 PHP GTK 程序,不需要写一行
代码,哈哈哈
提供 PHP-Themes 下载,非常漂亮啊~
http://www.cweiske.de/phpgtk_themes.htm
如果没有看上眼的也可以自己定制 :P
另外学 GTK 的话,就必须要提一下 winGlade ,呵呵~
一个 GUI 的 GTK 界面设计器。类似 VC 设计窗体一样
可以把控件拖来拖去,修改属性。
生成的是 xml 文件。
这里 http://wingtk.sourceforge.net/ 下载
4、AppWizard 确实很好,但是不能使用中文目录/文件,咋办咧^_^?
(1)、在同一目录下新建资源文件mygtkrc,内容如下:
style "defaultfont"
{
font = "-unknown-simsun-normal-r-normal-*-*-120-96-96-p-*-gb2312-0"
}
class "GtkWidget" style "defaultfont"
(2)、源程序解压后,appwizard.php-gtk的349行,也就是GTK::main();的前面一行加入:
Gtk::rc_parse(dirname($argv[0]).'/mygtkrc');
(3)、保存后,支持中文目录/文件名。第一次启动,需要等待一定的时间,俺的机器好像用了将近2分钟,不要认为是死机,值得等待。
以后遇到相同的中文问题,可以先尝试用上面的方法。
祝大家玩得开心,村民们有什么PHP-GTK的咚咚,全部贡献出来吧,人民会记住你的(村棍除外)。
注意:AppWizard第一次运行,不能放在带有中文的路径目录中,否则很可能会出错。
6、如何修改默认的PHP-GTK风格,比如我比较喜欢MAC风格?
将资源文件改名为“.gtkrc”,注意,前面有点号,这个过程可以通过DOS窗口实现(作者是这么说的),把它放到C:Documents and Settings{你的用户名}.gtkrc
例如有个文件内容如下
style "default"
{
bg[NORMAL] = "#ededed"
bg[PRELIGHT] = "#8db6cd"
bg[ACTIVE] = "#bababa"
bg[INSENSITIVE] = "#ededed"
bg[SELECTED] = "#8db6cd"
fg[NORMAL] = "#000000"
fg[PRELIGHT] = "#000000"
fg[ACTIVE] = "#000000"
fg[INSENSITIVE] = "#bababa"
fg[SELECTED] = "#000000"
engine "engradient"
{
use_gradient = TRUE
handlebox_marks = TRUE
scrollbar_marks = TRUE
}
}
widget "*" style "default"
style "tooltip"
{
bg[NORMAL] = "#ffffff"
}
widget "*gtk-tooltip*" style "tooltip"
将它改名.gtkrc,再放到:
C:Documents and Settings开心果目录下,以后你运行的PHP-GTK程序都是用这个风格。
当然,你必须拥有相应的风格库文件,否则只能显示主题颜色,框架不变,并提示找不到库文件。如果仅仅需要颜色主题,请把这一段删掉:
engine "engradient"
{
use_gradient = TRUE
handlebox_marks = TRUE
scrollbar_marks = TRUE
}
顺便提一句,AppWizard不能够生成我们所想要得PHP-GTK程序,它仅仅是个测试(JUST A TEST,作者又是这么说的),而且生成的代码垃圾一堆,继续寻找传说中的法宝~~
还有就是,PHP-GTK程序,得到ZEND的编码支持,也就是说,ZEND编译后PHP-GTK依然能够执行。
官方没有出台正式方案之前,暂时先用这个(学习中,高手有更好的解决方案请跟贴):
在php.ini的[PHP-GTK]部分
加入php-gtk.codepage = gb2312 ;将php格式保存为ansi格式
php-gtk.codepage = uft-8 ;将php格式保存为utf8格式
在你创建的窗口时
$window = &new GtkWindow();
$window->style->font =
gdk::font_load("-unknown-宋体-normal-r-normal-*-*-120-*-*-p-*-gb2132-0");
这里调用gdk::font_load函数载入字体,注意是“GDK”,不是“GTK”
(顺便抗议一下,程序一长,居然自动截断掉,只好这样写了)
2、我的PHP-GTK程序为什么那么单调,而演示程序确有颜色?
首先要感谢hisunweb大师的耐心指导,本文才得以完成。
文章的开始,我要更正一下上次的笔误(没有人有意见吧 )
gdk::font_load("-unknown-simsun-normal-r-normal-*-*-120-96-96-p-*-gb2312-0");
同时,本文将给出中文化的更好的方法:
(1)、将PHP.INI中的[PHP-GTK]模块下
php-gtk.codepage = "gb2312"
(2)、在原PHP-GTK程序目录下新建mygtkrc文件,内容如下:
style "defaultfont"
{
font = "-unknown-simsun-normal-r-normal-*-*-120-96-96-p-*-gb2312-0"
}
class "GtkWidget" style "defaultfont"
(3)、在你的PHP-GTK程序的Gtk::main();之前加入
Gtk::rc_parse(dirname($argv[0]).'/mygtkrc');
现在你的PHP-GTK能够很顺利的现实中文了。
上面是开胃菜,下面开始重点:大家都看到了,我们在上面新建了一个文件(名字自己爱怎么写就怎么写,以下简称资源文件),这个文件有点类似HTML的 CSS样式,能够对PHP-GTK程序的风格进行解析,如字体、颜色等。如果我们需要鼠标移动到按钮上时,按钮显示颜色,可以在你的资源文件中这样定义:
style 'button_list' = 'button'
{
bg[PRELIGHT] = { 0, 0.75, 0x00 }
}
widget "main window.*GtkScrolledWindow.*GtkButton*" style "button_list"
同时,在你的程序中,我们要这样定义一个标志“main window”,就有点像HTML中的ID
$window = &new GtkWindow();
$window->set_name('main window');
这样一来,你的GtkScrolledWindow下的GtkButton鼠标经过时都有颜色,详见附带gtk.php程序。
资源文件如何定义了?我们前只有这些信息:
如假如一行
widget "main window.*GtkButton*" style "main_button"
该定义把"主窗口"中的所有按钮构件设置为资源文件中定义的"main_buttons"风格。
有几个指令用于改变一个构件的属性。
fg - 设置构件的背景色。
bg - 设置构件的前景色。
bg_pixmap - 设置构件的背景为一幅像素图。
font - 设置构件使用的字体。
另外,一个构件可以有几种状态,你可以为每种状态设置不同的颜色,图像和字体。这些状态是:
NORMAL - 构件的一般状态,如鼠标不位于构件上方,键未按下时构件所处的状态。
PRELIGHT - 当鼠标移到构件上方,在此状态下定义的颜色生效。
ACTIVE - 当处于构件上的鼠标键被按下或点击时,该构件被激活,相应的属性值将生效。
INSENSITIVE - 当构件被设置为不敏感(insensitive)时,它不能被激活,相应属性值起作用。
SELECTED - 选中一个对象时,取相应的属性值。
当用"fg"和"bg"关键字设置构件的颜色时,其格式是:
fg[<STATE>] = { Red, Green, Blue }
这里STATE是前述状态(PRELIGHT,ACTIVE,...)之一,Red,Green,Blue是范围0-1.0间的数值, {1.0,1.0,1.0}表示白色。这些数值必须是浮点型的,否则将被存为0,因此写为"1"的数值是无效的,应写为"1.0".0值写为"0"却不错,因为即使系统认不出也没关系。所有系统不认识的数值都会被设为0。
bg_pixmap除了用一个文件名取代颜色名外和以上格式很相似。
pixmap_path是一个由‘:’分隔开的路径表。当搜索你定义的图像文件时选择这些路径。
最后,可能你对font的定义很感兴趣,我把定义方法转过来,原汁原味,就不翻译啦~~(每一行对应一个参数)
foundry xxx (where the font was created. 'unknown' is okay)
family xxx (e.g. Arial)
weight xxx (e.g. bold, medium)
slant x (r - roman, i = italic, o = oblique)
setwidth xxx (e.g. normal, condensed)
addedstyle xxx (e.g. serif, sans. Leave blank for none)
pixelsize N (set either this or pointsize, not both)
pointsize N (point size, e.g. 120)
resx N (x res the font was created for, in dots per inch)
resy N (y res the font was created for, in dots per inch)
space x (m = monospaced, p = proportional, c = cell)
averagewidth N (average character width in pixels. 0 if unknown)
registry xxx (e.g. utf, iso8859 or adobe)
encoding xxx (e.g. 1 or 2 (for iso8859) or fontspecific)
例如:$font = gdk::font_load('-unknown-Arial-normal-r-normal--*-120-96-96-p-0-iso8859-1');
3、PHP-GTK的相关资源
作者:Verdana
http://kromann.info/php4-gtk.php
这里有从 CVS 源码编译的 php-gtk 的版本,每天更新
类似 php snaps, 不过容易出问题。
还有 php5 的 gtk 版本。
http://www.cweiske.de/phpgtk.htm
德国网站,但内容是英文的,很容易看懂
提供了 PHP-GTK AppWizard 下载
非常不错的软件,帮你自动生成 PHP GTK 程序,不需要写一行
代码,哈哈哈
提供 PHP-Themes 下载,非常漂亮啊~
http://www.cweiske.de/phpgtk_themes.htm
如果没有看上眼的也可以自己定制 :P
另外学 GTK 的话,就必须要提一下 winGlade ,呵呵~
一个 GUI 的 GTK 界面设计器。类似 VC 设计窗体一样
可以把控件拖来拖去,修改属性。
生成的是 xml 文件。
这里 http://wingtk.sourceforge.net/ 下载
4、AppWizard 确实很好,但是不能使用中文目录/文件,咋办咧^_^?
(1)、在同一目录下新建资源文件mygtkrc,内容如下:
style "defaultfont"
{
font = "-unknown-simsun-normal-r-normal-*-*-120-96-96-p-*-gb2312-0"
}
class "GtkWidget" style "defaultfont"
(2)、源程序解压后,appwizard.php-gtk的349行,也就是GTK::main();的前面一行加入:
Gtk::rc_parse(dirname($argv[0]).'/mygtkrc');
(3)、保存后,支持中文目录/文件名。第一次启动,需要等待一定的时间,俺的机器好像用了将近2分钟,不要认为是死机,值得等待。
以后遇到相同的中文问题,可以先尝试用上面的方法。
祝大家玩得开心,村民们有什么PHP-GTK的咚咚,全部贡献出来吧,人民会记住你的(村棍除外)。
注意:AppWizard第一次运行,不能放在带有中文的路径目录中,否则很可能会出错。
6、如何修改默认的PHP-GTK风格,比如我比较喜欢MAC风格?
将资源文件改名为“.gtkrc”,注意,前面有点号,这个过程可以通过DOS窗口实现(作者是这么说的),把它放到C:Documents and Settings{你的用户名}.gtkrc
例如有个文件内容如下
style "default"
{
bg[NORMAL] = "#ededed"
bg[PRELIGHT] = "#8db6cd"
bg[ACTIVE] = "#bababa"
bg[INSENSITIVE] = "#ededed"
bg[SELECTED] = "#8db6cd"
fg[NORMAL] = "#000000"
fg[PRELIGHT] = "#000000"
fg[ACTIVE] = "#000000"
fg[INSENSITIVE] = "#bababa"
fg[SELECTED] = "#000000"
engine "engradient"
{
use_gradient = TRUE
handlebox_marks = TRUE
scrollbar_marks = TRUE
}
}
widget "*" style "default"
style "tooltip"
{
bg[NORMAL] = "#ffffff"
}
widget "*gtk-tooltip*" style "tooltip"
将它改名.gtkrc,再放到:
C:Documents and Settings开心果目录下,以后你运行的PHP-GTK程序都是用这个风格。
当然,你必须拥有相应的风格库文件,否则只能显示主题颜色,框架不变,并提示找不到库文件。如果仅仅需要颜色主题,请把这一段删掉:
engine "engradient"
{
use_gradient = TRUE
handlebox_marks = TRUE
scrollbar_marks = TRUE
}
顺便提一句,AppWizard不能够生成我们所想要得PHP-GTK程序,它仅仅是个测试(JUST A TEST,作者又是这么说的),而且生成的代码垃圾一堆,继续寻找传说中的法宝~~
还有就是,PHP-GTK程序,得到ZEND的编码支持,也就是说,ZEND编译后PHP-GTK依然能够执行。
http://www.phpe.net/articles/380.shtml
cookbook:http://www.kksou.com/php-gtk2/
cookbook:http://www.kksou.com/php-gtk2/
/usr/bin/rsync -vzrtup ./video_user_20080625_004312.txt 10.69.2.48::usersource_video/
aoyuntongji.php
aoyuntongji.php
<?php
require_once ("/data0/vshare/app/rank/config.php");
define("USER_SEARCH_IASK_LOG_PATH", "/data0/vshare/logs/user_search/iasks/");//删除的用户及视频日志目录(爱问)
echo "程序于 " . date("Y-m-d H:i:s") . " 开始执行:\n";
$date_d=date("d")-1;
if($date_d<10)
{
$date_d="0".$date_d;
}
$iask_filename = USER_SEARCH_IASK_LOG_PATH.date("Ym")."/".$date_d."/boke_ay_" . date("Ymd", strtotime("-1 day")) .".log";
$iask_filename_html = USER_SEARCH_IASK_LOG_PATH.date("Ym")."/".$date_d."/boke_ay_" . date("Ymd", strtotime("-1 day")) .".html";
$conn_db_3306_r = @mysql_connect(DBHOST_VIDEO_R_aoyun, DBUSER_VIDEO_R_aoyun, DBPASSWD_VIDEO_R_aoyun) or
die(DBHOST_VIDEO_R_aoyun.DBUSER_VIDEO_R_aoyun.DBPASSWD_VIDEO_R_aoyun."Can't connect to 3306 port readonly database");//长连接
//统计昨天登录过的用户个人中心信息
echo "正在从MySQL数据库中取出所有的用户userid,请稍候....";
//exit(0);
//$select_dt_user_r = @mysql_select_db("dt_video", $conn_db_3306_r) or die("Can't select database");
$select_dt_user_r = @mysql_select_db("dt_manage", $conn_db_3306_r) or die("Can't select database");
//$sql_tb_usertotal_r = "SELECT videoid,up_userid FROM tb_video_total where activeid = 0 limit 10";/*上线后打开*/
$starttime = date("Y-m-d 00:00:00", strtotime("-3 day"));
$endtime = date("Y-m-d 00:00:00");
$sql_tb_usertotal_r = "select videoid,up_userid from tb_video_activity where (adddate>'".$starttime."' or appr_time>'".$starttime."') and adddate<'".$endtime."' and appr_status=1 and active_status in(1,0) and conv_status=1 and del_status=0 and activeid=128;";/*上线后打开*/
$query_tb_usertotal_r = mysql_query($sql_tb_usertotal_r, $conn_db_3306_r) or die("Query Error:" .
mysql_error() . "\n");
echo $sql_tb_usertotal_r."\n";
echo "\n[取出所有的用户userid:完成]\n";
$i=0;
echo $iask_filename."\n";
if(file_exists($iask_filename))
{
unlink($iask_filename);
}
while ($row_tb_usertotal_r = mysql_fetch_assoc($query_tb_usertotal_r))
{
if (!($i % 2000))
{
sleep(1);
}
$vid = $row_tb_usertotal_r['videoid'];
$uid = $row_tb_usertotal_r['up_userid'];
$result['vid'] = $vid;
$result['uid'] = $uid;
/*
echo "VID:". $result['vid'] = $vid."\n";
echo "UID:".$result['uid'] = $uid."\n";
*/
$content = getContent($result,$i);
us_writeFile($content, $iask_filename, USER_SEARCH_IASK_LOG_PATH .date("Ym")."/".$date_d);
$i=$i+1;
}
if (file_exists($iask_filename) && is_readable($iask_filename))
{
echo "正在向爱问推送数据,请稍候....\n";
//pclose(popen("touch {$iask_filename} && chmod 0664 {$iask_filename} && /usr/bin/rsync -vzrtup {$iask_filename} 10.69.2.48::usersource_video/",
//"r"));
$command="/usr/bin/rsync -avgt --progress --password-file=/usr/local/etc/rsyncd.secrets " . USER_SEARCH_IASK_LOG_PATH ."*"." backupuser@219.142.118.48::boke_2008_sum_olympic_video";
echo $command."\n";
pclose(popen("touch {$iask_filename} && chmod 0664 {$iask_filename} && $command",
"r"));
$command="/usr/bin/rsync -avgt --progress --password-file=/usr/local/etc/rsyncd.secrets " . USER_SEARCH_IASK_LOG_PATH ."*"." backupuser@172.16.153.70::olympic_video/";
pclose(popen("touch {$iask_filename} && chmod 0664 {$iask_filename} && $command",
"r"));
$command="/usr/bin/rsync -avu " . $iask_filename ." 172.16.6.198::vblog/";
pclose(popen("touch {$iask_filename} && chmod 0664 {$iask_filename} && $command",
"r"));
$command="cp {$iask_filename} {$iask_filename_html}";
pclose(popen($command, "r"));
$command="/usr/bin/rsync -avu {$iask_filename_html} {$iask_filename} 10.68.1.30::v_blog_sina_com_cn/htdocs/ay_data/";
pclose(popen($command, "r"));
$command="/usr/bin/rsync -avu {$iask_filename_html} {$iask_filename} 10.68.1.71::v_blog_sina_com_cn/htdocs/ay_data/";
pclose(popen($command, "r"));
echo "[推送完成]\n";
}
echo "\n[完成]\n";
echo "程序于 " . date("Y-m-d H:i:s") . " 执行结束。\n\n";
function us_path_validate($path)
{
$arraypath = split("\/+", $path);
$tmppath = "";
for ($i = 0; $i < count($arraypath); $i++)
{
if ("" == $arraypath[$i])
continue;
$tmppath .= (0 == $i ? "":"/") . $arraypath[$i];
if (!is_dir($tmppath))
{
if (!mkdir($tmppath, 0777))
{
return false;
}
}
}
return true;
}
function us_writeFile($content, $filename, $dirpath)
{
if (!us_path_validate($dirpath))
exit();
$fp = fopen($filename, "a+");
if (!@fwrite($fp, $content . "\n"))
{
@fclose($fp);
return false;
}
fclose($fp);
return true;
}
function getContent($result,$i)
{
/*
if($i==0)
{
$str = "VID\tUID\t日期\n";
$str .= $result['vid'] . "\t";//视频总量
$str .= $result['uid'] . "\t";//userid,用户UID
$str .= date("Y-m-d",strtotime("-1 day")). "";
return $str;
}else{
*/
$str = $result['vid'] . "\t";//视频总量
$str .= $result['uid'] . "\t";//userid,用户UID
$str .= date("Y-m-d",strtotime("-1 day")) . "";
return $str;
// }
}
?>
require_once ("/data0/vshare/app/rank/config.php");
define("USER_SEARCH_IASK_LOG_PATH", "/data0/vshare/logs/user_search/iasks/");//删除的用户及视频日志目录(爱问)
echo "程序于 " . date("Y-m-d H:i:s") . " 开始执行:\n";
$date_d=date("d")-1;
if($date_d<10)
{
$date_d="0".$date_d;
}
$iask_filename = USER_SEARCH_IASK_LOG_PATH.date("Ym")."/".$date_d."/boke_ay_" . date("Ymd", strtotime("-1 day")) .".log";
$iask_filename_html = USER_SEARCH_IASK_LOG_PATH.date("Ym")."/".$date_d."/boke_ay_" . date("Ymd", strtotime("-1 day")) .".html";
$conn_db_3306_r = @mysql_connect(DBHOST_VIDEO_R_aoyun, DBUSER_VIDEO_R_aoyun, DBPASSWD_VIDEO_R_aoyun) or
die(DBHOST_VIDEO_R_aoyun.DBUSER_VIDEO_R_aoyun.DBPASSWD_VIDEO_R_aoyun."Can't connect to 3306 port readonly database");//长连接
//统计昨天登录过的用户个人中心信息
echo "正在从MySQL数据库中取出所有的用户userid,请稍候....";
//exit(0);
//$select_dt_user_r = @mysql_select_db("dt_video", $conn_db_3306_r) or die("Can't select database");
$select_dt_user_r = @mysql_select_db("dt_manage", $conn_db_3306_r) or die("Can't select database");
//$sql_tb_usertotal_r = "SELECT videoid,up_userid FROM tb_video_total where activeid = 0 limit 10";/*上线后打开*/
$starttime = date("Y-m-d 00:00:00", strtotime("-3 day"));
$endtime = date("Y-m-d 00:00:00");
$sql_tb_usertotal_r = "select videoid,up_userid from tb_video_activity where (adddate>'".$starttime."' or appr_time>'".$starttime."') and adddate<'".$endtime."' and appr_status=1 and active_status in(1,0) and conv_status=1 and del_status=0 and activeid=128;";/*上线后打开*/
$query_tb_usertotal_r = mysql_query($sql_tb_usertotal_r, $conn_db_3306_r) or die("Query Error:" .
mysql_error() . "\n");
echo $sql_tb_usertotal_r."\n";
echo "\n[取出所有的用户userid:完成]\n";
$i=0;
echo $iask_filename."\n";
if(file_exists($iask_filename))
{
unlink($iask_filename);
}
while ($row_tb_usertotal_r = mysql_fetch_assoc($query_tb_usertotal_r))
{
if (!($i % 2000))
{
sleep(1);
}
$vid = $row_tb_usertotal_r['videoid'];
$uid = $row_tb_usertotal_r['up_userid'];
$result['vid'] = $vid;
$result['uid'] = $uid;
/*
echo "VID:". $result['vid'] = $vid."\n";
echo "UID:".$result['uid'] = $uid."\n";
*/
$content = getContent($result,$i);
us_writeFile($content, $iask_filename, USER_SEARCH_IASK_LOG_PATH .date("Ym")."/".$date_d);
$i=$i+1;
}
if (file_exists($iask_filename) && is_readable($iask_filename))
{
echo "正在向爱问推送数据,请稍候....\n";
//pclose(popen("touch {$iask_filename} && chmod 0664 {$iask_filename} && /usr/bin/rsync -vzrtup {$iask_filename} 10.69.2.48::usersource_video/",
//"r"));
$command="/usr/bin/rsync -avgt --progress --password-file=/usr/local/etc/rsyncd.secrets " . USER_SEARCH_IASK_LOG_PATH ."*"." backupuser@219.142.118.48::boke_2008_sum_olympic_video";
echo $command."\n";
pclose(popen("touch {$iask_filename} && chmod 0664 {$iask_filename} && $command",
"r"));
$command="/usr/bin/rsync -avgt --progress --password-file=/usr/local/etc/rsyncd.secrets " . USER_SEARCH_IASK_LOG_PATH ."*"." backupuser@172.16.153.70::olympic_video/";
pclose(popen("touch {$iask_filename} && chmod 0664 {$iask_filename} && $command",
"r"));
$command="/usr/bin/rsync -avu " . $iask_filename ." 172.16.6.198::vblog/";
pclose(popen("touch {$iask_filename} && chmod 0664 {$iask_filename} && $command",
"r"));
$command="cp {$iask_filename} {$iask_filename_html}";
pclose(popen($command, "r"));
$command="/usr/bin/rsync -avu {$iask_filename_html} {$iask_filename} 10.68.1.30::v_blog_sina_com_cn/htdocs/ay_data/";
pclose(popen($command, "r"));
$command="/usr/bin/rsync -avu {$iask_filename_html} {$iask_filename} 10.68.1.71::v_blog_sina_com_cn/htdocs/ay_data/";
pclose(popen($command, "r"));
echo "[推送完成]\n";
}
echo "\n[完成]\n";
echo "程序于 " . date("Y-m-d H:i:s") . " 执行结束。\n\n";
function us_path_validate($path)
{
$arraypath = split("\/+", $path);
$tmppath = "";
for ($i = 0; $i < count($arraypath); $i++)
{
if ("" == $arraypath[$i])
continue;
$tmppath .= (0 == $i ? "":"/") . $arraypath[$i];
if (!is_dir($tmppath))
{
if (!mkdir($tmppath, 0777))
{
return false;
}
}
}
return true;
}
function us_writeFile($content, $filename, $dirpath)
{
if (!us_path_validate($dirpath))
exit();
$fp = fopen($filename, "a+");
if (!@fwrite($fp, $content . "\n"))
{
@fclose($fp);
return false;
}
fclose($fp);
return true;
}
function getContent($result,$i)
{
/*
if($i==0)
{
$str = "VID\tUID\t日期\n";
$str .= $result['vid'] . "\t";//视频总量
$str .= $result['uid'] . "\t";//userid,用户UID
$str .= date("Y-m-d",strtotime("-1 day")). "";
return $str;
}else{
*/
$str = $result['vid'] . "\t";//视频总量
$str .= $result['uid'] . "\t";//userid,用户UID
$str .= date("Y-m-d",strtotime("-1 day")) . "";
return $str;
// }
}
?>
实践时发现:
在做shell执行:ls /data/htdocs/pro/logs/*
出现多个文件时,最好是对返回串进行:rtrim($returnStr,"\n");
再:explode($returnStr,"\n"); 这样就不会有空数组了。
Example:
<?php
error_reporting(E_ALL);
while(1)
{
$handle=popen("more video_user_20080626_190223.txt|grep @docid:|wc","r");
$read = fread($handle, 2096);
echo $read;
pclose($handle);
sleep(1);
}
?>
二、调用PHP或其它语言有while(1)的特别注意点:
特别是调用串口的一直监控代码,尽可能要用到,读取返回值,否则就会启动不起来那个while的程序:
C:
vi startAutoAnserSer.php
$tomorrow = date("Y-m-d", mktime(0,0,0,4,1+1,2005));
$tomorrow = date("Y-m-d", mktime(0,0,0,date("m") ,date("d")+1,date("Y"))); //明天
$yesterday = date("Y-m-d", mktime(0,0,0,date("m") ,date("d")-1,date("Y"))); //昨天
$lastmonth = date("Y-m-d", mktime(0,0,0,date("m")-1,date("d"), date("Y"))); //上一个月
$nextyear = date("Y-m-d", mktime(0,0,0,date("m"), date("d", date("Y")+1)); //下一年
$today = date("Ymd",strtotime ("+1 day"));
$date1="2006-08-09″;
echo date(’Y-m-d’,strtotime("$date1 +5 day")); //相应地,要增加月,年,将day改成month或year即可
$tomorrow = date("Y-m-d", mktime(0,0,0,date("m") ,date("d")+1,date("Y"))); //明天
$yesterday = date("Y-m-d", mktime(0,0,0,date("m") ,date("d")-1,date("Y"))); //昨天
$lastmonth = date("Y-m-d", mktime(0,0,0,date("m")-1,date("d"), date("Y"))); //上一个月
$nextyear = date("Y-m-d", mktime(0,0,0,date("m"), date("d", date("Y")+1)); //下一年
$today = date("Ymd",strtotime ("+1 day"));
$date1="2006-08-09″;
echo date(’Y-m-d’,strtotime("$date1 +5 day")); //相应地,要增加月,年,将day改成month或year即可
1.需要移植crond和crontab
crontab使用大概有两种,一种是修改全局配置文件/etc/crontab,另一种是直接运行命令crontab -e.
全局配置没有详细测试,似乎直接运行crontab -e方便一些.
1.先把要加入定时任务的脚本写好
比如可以写test:
#!/bin/shzEmLinux联盟
cd /home/azEmLinux联盟
echo "Hello World!" > hellozEmLinux联盟
ls -l > mm
2.执行命令 crontab -e,此时系统会打开一个vi编辑器.
3.输入
59 23 * * * /home/a/test
表示每天23:59运行脚本bakuplog.sh.前面的时间格式为“M H D m d cmd”。其中,M代表分钟(0~59),H代表小时(0~23),D代表天(1~31),m代表月(1~12),d代表一星期内的天(0~6,0为星期天)。*表示任何.例如01 * * * * 表示每小时的01分执行.
4.重新启动这个进程
/etc/init.d/cron restart
crontab使用大概有两种,一种是修改全局配置文件/etc/crontab,另一种是直接运行命令crontab -e.
全局配置没有详细测试,似乎直接运行crontab -e方便一些.
1.先把要加入定时任务的脚本写好
比如可以写test:
#!/bin/shzEmLinux联盟
cd /home/azEmLinux联盟
echo "Hello World!" > hellozEmLinux联盟
ls -l > mm
2.执行命令 crontab -e,此时系统会打开一个vi编辑器.
3.输入
59 23 * * * /home/a/test
表示每天23:59运行脚本bakuplog.sh.前面的时间格式为“M H D m d cmd”。其中,M代表分钟(0~59),H代表小时(0~23),D代表天(1~31),m代表月(1~12),d代表一星期内的天(0~6,0为星期天)。*表示任何.例如01 * * * * 表示每小时的01分执行.
4.重新启动这个进程
/etc/init.d/cron restart
我已经在 10.210.71.254上安装了. 你可以直接测试.
webbench最多可以模拟3万个并发连接去测试网站的负载能力,个人感觉要比Apache自带的ab压力测试工具好,安装使用也特别方便。
1、适用系统:Linux
2、编译安装:
引用
wget http://blog.s135.com/soft/linux/webbench/webbench-1.5.tar.gz
tar zxvf webbench-1.5.tar.gz
cd webbench-1.5
make && make install
3、使用:
引用
webbench -c 500 -t 30 http://127.0.0.1/test.jpg
参数说明:-c表示并发数,-t表示时间(秒)
4、测试结果示例:
引用
Webbench - Simple Web Benchmark 1.5
Copyright (c) Radim Kolar 1997-2004, GPL Open Source Software.
Benchmarking: GET http://127.0.0.1/test.jpg
500 clients, running 30 sec.
Speed=3230 pages/min, 11614212 bytes/sec.
Requests: 1615 susceed, 0 failed.
webbench最多可以模拟3万个并发连接去测试网站的负载能力,个人感觉要比Apache自带的ab压力测试工具好,安装使用也特别方便。
1、适用系统:Linux
2、编译安装:
引用
wget http://blog.s135.com/soft/linux/webbench/webbench-1.5.tar.gz
tar zxvf webbench-1.5.tar.gz
cd webbench-1.5
make && make install
3、使用:
引用
webbench -c 500 -t 30 http://127.0.0.1/test.jpg
参数说明:-c表示并发数,-t表示时间(秒)
4、测试结果示例:
引用
Webbench - Simple Web Benchmark 1.5
Copyright (c) Radim Kolar 1997-2004, GPL Open Source Software.
Benchmarking: GET http://127.0.0.1/test.jpg
500 clients, running 30 sec.
Speed=3230 pages/min, 11614212 bytes/sec.
Requests: 1615 susceed, 0 failed.
主要是要这个:
5000并发,请求数100w
ab -c 5000 -n 1000000 'http://10.70.62.28/riddle.php?iid=56764&qid=56866&uid=1
&reply=56867,56868'
5000并发,请求数100w:
ab -c 5000 -n 1000000 'http://10.71.183.167/question.js'
rpm -qf /usr/bin/nload
nload-0.7.4-1.el6.x86_64
ab压测了一下10.70.62.28(就是白天压测掉的厉害的那台),测试结果我觉得挺好的。
并发4000,完成100w请求
cpu负载5左右浮动
Complete requests: 1000000
Failed requests: 21659
请求失败数是21659,计算了一下,100个人里有2个人失败
Requests per second: 5986.29 [#/sec] (mean) 相当于LR中的tps,几乎就是6000了
Time per request: 668.193 [ms] (mean) 用户等待每个请求时间,668毫秒
Time per request: 0.167 [ms] 服务器处理每个请求时间 0.167毫秒
网卡流量-取最大值
进-112Mbps
出-86Mbps
单独统计了一下nginx日志中http状态
"200" 978350
"500" 21664
状态码是500有21664,符合ab的测试结果中的 Failed requests: 21659
单独以ip地址建的web虚机,压测的产生的ngxin访问日志、错误日志也是单独的,就是为了统计一下http状态码的数量,然后和ab结果进行对比。
__________________________________________
apache压力测试ab
ab是Apache超文本传输协议(HTTP)的性能测试工具。其设计意图是描绘当前所安装的Apache的执行性能,主要是显示你安装的Apache每秒可以处理多少个请求
ab是Apache超文本传输协议(HTTP)的性能测试工具。其设计意图是描绘当前所安装的Apache的执行性能,主要是显示你安装的Apache每秒可以处理多少个请求。
概要
ab [ -A auth-username ] [ -c concurrency ] [ -C cookie-name=value ] [ -d ] [ -e csv-file ] [ -g gnuplot-file ] [ -h ] [ -H custom-header ] [ -i ] [ -k ] [ -n requests ] [ -p POST-file ] [ -P proxy-auth-username ] [ -q ] [ -s ] [ -S ] [ -t timelimit ] [ -T content-type ] [ -v verbosity] [ -V ] [ -w ] [ -x <table>-attributes ] [ -X proxy[] ] [ -y <tr>-attributes ] [ -z <td>-attributes ] [http://]hostname[:port]/path
选项
-A auth-username:password
对服务器提供BASIC认证信任。用户名和密码由一个:隔开,并以base64编码形式发送。无论服务器是否需要(即, 是否发送了401认证需求代码),此字符串都会被发送。
-c concurrency
一次产生的请求个数。默认是一次一个。
-C cookie-name=value
对请求附加一个Cookie:行。 其典型形式是name=value的一个参数对。此参数可以重复。
-d
不显示"percentage served within XX [ms] table"的消息(为以前的版本提供支持)。
-e csv-file
产生一个以逗号分隔的(CSV)文件,其中包含了处理每个相应百分比的请求所需要(从1%到100%)的相应百分比的(以微妙为单位)时间。由于这种格式已经“二进制化”,所以比'gnuplot'格式更有用。
-g gnuplot-file
把所有测试结果写入一个'gnuplot'或者TSV (以Tab分隔的)文件。此文件可以方便地导入到Gnuplot, IDL, Mathematica, Igor甚至Excel中。其中的第一行为标题。
-h
显示使用方法。
-H custom-header
对请求附加额外的头信息。此参数的典型形式是一个有效的头信息行,其中包含了以冒号分隔的字段和值的对 (如, "Accept-Encoding: zip/zop;8bit").
-i
执行HEAD请求,而不是GET。
-k
启用HTTP KeepAlive功能,即, 在一个HTTP会话中执行多个请求。默认时,不启用KeepAlive功能.
-n requests
在测试会话中所执行的请求个数。默认时,仅执行一个请求,但通常其结果不具有代表意义。
-p POST-file
包含了需要POST的数据的文件.
-P proxy-auth-username:password
对一个中转代理提供BASIC认证信任。用户名和密码由一个:隔开,并以base64编码形式发送。无论服务器是否需要(即, 是否发送了401认证需求代码),此字符串都会被发送。
-q
如果处理的请求数大于150, ab每处理大约10%或者100个请求时,会在stderr输出一个进度计数。此-q标记可以抑制这些信息。
-s
用于编译中(ab -h会显示相关信息)使用了SSL的受保护的https,而不是http协议的时候。此功能是实验性的,也是很简陋的。最好不要用。
-S
不显示中值和标准背离值,而且在均值和中值为标准背离值的1到2倍时,也不显示警告或出错信息。默认时,会显示最小值/均值/最大值等数值。(为以前的版本提供支持).
-t timelimit
测试所进行的最大秒数。其内部隐含值是-n 50000。它可以使对服务器的测试限制在一个固定的总时间以内。默认时,没有时间限制。
-T content-type
POST数据所使用的Content-type头信息。
-v verbosity
设置显示信息的详细程度 - 4或更大值会显示头信息, 3或更大值可以显示响应代码(404, 200等), 2或更大值可以显示警告和其他信息。
-V
显示版本号并退出。
-w
以HTML表的格式输出结果。默认时,它是白色背景的两列宽度的一张表。
-x <table>-attributes
设置<table>属性的字符串。 此属性被填入<table 这里 >.
-X proxy[:port]
对请求使用代理服务器。
-y <tr>-attributes
设置<tr>属性的字符串.
-z <td>-attributes
设置<td>属性的字符串.
缺陷
程序中有各种静态声明的固定长度的缓冲区。另外,对命令行参数、服务器的响应头和其他外部输入的解析也很简单,这可能会有不良后果。
它没有完整地实现HTTP/1.x; 仅接受某些'预想'的响应格式。 strstr(3)的频繁使用可能会带来性能问题,即, 你可能是在测试ab而不是服务器的性能。
----------------------------------------------------------------------------------------------------------------------
ex: 要執行 1000 次的 connection, 20 次的 concurrent (並行, 同時).
語法: ab -n 1000 -c 20 http://localhost/abc.php
產生出來的結果. 主要要注意的是以下幾個.
Time taken for tests: 總共執行花了多久的時間.(以上 1000 次共多久)
Requests per second: 每秒平均可以處理多少個 connection.
假设我们要对 echo.fcg 做测试,仿真 1000 次的联机请求,而且同一时间有 20 个并行的 (concurrent) 联机请求的情况,只要在命令列模式下执行 $ ab -n 1000 -c 20 http://localhost/fcgi-bin/echo.fcg 稍等一会,ApacheBench 会把结果秀出来,
This is ApacheBench, Version 1.3 Copyright c 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Copyright c 1998-1999 The Apache Group, http://www.apache.org/ Benchmarking localhost (be patient)...
Server Software: Apache/1.3.6
Server Hostname: localhost
Server Port: 80
Document Path: /fcgi-bin/echo.fcg
Document Length: 995 bytes
Concurrency Level: 20
Time taken for tests: 6.859 seconds
Complete requests: 1000
Failed requests: 0
Total transferred: 1142000 bytes HTML transferred: 995000 bytes
Requests per second: 145.79
Transfer rate: 166.50 kb/s received Connnection Times (ms) min avg
max Connect: 0 4 61
Processing: 62 128 771
Total: 62 132 832
以上结果指出,在同时间 20 个联机请求 (Concurrency Level) 的情况下,完成 1000 次的联机请求,共花了 6.859 秒 (Time taken for tests),因此这个程序每秒平均可以处理 (Requests per second) 145.79 个联机请求。 在接下来的评比测试中,我们就以每秒可以处理的联机请求数目来做为效能评比的依据。
5000并发,请求数100w
ab -c 5000 -n 1000000 'http://10.70.62.28/riddle.php?iid=56764&qid=56866&uid=1
&reply=56867,56868'
5000并发,请求数100w:
ab -c 5000 -n 1000000 'http://10.71.183.167/question.js'
rpm -qf /usr/bin/nload
nload-0.7.4-1.el6.x86_64
ab压测了一下10.70.62.28(就是白天压测掉的厉害的那台),测试结果我觉得挺好的。
并发4000,完成100w请求
cpu负载5左右浮动
Complete requests: 1000000
Failed requests: 21659
请求失败数是21659,计算了一下,100个人里有2个人失败
Requests per second: 5986.29 [#/sec] (mean) 相当于LR中的tps,几乎就是6000了
Time per request: 668.193 [ms] (mean) 用户等待每个请求时间,668毫秒
Time per request: 0.167 [ms] 服务器处理每个请求时间 0.167毫秒
网卡流量-取最大值
进-112Mbps
出-86Mbps
单独统计了一下nginx日志中http状态
"200" 978350
"500" 21664
状态码是500有21664,符合ab的测试结果中的 Failed requests: 21659
单独以ip地址建的web虚机,压测的产生的ngxin访问日志、错误日志也是单独的,就是为了统计一下http状态码的数量,然后和ab结果进行对比。
__________________________________________
apache压力测试ab
ab是Apache超文本传输协议(HTTP)的性能测试工具。其设计意图是描绘当前所安装的Apache的执行性能,主要是显示你安装的Apache每秒可以处理多少个请求
ab是Apache超文本传输协议(HTTP)的性能测试工具。其设计意图是描绘当前所安装的Apache的执行性能,主要是显示你安装的Apache每秒可以处理多少个请求。
概要
ab [ -A auth-username ] [ -c concurrency ] [ -C cookie-name=value ] [ -d ] [ -e csv-file ] [ -g gnuplot-file ] [ -h ] [ -H custom-header ] [ -i ] [ -k ] [ -n requests ] [ -p POST-file ] [ -P proxy-auth-username ] [ -q ] [ -s ] [ -S ] [ -t timelimit ] [ -T content-type ] [ -v verbosity] [ -V ] [ -w ] [ -x <table>-attributes ] [ -X proxy[] ] [ -y <tr>-attributes ] [ -z <td>-attributes ] [http://]hostname[:port]/path
选项
-A auth-username:password
对服务器提供BASIC认证信任。用户名和密码由一个:隔开,并以base64编码形式发送。无论服务器是否需要(即, 是否发送了401认证需求代码),此字符串都会被发送。
-c concurrency
一次产生的请求个数。默认是一次一个。
-C cookie-name=value
对请求附加一个Cookie:行。 其典型形式是name=value的一个参数对。此参数可以重复。
-d
不显示"percentage served within XX [ms] table"的消息(为以前的版本提供支持)。
-e csv-file
产生一个以逗号分隔的(CSV)文件,其中包含了处理每个相应百分比的请求所需要(从1%到100%)的相应百分比的(以微妙为单位)时间。由于这种格式已经“二进制化”,所以比'gnuplot'格式更有用。
-g gnuplot-file
把所有测试结果写入一个'gnuplot'或者TSV (以Tab分隔的)文件。此文件可以方便地导入到Gnuplot, IDL, Mathematica, Igor甚至Excel中。其中的第一行为标题。
-h
显示使用方法。
-H custom-header
对请求附加额外的头信息。此参数的典型形式是一个有效的头信息行,其中包含了以冒号分隔的字段和值的对 (如, "Accept-Encoding: zip/zop;8bit").
-i
执行HEAD请求,而不是GET。
-k
启用HTTP KeepAlive功能,即, 在一个HTTP会话中执行多个请求。默认时,不启用KeepAlive功能.
-n requests
在测试会话中所执行的请求个数。默认时,仅执行一个请求,但通常其结果不具有代表意义。
-p POST-file
包含了需要POST的数据的文件.
-P proxy-auth-username:password
对一个中转代理提供BASIC认证信任。用户名和密码由一个:隔开,并以base64编码形式发送。无论服务器是否需要(即, 是否发送了401认证需求代码),此字符串都会被发送。
-q
如果处理的请求数大于150, ab每处理大约10%或者100个请求时,会在stderr输出一个进度计数。此-q标记可以抑制这些信息。
-s
用于编译中(ab -h会显示相关信息)使用了SSL的受保护的https,而不是http协议的时候。此功能是实验性的,也是很简陋的。最好不要用。
-S
不显示中值和标准背离值,而且在均值和中值为标准背离值的1到2倍时,也不显示警告或出错信息。默认时,会显示最小值/均值/最大值等数值。(为以前的版本提供支持).
-t timelimit
测试所进行的最大秒数。其内部隐含值是-n 50000。它可以使对服务器的测试限制在一个固定的总时间以内。默认时,没有时间限制。
-T content-type
POST数据所使用的Content-type头信息。
-v verbosity
设置显示信息的详细程度 - 4或更大值会显示头信息, 3或更大值可以显示响应代码(404, 200等), 2或更大值可以显示警告和其他信息。
-V
显示版本号并退出。
-w
以HTML表的格式输出结果。默认时,它是白色背景的两列宽度的一张表。
-x <table>-attributes
设置<table>属性的字符串。 此属性被填入<table 这里 >.
-X proxy[:port]
对请求使用代理服务器。
-y <tr>-attributes
设置<tr>属性的字符串.
-z <td>-attributes
设置<td>属性的字符串.
缺陷
程序中有各种静态声明的固定长度的缓冲区。另外,对命令行参数、服务器的响应头和其他外部输入的解析也很简单,这可能会有不良后果。
它没有完整地实现HTTP/1.x; 仅接受某些'预想'的响应格式。 strstr(3)的频繁使用可能会带来性能问题,即, 你可能是在测试ab而不是服务器的性能。
----------------------------------------------------------------------------------------------------------------------
ex: 要執行 1000 次的 connection, 20 次的 concurrent (並行, 同時).
語法: ab -n 1000 -c 20 http://localhost/abc.php
產生出來的結果. 主要要注意的是以下幾個.
Time taken for tests: 總共執行花了多久的時間.(以上 1000 次共多久)
Requests per second: 每秒平均可以處理多少個 connection.
假设我们要对 echo.fcg 做测试,仿真 1000 次的联机请求,而且同一时间有 20 个并行的 (concurrent) 联机请求的情况,只要在命令列模式下执行 $ ab -n 1000 -c 20 http://localhost/fcgi-bin/echo.fcg 稍等一会,ApacheBench 会把结果秀出来,
This is ApacheBench, Version 1.3 Copyright c 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Copyright c 1998-1999 The Apache Group, http://www.apache.org/ Benchmarking localhost (be patient)...
Server Software: Apache/1.3.6
Server Hostname: localhost
Server Port: 80
Document Path: /fcgi-bin/echo.fcg
Document Length: 995 bytes
Concurrency Level: 20
Time taken for tests: 6.859 seconds
Complete requests: 1000
Failed requests: 0
Total transferred: 1142000 bytes HTML transferred: 995000 bytes
Requests per second: 145.79
Transfer rate: 166.50 kb/s received Connnection Times (ms) min avg
max Connect: 0 4 61
Processing: 62 128 771
Total: 62 132 832
以上结果指出,在同时间 20 个联机请求 (Concurrency Level) 的情况下,完成 1000 次的联机请求,共花了 6.859 秒 (Time taken for tests),因此这个程序每秒平均可以处理 (Requests per second) 145.79 个联机请求。 在接下来的评比测试中,我们就以每秒可以处理的联机请求数目来做为效能评比的依据。
正则表达式用于字符串处理、表单验证等场合,实用高效。现将一些常用的表达式收集于此,以备不时之需。
匹配中文字符的正则表达式: [\u4e00-\u9fa5]
评注:匹配中文还真是个头疼的事,有了这个表达式就好办了
匹配双字节字符(包括汉字在内):[^\x00-\xff]
评注:可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)
匹配空白行的正则表达式:\n\s*\r
评注:可以用来删除空白行
匹配HTML标记的正则表达式:<(\S*?)[^>]*>.*?|<.*? />
评注:网上流传的版本太糟糕,上面这个也仅仅能匹配部分,对于复杂的嵌套标记依旧无能为力
匹配首尾空白字符的正则表达式:^\s*|\s*$
评注:可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式
匹配Email地址的正则表达式:\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*
评注:表单验证时很实用
匹配网址URL的正则表达式:[a-zA-z]+://[^\s]*
评注:网上流传的版本功能很有限,上面这个基本可以满足需求
匹配帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
评注:表单验证时很实用
匹配国内电话号码:\d{3}-\d{8}|\d{4}-\d{7}
评注:匹配形式如 0511-4405222 或 021-87888822
匹配腾讯QQ号:[1-9][0-9]{4,}
评注:腾讯QQ号从10000开始
匹配中国邮政编码:[1-9]\d{5}(?!\d)
评注:中国邮政编码为6位数字
匹配身份证:\d{15}|\d{18}
评注:中国的身份证为15位或18位
匹配ip地址:\d+\.\d+\.\d+\.\d+
评注:提取ip地址时有用
匹配特定数字:
^[1-9]\d*$ //匹配正整数
^-[1-9]\d*$ //匹配负整数
^-?[1-9]\d*$ //匹配整数
^[1-9]\d*|0$ //匹配非负整数(正整数 + 0)
^-[1-9]\d*|0$ //匹配非正整数(负整数 + 0)
^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$ //匹配正浮点数
^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$ //匹配负浮点数
^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$ //匹配浮点数
^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$ //匹配非负浮点数(正浮点数 + 0)
^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$ //匹配非正浮点数(负浮点数 + 0)
评注:处理大量数据时有用,具体应用时注意修正
匹配特定字符串:
^[A-Za-z]+$ //匹配由26个英文字母组成的字符串
^[A-Z]+$ //匹配由26个英文字母的大写组成的字符串
^[a-z]+$ //匹配由26个英文字母的小写组成的字符串
^[A-Za-z0-9]+$ //匹配由数字和26个英文字母组成的字符串
^\w+$ //匹配由数字、26个英文字母或者下划线组成的字符串
评注:最基本也是最常用的一些表达式
许多元字符要求在试图匹配它们时特别对待。若要匹配这些特殊字符,必须首先使字符“转义”,即,将反斜杠字符 (\) 放在它们前面。下表列出了特殊字符以及它们的含义:
$ 匹配输入字符串结尾的位置。
如果设置了 RegExp 对象的 Multiline 属性,那么 $ 还匹配 \n 或 \r 前面的位置。若要匹配 $ 字符本身,请使用 \$。
( ) 标记子表达式的开始和结束。可以捕获子表达式以供以后使用。
若要匹配这两个字符,请使用 \( 和 \)。
* 零次或多次匹配前面的字符或子表达式。
若要匹配 * 字符,请使用 \*。
+ 一次或多次匹配前面的字符或子表达式。
若要匹配 + 字符,请使用 \+。
. 匹配除换行符 \n 之外的任何单个字符。
若要匹配 .,请使用 \。
[ ] 标记中括号表达式的开始。
若要匹配这些字符,请使用 \[ 和 \]。
? 零次或一次匹配前面的字符或子表达式,或指示“非贪心”限定符。
若要匹配 ? 字符,请使用 \?。
\ 将下一字符标记为特殊字符、文本、反向引用或八进制转义符。
例如,字符 n 匹配字符 n。\n 匹配换行符。序列 \\ 匹配 \,序列 \( 匹配 (。
/ 表示文本正则表达式的开始或结束。
若要匹配 / 字符,请使用 \/。
^ 匹配输入字符串开始处的位置,但在中括号表达式中使用的情况除外,在那种情况下它对字符集求反。
若要匹配 ^ 字符本身,请使用 \^。
{ } 标记限定符表达式的开始。
若要匹配这些字符,请使用 \{ 和 \}。
| 指出在两个项之间进行选择。
若要匹配 | ,请使用 \|
preg_match() 返回 pattern 所匹配的次数。要么是 0 次(没有匹配)或 1 次,因为 preg_match() 在第一次匹配之后将停止搜索。preg_match_all() 则相反,会一直搜索到 subject 的结尾处。如果出错 preg_match() 返回 FALSE。
提示:
如果只想查看一个字符串是否包含在另一个字符串中,不要用 preg_match()。可以用 strpos() 或 strstr() 替代,要快得多。
例1609.在文本中搜索“php”
copy to clipboard
<?php
// 模式定界符后面的 "i" 表示不区分大小写字母的搜索
if (preg_match ("/php/i", "PHP is the web scripting language of choice.")) {
print "A match was found.";
} else {
print "A match was not found.";
}
?>
例1610.搜索单词“web”
copy to clipboard
<?php
/* 模式中的 \b 表示单词的边界,因此只有独立的 "web" 单词会被匹配,
* 而不会匹配例如 "webbing" 或 "cobweb" 中的一部分 */
if (preg_match ("/\bweb\b/i", "PHP is the web scripting language of choice.")) {
print "A match was found.";
} else {
print "A match was not found.";
}
if (preg_match ("/\bweb\b/i", "PHP is the website scripting language of choice.")) {
print "A match was found.";
} else {
print "A match was not found.";
}
?>
例1611.从 URL 中取出域名
copy to clipboard
<?php
// 从 URL 中取得主机名
preg_match("/^(http:\/\/)?([^\/]+)/i",
"http://www.php.net/index.html", $matches);
$host = $matches[2];
// 从主机名中取得后面两段
preg_match("/[^\.\/]+\.[^\.\/]+$/", $host, $matches);
echo "domain name is: {$matches[0]}\n";
?>
匹配中文字符的正则表达式: [\u4e00-\u9fa5]
评注:匹配中文还真是个头疼的事,有了这个表达式就好办了
匹配双字节字符(包括汉字在内):[^\x00-\xff]
评注:可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)
匹配空白行的正则表达式:\n\s*\r
评注:可以用来删除空白行
匹配HTML标记的正则表达式:<(\S*?)[^>]*>.*?|<.*? />
评注:网上流传的版本太糟糕,上面这个也仅仅能匹配部分,对于复杂的嵌套标记依旧无能为力
匹配首尾空白字符的正则表达式:^\s*|\s*$
评注:可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式
匹配Email地址的正则表达式:\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*
评注:表单验证时很实用
匹配网址URL的正则表达式:[a-zA-z]+://[^\s]*
评注:网上流传的版本功能很有限,上面这个基本可以满足需求
匹配帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
评注:表单验证时很实用
匹配国内电话号码:\d{3}-\d{8}|\d{4}-\d{7}
评注:匹配形式如 0511-4405222 或 021-87888822
匹配腾讯QQ号:[1-9][0-9]{4,}
评注:腾讯QQ号从10000开始
匹配中国邮政编码:[1-9]\d{5}(?!\d)
评注:中国邮政编码为6位数字
匹配身份证:\d{15}|\d{18}
评注:中国的身份证为15位或18位
匹配ip地址:\d+\.\d+\.\d+\.\d+
评注:提取ip地址时有用
匹配特定数字:
^[1-9]\d*$ //匹配正整数
^-[1-9]\d*$ //匹配负整数
^-?[1-9]\d*$ //匹配整数
^[1-9]\d*|0$ //匹配非负整数(正整数 + 0)
^-[1-9]\d*|0$ //匹配非正整数(负整数 + 0)
^[1-9]\d*\.\d*|0\.\d*[1-9]\d*$ //匹配正浮点数
^-([1-9]\d*\.\d*|0\.\d*[1-9]\d*)$ //匹配负浮点数
^-?([1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0)$ //匹配浮点数
^[1-9]\d*\.\d*|0\.\d*[1-9]\d*|0?\.0+|0$ //匹配非负浮点数(正浮点数 + 0)
^(-([1-9]\d*\.\d*|0\.\d*[1-9]\d*))|0?\.0+|0$ //匹配非正浮点数(负浮点数 + 0)
评注:处理大量数据时有用,具体应用时注意修正
匹配特定字符串:
^[A-Za-z]+$ //匹配由26个英文字母组成的字符串
^[A-Z]+$ //匹配由26个英文字母的大写组成的字符串
^[a-z]+$ //匹配由26个英文字母的小写组成的字符串
^[A-Za-z0-9]+$ //匹配由数字和26个英文字母组成的字符串
^\w+$ //匹配由数字、26个英文字母或者下划线组成的字符串
评注:最基本也是最常用的一些表达式
许多元字符要求在试图匹配它们时特别对待。若要匹配这些特殊字符,必须首先使字符“转义”,即,将反斜杠字符 (\) 放在它们前面。下表列出了特殊字符以及它们的含义:
$ 匹配输入字符串结尾的位置。
如果设置了 RegExp 对象的 Multiline 属性,那么 $ 还匹配 \n 或 \r 前面的位置。若要匹配 $ 字符本身,请使用 \$。
( ) 标记子表达式的开始和结束。可以捕获子表达式以供以后使用。
若要匹配这两个字符,请使用 \( 和 \)。
* 零次或多次匹配前面的字符或子表达式。
若要匹配 * 字符,请使用 \*。
+ 一次或多次匹配前面的字符或子表达式。
若要匹配 + 字符,请使用 \+。
. 匹配除换行符 \n 之外的任何单个字符。
若要匹配 .,请使用 \。
[ ] 标记中括号表达式的开始。
若要匹配这些字符,请使用 \[ 和 \]。
? 零次或一次匹配前面的字符或子表达式,或指示“非贪心”限定符。
若要匹配 ? 字符,请使用 \?。
\ 将下一字符标记为特殊字符、文本、反向引用或八进制转义符。
例如,字符 n 匹配字符 n。\n 匹配换行符。序列 \\ 匹配 \,序列 \( 匹配 (。
/ 表示文本正则表达式的开始或结束。
若要匹配 / 字符,请使用 \/。
^ 匹配输入字符串开始处的位置,但在中括号表达式中使用的情况除外,在那种情况下它对字符集求反。
若要匹配 ^ 字符本身,请使用 \^。
{ } 标记限定符表达式的开始。
若要匹配这些字符,请使用 \{ 和 \}。
| 指出在两个项之间进行选择。
若要匹配 | ,请使用 \|
preg_match() 返回 pattern 所匹配的次数。要么是 0 次(没有匹配)或 1 次,因为 preg_match() 在第一次匹配之后将停止搜索。preg_match_all() 则相反,会一直搜索到 subject 的结尾处。如果出错 preg_match() 返回 FALSE。
提示:
如果只想查看一个字符串是否包含在另一个字符串中,不要用 preg_match()。可以用 strpos() 或 strstr() 替代,要快得多。
例1609.在文本中搜索“php”
copy to clipboard
<?php
// 模式定界符后面的 "i" 表示不区分大小写字母的搜索
if (preg_match ("/php/i", "PHP is the web scripting language of choice.")) {
print "A match was found.";
} else {
print "A match was not found.";
}
?>
例1610.搜索单词“web”
copy to clipboard
<?php
/* 模式中的 \b 表示单词的边界,因此只有独立的 "web" 单词会被匹配,
* 而不会匹配例如 "webbing" 或 "cobweb" 中的一部分 */
if (preg_match ("/\bweb\b/i", "PHP is the web scripting language of choice.")) {
print "A match was found.";
} else {
print "A match was not found.";
}
if (preg_match ("/\bweb\b/i", "PHP is the website scripting language of choice.")) {
print "A match was found.";
} else {
print "A match was not found.";
}
?>
例1611.从 URL 中取出域名
copy to clipboard
<?php
// 从 URL 中取得主机名
preg_match("/^(http:\/\/)?([^\/]+)/i",
"http://www.php.net/index.html", $matches);
$host = $matches[2];
// 从主机名中取得后面两段
preg_match("/[^\.\/]+\.[^\.\/]+$/", $host, $matches);
echo "domain name is: {$matches[0]}\n";
?>
在对正则表达式有了较为全面的了解之后,就可以在Perl,PHP,以及ASP等程式中使用正则表达式了。
下面以PHP语言为例,使用验证用户在线输入的邮件地址以及网址的格式是否正确。PHP 提供了eregi()或ereg()资料处理函数实现字串比对剖析的模式匹配操作ereg()函数的使用格式如下:
ereg (pattern, string)
其中,pattern代表正则表达式的模式;而string则是执行查找替换操作的目标对象,如Email地址值。本函式以 pattern 的规则来剖析比对字串 string,找到则传回值为 true。函式ereg()与eregi()的区别就是前者区分大小写,后者与大小写无关。使用PHP编写的程序代码如下:
<?php
if (ereg("^([a-z0-9_-])+@([a-zZ0-9_-])+(\.[a-z0-9_-])+[a-z]{2,3}$",$email))
{ echo "您的 E-Mail 通过初步检查!";}
else
{ echo "不是合法的E-Mail 地址,请重新输入!";}
?>
这个例子是可对使用者输入的 E-Mail 作简单的检查,检查使用者的 E-Mail 字串是否有 @ 字元,在 @ 字元前有小写英文字母、数字或下"_",在 @ 之后有数节字串,最后的小数点后只能有二个或三个小写英文字母。如webmaster@mail.sever.net, hello_2001@88new.cn就可以通过检查,而New99@253.com(出现大写字母)和new99@253.comn(最后的小数点后只能超过3个英文字母)就不能通过检查。
我们通过调用自定义正规则判别函式也可以进行检查操作,如下面的网址检验函式:
function VerifyWebSiteAddr ($strWebSiteAddr){
return (eregi ("^([_0-9a-z-]+.)+([0-9a-z-]+.)+[a-z]{2,3}$", $strWebSiteAddr));
}
我们知道,PHP程式的运行必须有服务器支持,如果您在自己的主页上想实现以上功能, 嵌入式脚本语言Javascript或许是好的选择。Javascript中带有一个功能强大的RegExp()对象,可以用来进行正则表达式的匹配操作。其中的test()方法可以检验目标对象中是否包含匹配模式,并相应的返回true或false。只须在HTML文档的<head>区域添加一段Javascript代码。
< language="Javascript1.2">
function verifyAddress(obj){
var email = obj.email.value;
var pattern = /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-])+/;
flag = pattern.test(email);
if(flag){
alert("您的 E-Mail 通过初步检查!");
return true;}
else{
alert("不是合法的E-Mail 地址,请重新输入!");
return false;}
}
</script>
然后在网页中输入信息的表单域<form>标签区域内中加入一行如下代码:
<onSubmit="return verifyAddress(this);">
当按下提交按钮后,首先运行verifyAddress()函式,进行匹配识别,如果满足条件则发送表单信息到目标页面,否则返回错误信息。
事实上,正则表达式的功能远非本文提到的这一点,下次,给大家介绍一种使用正则表达式从任意指定网页中析取任意种类文本信息(如网页中所有的图片文件名)的技巧。
Html源文件中image标签的析取
上篇,我们介绍了正则表达式的概念及其在网络编程中使用正则表达式验证用户在线输入的邮件地址以及网址的格式是否正确的应用实例,今天介绍一种从指定网页源文件中析取image标签的的编程技巧,即从网页源文件中,解析出所有的插图文件名(包括图片路径),也就是标签<img src=http://www.host01.com/Get/asp/regex/".../.../abc.jpg"> 中的文件名http://www.host01.com/Get/asp/regex/".../.../abc.jpg"(有的可能是gif格式)。编程环境:PHP+Apache for Win98。
首先, 用文本编辑器新建一个PHP类型的文件:abstractSRCfrompage.php3。为了方便讲解,我们打算是在浏览器表单域中输入需要析取image标签的网页的URL(或本机文档),提交后执行析取操作,所以在该文件中,我们要建立一个用于输入网址的表单,举例如下:
<form action=" abstractSRCfrompage.php3" method="post">
输入网址<input type=text name=filename><br>
<input type=submit name=submit value="提交">
</form>
输入正确的网址,提交后表单信息被送到abstractSRCfrompage.php3页面,由于表单本身就在该页面,所以相当于被送到自身页面,下面我们需要编写析取处理的PHP代码,紧接着表单代码段后写入如下代码:
<?php
if ($filename!=""){
$fp = fopen($filename, "r"); file://若输入不为空,开启本地或者远程档案;
while ($buffer = fgets($fp, 1024)) {
$source .=$buffer; }
fclose($fp);
file://查找$source中是否有<img ...src=http://www.host01.com/Get/asp/regex/".../...gif | jpg"> 这样的标记
if(eregi("(<img)+[^<>]+(src=\")+[^\*\"<>|]+(\.)+((gif)|(jpg))+(\")",$source)) {
echo "找到图片标签:)<br>";}
else{
echo "未发现图片标签:(<br>";}
file://拆分,第一次用标签,<img ...src=拆分,得到了以图形文件名开头的数组,
$splitres=split("((\">)|())+(<img)+[^<>]+(src=\")",$source);
echo "找到: $imagenums-1个图片<br>分别为:<br>";
for($i=1;$i<sizeof($splitres);$i++){
file://二次拆分,用"拆分。因为文件名能含有",得到的拆分数组的第一个元素就是路径+文件名了;
unset($imgname); // 再次使用前删除imgname变量;
$imgname=spliti("\"",$splitres[$i]);//将析取的图片信息依次赋给imgname变量
echo "$i=>".$imgname[0]."<br>"; file://输出析取的图片信息
}
}
?>
该段程序的设计思路是:PHP程式判断是否输入了档案名称(网址URL或本机档案名),若不为空则以只读方式打开该档案;接着使用函式fgets(fp,length)取得档案指标fp所指的行并传回该行内长度为length-1 的字串,上例中就是1024-1=1023;然后利用字串比对剖析函式ereg()查找$source中是否含有<img ...src=http://www.host01.com/Get/asp/regex/".../...gif | jpg"> 这样的标记(关于该函式在上篇中有详细的介绍);假如找到的话,则利用split()函式按一定的规则执行两次拆分,去掉标记中的<img…src=字符和"字符,结果得到数组splitres,其中的每一个元素都是以图形路径+文件名开头的数组;用for循环在屏幕上输出每个数组的第一个元素值,即我们所需要的所有图形路径+文件名。
其中函式sizeof($splitres)返回个数;在for循环中,依次将数组splitres的每个元素(也是数组)赋给数组变量imgname,并输出imgname的第一个元素值(为找到的一个图形路径+文件名),当执行下次循环时,删除变量imgname,达到重复使用的目的。大家可以仔细研究其中的奥妙。
好了,写好后,将abstractSRCfrompage.php3存到你的服务器指定目录下,启动Apache服务器,在浏览器中打开它,随便输入一个存在的网页名称或是远程URL,看看效果如何。
如果有兴趣,你可以尝试析取HTML文档中的任意感兴趣的信息,如果稍加改装,做一个网站文本搜索引擎岂不更妙?
下面以PHP语言为例,使用验证用户在线输入的邮件地址以及网址的格式是否正确。PHP 提供了eregi()或ereg()资料处理函数实现字串比对剖析的模式匹配操作ereg()函数的使用格式如下:
ereg (pattern, string)
其中,pattern代表正则表达式的模式;而string则是执行查找替换操作的目标对象,如Email地址值。本函式以 pattern 的规则来剖析比对字串 string,找到则传回值为 true。函式ereg()与eregi()的区别就是前者区分大小写,后者与大小写无关。使用PHP编写的程序代码如下:
<?php
if (ereg("^([a-z0-9_-])+@([a-zZ0-9_-])+(\.[a-z0-9_-])+[a-z]{2,3}$",$email))
{ echo "您的 E-Mail 通过初步检查!";}
else
{ echo "不是合法的E-Mail 地址,请重新输入!";}
?>
这个例子是可对使用者输入的 E-Mail 作简单的检查,检查使用者的 E-Mail 字串是否有 @ 字元,在 @ 字元前有小写英文字母、数字或下"_",在 @ 之后有数节字串,最后的小数点后只能有二个或三个小写英文字母。如webmaster@mail.sever.net, hello_2001@88new.cn就可以通过检查,而New99@253.com(出现大写字母)和new99@253.comn(最后的小数点后只能超过3个英文字母)就不能通过检查。
我们通过调用自定义正规则判别函式也可以进行检查操作,如下面的网址检验函式:
function VerifyWebSiteAddr ($strWebSiteAddr){
return (eregi ("^([_0-9a-z-]+.)+([0-9a-z-]+.)+[a-z]{2,3}$", $strWebSiteAddr));
}
我们知道,PHP程式的运行必须有服务器支持,如果您在自己的主页上想实现以上功能, 嵌入式脚本语言Javascript或许是好的选择。Javascript中带有一个功能强大的RegExp()对象,可以用来进行正则表达式的匹配操作。其中的test()方法可以检验目标对象中是否包含匹配模式,并相应的返回true或false。只须在HTML文档的<head>区域添加一段Javascript代码。
< language="Javascript1.2">
function verifyAddress(obj){
var email = obj.email.value;
var pattern = /^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+(\.[a-zA-Z0-9_-])+/;
flag = pattern.test(email);
if(flag){
alert("您的 E-Mail 通过初步检查!");
return true;}
else{
alert("不是合法的E-Mail 地址,请重新输入!");
return false;}
}
</script>
然后在网页中输入信息的表单域<form>标签区域内中加入一行如下代码:
<onSubmit="return verifyAddress(this);">
当按下提交按钮后,首先运行verifyAddress()函式,进行匹配识别,如果满足条件则发送表单信息到目标页面,否则返回错误信息。
事实上,正则表达式的功能远非本文提到的这一点,下次,给大家介绍一种使用正则表达式从任意指定网页中析取任意种类文本信息(如网页中所有的图片文件名)的技巧。
Html源文件中image标签的析取
上篇,我们介绍了正则表达式的概念及其在网络编程中使用正则表达式验证用户在线输入的邮件地址以及网址的格式是否正确的应用实例,今天介绍一种从指定网页源文件中析取image标签的的编程技巧,即从网页源文件中,解析出所有的插图文件名(包括图片路径),也就是标签<img src=http://www.host01.com/Get/asp/regex/".../.../abc.jpg"> 中的文件名http://www.host01.com/Get/asp/regex/".../.../abc.jpg"(有的可能是gif格式)。编程环境:PHP+Apache for Win98。
首先, 用文本编辑器新建一个PHP类型的文件:abstractSRCfrompage.php3。为了方便讲解,我们打算是在浏览器表单域中输入需要析取image标签的网页的URL(或本机文档),提交后执行析取操作,所以在该文件中,我们要建立一个用于输入网址的表单,举例如下:
<form action=" abstractSRCfrompage.php3" method="post">
输入网址<input type=text name=filename><br>
<input type=submit name=submit value="提交">
</form>
输入正确的网址,提交后表单信息被送到abstractSRCfrompage.php3页面,由于表单本身就在该页面,所以相当于被送到自身页面,下面我们需要编写析取处理的PHP代码,紧接着表单代码段后写入如下代码:
<?php
if ($filename!=""){
$fp = fopen($filename, "r"); file://若输入不为空,开启本地或者远程档案;
while ($buffer = fgets($fp, 1024)) {
$source .=$buffer; }
fclose($fp);
file://查找$source中是否有<img ...src=http://www.host01.com/Get/asp/regex/".../...gif | jpg"> 这样的标记
if(eregi("(<img)+[^<>]+(src=\")+[^\*\"<>|]+(\.)+((gif)|(jpg))+(\")",$source)) {
echo "找到图片标签:)<br>";}
else{
echo "未发现图片标签:(<br>";}
file://拆分,第一次用标签,<img ...src=拆分,得到了以图形文件名开头的数组,
$splitres=split("((\">)|())+(<img)+[^<>]+(src=\")",$source);
echo "找到: $imagenums-1个图片<br>分别为:<br>";
for($i=1;$i<sizeof($splitres);$i++){
file://二次拆分,用"拆分。因为文件名能含有",得到的拆分数组的第一个元素就是路径+文件名了;
unset($imgname); // 再次使用前删除imgname变量;
$imgname=spliti("\"",$splitres[$i]);//将析取的图片信息依次赋给imgname变量
echo "$i=>".$imgname[0]."<br>"; file://输出析取的图片信息
}
}
?>
该段程序的设计思路是:PHP程式判断是否输入了档案名称(网址URL或本机档案名),若不为空则以只读方式打开该档案;接着使用函式fgets(fp,length)取得档案指标fp所指的行并传回该行内长度为length-1 的字串,上例中就是1024-1=1023;然后利用字串比对剖析函式ereg()查找$source中是否含有<img ...src=http://www.host01.com/Get/asp/regex/".../...gif | jpg"> 这样的标记(关于该函式在上篇中有详细的介绍);假如找到的话,则利用split()函式按一定的规则执行两次拆分,去掉标记中的<img…src=字符和"字符,结果得到数组splitres,其中的每一个元素都是以图形路径+文件名开头的数组;用for循环在屏幕上输出每个数组的第一个元素值,即我们所需要的所有图形路径+文件名。
其中函式sizeof($splitres)返回个数;在for循环中,依次将数组splitres的每个元素(也是数组)赋给数组变量imgname,并输出imgname的第一个元素值(为找到的一个图形路径+文件名),当执行下次循环时,删除变量imgname,达到重复使用的目的。大家可以仔细研究其中的奥妙。
好了,写好后,将abstractSRCfrompage.php3存到你的服务器指定目录下,启动Apache服务器,在浏览器中打开它,随便输入一个存在的网页名称或是远程URL,看看效果如何。
如果有兴趣,你可以尝试析取HTML文档中的任意感兴趣的信息,如果稍加改装,做一个网站文本搜索引擎岂不更妙?
在这里我想总结一下取得地址栏内URL及文件所属的我更路径的一些信息:
运用$_SERVER[ ]我们可以来完成许多事情:它是一个包含头部(headers),路径信息及脚本位置的数组,数组的实体由web服务器创建。
这是一个“superglobal”,或者可以描述为自动全局变量。这只不过意味这它在所有的脚本中都有效。在函数或方法中您不需要使用global $_SERVER; 访问它,就如同使用 $HTTP_SERVER_VARS 一样。 $HTTP_SERVER_VARS 包含着同样的信息,但是不是一个自动全局变量。(注意: $HTTP_SERVER_VARS 和 $_SERVER 是不同的变量,PHP 处理它们的方式不同。)如果设置了 register_globals 指令,这些变量也在所有脚本中可用;也就是,分离了 $_SERVER 和 $HTTP_SERVER_VARS 数组。
$_SERVER['HTTP_HOST'] 取得当前请求的Host:头部内容
$_SERVER['PHP_SELF']这可能是我们最为经常用到的了,它返回当前调用 的页的文件名,如果是http://localhost/test/2005/test.php, 那么将会返回/test/2005/test.php
$_SERVER['SCRIPT_NAME']它将返回包含当前脚本的路径。这在页面需要指向自己时非常有用
$_SERVER['SCRIPT_FILENAME']它将返回当前文件所在的绝对路径信息
$_SERVER['REQUEST_URI']返回访问此页面所需的URI,包括"/"
当然还有许多路径函数:
dirname(),返回路径信息中的目录部分,前面是带有"/"的
basename()返回路径中的基本的文件名部分,当然也可以设置后缀来控制输出。
realpath(),返回路径信息的绝对规范化的路径
运用$_SERVER[ ]我们可以来完成许多事情:它是一个包含头部(headers),路径信息及脚本位置的数组,数组的实体由web服务器创建。
这是一个“superglobal”,或者可以描述为自动全局变量。这只不过意味这它在所有的脚本中都有效。在函数或方法中您不需要使用global $_SERVER; 访问它,就如同使用 $HTTP_SERVER_VARS 一样。 $HTTP_SERVER_VARS 包含着同样的信息,但是不是一个自动全局变量。(注意: $HTTP_SERVER_VARS 和 $_SERVER 是不同的变量,PHP 处理它们的方式不同。)如果设置了 register_globals 指令,这些变量也在所有脚本中可用;也就是,分离了 $_SERVER 和 $HTTP_SERVER_VARS 数组。
$_SERVER['HTTP_HOST'] 取得当前请求的Host:头部内容
$_SERVER['PHP_SELF']这可能是我们最为经常用到的了,它返回当前调用 的页的文件名,如果是http://localhost/test/2005/test.php, 那么将会返回/test/2005/test.php
$_SERVER['SCRIPT_NAME']它将返回包含当前脚本的路径。这在页面需要指向自己时非常有用
$_SERVER['SCRIPT_FILENAME']它将返回当前文件所在的绝对路径信息
$_SERVER['REQUEST_URI']返回访问此页面所需的URI,包括"/"
当然还有许多路径函数:
dirname(),返回路径信息中的目录部分,前面是带有"/"的
basename()返回路径中的基本的文件名部分,当然也可以设置后缀来控制输出。
realpath(),返回路径信息的绝对规范化的路径
http://hometown.aol.de/_ht_a/memtronic/
download:http://download.microsoft.com/download/7/b/9/7b90644d-1af0-42b9-b76d-a2770319a568/dotnetfx.exe
http://www.x2blog.cn/supNate/UserFiles/X2JSCompactor.rar
blogurl:http://www.x2blog.cn/supnate/?tid=4175
对哦无奈哦:下载
download:http://download.microsoft.com/download/7/b/9/7b90644d-1af0-42b9-b76d-a2770319a568/dotnetfx.exe
http://www.x2blog.cn/supNate/UserFiles/X2JSCompactor.rar
blogurl:http://www.x2blog.cn/supnate/?tid=4175
对哦无奈哦:下载
# 将domain.com/xxx转向www.domain.com/xxx
RewriteCond %{HTTP_HOST} ^domain.com [NC]
RewriteRule ^(.*)$ http://www.domain.com$1 [R=301,NC]
# 将xxx.domain.com/yyy...重定向到www.domain.com/xxx/yyy..., xxx 5-20位, 字母开头只含字母, 数字以及"-"和"_"
RewriteCond %{SERVER_NAME} ^([a-z][a-z0-9\-\_]{4,19})\.domain\.com [NC]
RewriteRule ^(.+)$ %{SERVER_NAME}$1 [C]
RewriteRule ^([a-z][a-z0-9\-\_]{4,19})\.domain\.com(.*)$ http://www.domain.com/$1$2 [R=301,NC]
# 将首页www.domain.com转向www.domain.com/html/index.html
RewriteCond %{HTTP_HOST} www\.domain\.com
RewriteRule ^/$ http://www.domain.com/html/index.html [R=301,L]
RewriteCond %{HTTP_HOST} ^domain.com [NC]
RewriteRule ^(.*)$ http://www.domain.com$1 [R=301,NC]
# 将xxx.domain.com/yyy...重定向到www.domain.com/xxx/yyy..., xxx 5-20位, 字母开头只含字母, 数字以及"-"和"_"
RewriteCond %{SERVER_NAME} ^([a-z][a-z0-9\-\_]{4,19})\.domain\.com [NC]
RewriteRule ^(.+)$ %{SERVER_NAME}$1 [C]
RewriteRule ^([a-z][a-z0-9\-\_]{4,19})\.domain\.com(.*)$ http://www.domain.com/$1$2 [R=301,NC]
# 将首页www.domain.com转向www.domain.com/html/index.html
RewriteCond %{HTTP_HOST} www\.domain\.com
RewriteRule ^/$ http://www.domain.com/html/index.html [R=301,L]
function init_space_user_friend_unicode()
{
if(typeof SpaceUserFriend !="undefined")
{
try{
//*
SpaceUserFriend.traceInfo = function (sMSG) {
alert("信息: " + sMSG)
};
//*/
}catch(e){
}
var tmp=SpaceUserFriend.createContent();
//alert(tmp)
document.getElementById("innerDiv").innerHTML=tmp;
SpaceUserFriend.init();
}else
{
setTimeout(function(){
init_space_user_friend_unicode();
},100
)
}
}init_space_user_friend_unicode();
经常会在js里用到数组,比如 多个名字相同的input, 若是动态生成的, 提交时就需要判断其是否是数组.
if(document.mylist.length != "undefined" ) {} 这个用法有误.
正确的是 if( typeof(document.mylist.length) != "undefined" ) {}
或 if( !isNaN(document.mylist.length) ) {}
typeof的运算数未定义,返回的就是 "undefined".
运算数为数字 typeof(x) = "number"
字符串 typeof(x) = "string"
布尔值 typeof(x) = "boolean"
对象,数组和null typeof(x) = "object"
函数 typeof(x) = "function"
typeof 运算符返回一个用来表示表达式的数据类型的字符串。
可能的字符串有:"number"、"string"、"boolean"、"object"、"function" 和 "undefined"。
如:
alert(typeof (123));//typeof(123)返回"number"
alert(typeof ("123"));//typeof("123")返回"string"
typeof 运算符
返回一个用来表示表达式的数据类型的字符串。
typeof[()expression[]] ;
expression 参数是需要查找类型信息的任意表达式。
说明
typeof 运算符把类型信息当作字符串返回。typeof 返回值有六种可能: "number," "string," "boolean," "object," "function," 和 "undefined."
typeof 语法中的圆括号是可选项。
在很多情况下,需要定期的刷新页面,比如显示股票或者比赛比分的页面(当然现在一般都是通过ajax去定期的从后台取数据,然后更新局部页面),又或者你网站的域名换了以后,当用户打开旧网站的时候重定向到新域名(告诉用户5秒钟后转到另一个页面等等)。
<html>
<head>
<script type="text/javascript">
function delayedRedirect(){
window.location = "http://www.collin.cn"
}
</script>
</head>
<body onLoad="setTimeout('delayedRedirect()', 5000)">
<h2>5秒钟后你将重定向到www.collin.cn!</h2>
</body>
</html>
{
if(typeof SpaceUserFriend !="undefined")
{
try{
//*
SpaceUserFriend.traceInfo = function (sMSG) {
alert("信息: " + sMSG)
};
//*/
}catch(e){
}
var tmp=SpaceUserFriend.createContent();
//alert(tmp)
document.getElementById("innerDiv").innerHTML=tmp;
SpaceUserFriend.init();
}else
{
setTimeout(function(){
init_space_user_friend_unicode();
},100
)
}
}init_space_user_friend_unicode();
经常会在js里用到数组,比如 多个名字相同的input, 若是动态生成的, 提交时就需要判断其是否是数组.
if(document.mylist.length != "undefined" ) {} 这个用法有误.
正确的是 if( typeof(document.mylist.length) != "undefined" ) {}
或 if( !isNaN(document.mylist.length) ) {}
typeof的运算数未定义,返回的就是 "undefined".
运算数为数字 typeof(x) = "number"
字符串 typeof(x) = "string"
布尔值 typeof(x) = "boolean"
对象,数组和null typeof(x) = "object"
函数 typeof(x) = "function"
typeof 运算符返回一个用来表示表达式的数据类型的字符串。
可能的字符串有:"number"、"string"、"boolean"、"object"、"function" 和 "undefined"。
如:
alert(typeof (123));//typeof(123)返回"number"
alert(typeof ("123"));//typeof("123")返回"string"
typeof 运算符
返回一个用来表示表达式的数据类型的字符串。
typeof[()expression[]] ;
expression 参数是需要查找类型信息的任意表达式。
说明
typeof 运算符把类型信息当作字符串返回。typeof 返回值有六种可能: "number," "string," "boolean," "object," "function," 和 "undefined."
typeof 语法中的圆括号是可选项。
在很多情况下,需要定期的刷新页面,比如显示股票或者比赛比分的页面(当然现在一般都是通过ajax去定期的从后台取数据,然后更新局部页面),又或者你网站的域名换了以后,当用户打开旧网站的时候重定向到新域名(告诉用户5秒钟后转到另一个页面等等)。
<html>
<head>
<script type="text/javascript">
function delayedRedirect(){
window.location = "http://www.collin.cn"
}
</script>
</head>
<body onLoad="setTimeout('delayedRedirect()', 5000)">
<h2>5秒钟后你将重定向到www.collin.cn!</h2>
</body>
</html>
<html>
<script language="javascript">
function updatedoc()
{
document.writeln("abc<br>");
document.writeln("def<br>");
document.writeln('<script language="javascript">');
document.writeln('function updatedoc()');
document.writeln('{');
document.writeln(' document.writeln("first<br>");');
document.writeln(' document.writeln("second<br>");');
document.writeln('}');
document.writeln('</scr'+'ipt>');
document.writeln('<input type=button name="update" value="更新" onclick="updatedoc()">');
}
</script>
<input type=button name="update" value="更新" onclick="updatedoc()">
</html>
/*这里不能写作</script>,否则系统会报错,其默认与上面的<script language="javascript"> 匹配。所以应当注意^_^*/
URL:http://www.cnblogs.com/happiness/archive/2006/04/18/377880.html
<script language="javascript">
function updatedoc()
{
document.writeln("abc<br>");
document.writeln("def<br>");
document.writeln('<script language="javascript">');
document.writeln('function updatedoc()');
document.writeln('{');
document.writeln(' document.writeln("first<br>");');
document.writeln(' document.writeln("second<br>");');
document.writeln('}');
document.writeln('</scr'+'ipt>');
document.writeln('<input type=button name="update" value="更新" onclick="updatedoc()">');
}
</script>
<input type=button name="update" value="更新" onclick="updatedoc()">
</html>
/*这里不能写作</script>,否则系统会报错,其默认与上面的<script language="javascript"> 匹配。所以应当注意^_^*/
URL:http://www.cnblogs.com/happiness/archive/2006/04/18/377880.html
http://www.picavr.com/news/2008-02/4172.htm
用USB接口的数据采集系统,使用简单方便,无需外接电源,还可以利用PC机强大的运算能力处理数据。这类系统一般都要用单片机做接口控制,对于不会使用单片机的人是个难题。这里介绍一个不用单片机的USB数据采集系统,只要会用VB编程就可以实现。
参考链接:http://www.picavr.com/news/2008-02/4172.htm
一、系统的硬件构成
本系统的电原理如上图,CH371是USB接口芯片,MAX197多路AD转换器做数据采集,电脑对采集的数据进行处理。
CH371是南京沁恒电子出品的一种简单易用的USB接口芯片,它包括芯片本身和计算机端的通用驱动程序。CH371以硬件逻辑实现了USB通信协议传输控制的整个过程,通用驱动程序通过软件向计算机应用层提供设备级接口,因此用户不必考虑USB通信协议、固件程序、驱动程序、底层数据传输过程等,就可以设计出各种USB接口设备。
CH371有多种工作方式,除了数据传输方式外,它还可以工作在一种主控方式,即使没有连结单片机、DSP等控制器,也可以输出控制信号和输入数据。CH371的D7~D0、A3~A0都是双向引脚,它们可以被分为两组,分别设置用于输入或输出。把CH371的A3~A0与MAX197的CS、WR、RD、HBEN四根输入控制线相连,把D7~D0和MAX197的并行数据端口相连,就可以通过软件直接控制MAX197的工作。
MAX197是MAXIM推出的12位AD转换器,单5伏供电,内置4.096伏电压基准,外围电路很简单,仅需外接几只电容就可以工作。MAX197有内外两种时钟和采样模式,模拟输入量程和极性可选,有0~5伏、0~10伏、±5伏、±10伏四种。有8个模拟输入通道。所有这些都可以通过软件来选择,即向MAX197写入一个字节的控制字来实现,控制字的各位功能见下表:
位
PD1
PD0
ACQMOD
RNG
BIP
A2
A1
A0
功能
内外时钟和电源管理模式
内外控制采样模式
模拟信号量程
模拟信号极性
模拟输入通道选择
二、系统的软件设计
1. CH371计算机端的软件接口
CH371在计算机端提供了三个层次的软件接口,最高层是应用层接口。应用层接口是由CH371动态链接库DLL提供的面向功能应用的API函数。每个函数实现一个具体的功能,并用简便易用的API参数代替设备级接口中所要求的数据格式,所有API在调用后都有操作状态返回,用户只要选择特定的API函数就可以实现所需的功能。
CH371动态链接库DLL提供的的API函数包括设备管理、数据传输、中断查询、I2C操作和直接控制等几类,我们这里要用的是两个直接控制函数。
CH371GetStatus(ByVal iIndex As Long, ByVal iStatus As Long,ByRef iDataReg As Long)As Boolean
它的功能是通过CH371直接输入数据和状态,其中iIndex指定CH37设备序号,iStatus指向一个双字单元,用于保存状态数据。Bit7~Bit0对应CH371的D7~D0引脚。IDataReg指向一个双字单元,用于保存数据寄存器的数据。
CH371SetControl(ByVal iIndex As Long, ByVal iCtrData As Byte, ByVal iCtrlAddr As Byte,ByVal iData0e As Boolean, ByVal iAddr0e As Boolean)As Boolean
它的功能是通过CH371直接输出控制信号。ICtrData是准备写入D7~D0数据寄存器的数据, iCtrlAddr是准备写入A3~A0数据寄存器的数据, 它们都必须在输出使能时才可以输出数据。iData0e控制D7~D0输出使能,1输出、0输入。iAddr0e控制A3~A0输出使能,1输出、0输入。
2. VB应用程序
应用程序是用VB编写的,它的核心就是调用上述两个API函数,通过CH371的D7~D0和A3~A0向MAX197写入控制字,启动模数转换,最后读出转换结果。VB要使用CH371动态链接库中的API函数,首先要用Declare语句在全局模块的代码段声明这些函数,CH371芯片厂商在其提供的VB DEMO中,有两个MODULE已经包含了CH371所有的API函数,用户只需要在自己的工程项目中将其加入即可。通过这两个函数调用,向MAX197写入控制字,设定模数转换器的工作方式、选择输入通道、启动模数转换,最后读入转换结果,存入电脑,再做进一步处理
参考链接:http://www.picavr.com/news/2008-02/4172.htm
由于CH371芯片的功能有限,对于新客户建议用下列芯片代替CH371,
新的芯片比CH371功能更多,更易使用,数据传输速度更快,成本更低
1、如果应用电路中有单片机或者DSP等,打算通过USB与计算机通讯,
那么建议用CH372或者CH375或者CH374代替CH371,
因为CH372/CH375/CH374的缓冲区是CH371的8倍,所以传输速度更快,
可达每秒300K甚至800K字节以上,即使是MCS51单片机也能够达到300KB
2、如果应用电路中没有单片机和DSP,只是打算通过CH371直接控制
外部逻辑电路,那么建议用CH341代替CH371,
因为CH341可以提供异步串口、并口以及类似I2C的两线串行接口,
CH341的串口波特率支持从50bps到2000000bps,支持速率控制,
CH341的并口有两种时序,分别是8位仿EPP并口和8位仿MEM并口,
并口的速度可达每秒300K字节,不但速度快而且容易I/O扩展,
CH341的仿I2C接口的时钟约为200KHz,传输速度约为每秒7KB
3、CH372或CH375或CH374必须在单片机或DSP的控制下才能与计算机通讯,
CH375和CH374还能与USB设备(如U盘、USB打印机、USB摄像头)通讯,
CH341可以直接与计算机通讯,不需要单片机或者DSP,可以用于
I/O扩展,I/O控制,简单的AD或者DA,USB转串口、USB转并口等。
4、网站上有用CH375或者CH374或者CH372升级CH371的详细说明,
注意,CH372/CH375/CH374和CH341与CH371的部分引脚不同
5、如果有其它技术问题,请联系技术支持EMAIL:
tech@winchiphead.com
用USB接口的数据采集系统,使用简单方便,无需外接电源,还可以利用PC机强大的运算能力处理数据。这类系统一般都要用单片机做接口控制,对于不会使用单片机的人是个难题。这里介绍一个不用单片机的USB数据采集系统,只要会用VB编程就可以实现。
参考链接:http://www.picavr.com/news/2008-02/4172.htm
一、系统的硬件构成
本系统的电原理如上图,CH371是USB接口芯片,MAX197多路AD转换器做数据采集,电脑对采集的数据进行处理。
CH371是南京沁恒电子出品的一种简单易用的USB接口芯片,它包括芯片本身和计算机端的通用驱动程序。CH371以硬件逻辑实现了USB通信协议传输控制的整个过程,通用驱动程序通过软件向计算机应用层提供设备级接口,因此用户不必考虑USB通信协议、固件程序、驱动程序、底层数据传输过程等,就可以设计出各种USB接口设备。
CH371有多种工作方式,除了数据传输方式外,它还可以工作在一种主控方式,即使没有连结单片机、DSP等控制器,也可以输出控制信号和输入数据。CH371的D7~D0、A3~A0都是双向引脚,它们可以被分为两组,分别设置用于输入或输出。把CH371的A3~A0与MAX197的CS、WR、RD、HBEN四根输入控制线相连,把D7~D0和MAX197的并行数据端口相连,就可以通过软件直接控制MAX197的工作。
MAX197是MAXIM推出的12位AD转换器,单5伏供电,内置4.096伏电压基准,外围电路很简单,仅需外接几只电容就可以工作。MAX197有内外两种时钟和采样模式,模拟输入量程和极性可选,有0~5伏、0~10伏、±5伏、±10伏四种。有8个模拟输入通道。所有这些都可以通过软件来选择,即向MAX197写入一个字节的控制字来实现,控制字的各位功能见下表:
位
PD1
PD0
ACQMOD
RNG
BIP
A2
A1
A0
功能
内外时钟和电源管理模式
内外控制采样模式
模拟信号量程
模拟信号极性
模拟输入通道选择
二、系统的软件设计
1. CH371计算机端的软件接口
CH371在计算机端提供了三个层次的软件接口,最高层是应用层接口。应用层接口是由CH371动态链接库DLL提供的面向功能应用的API函数。每个函数实现一个具体的功能,并用简便易用的API参数代替设备级接口中所要求的数据格式,所有API在调用后都有操作状态返回,用户只要选择特定的API函数就可以实现所需的功能。
CH371动态链接库DLL提供的的API函数包括设备管理、数据传输、中断查询、I2C操作和直接控制等几类,我们这里要用的是两个直接控制函数。
CH371GetStatus(ByVal iIndex As Long, ByVal iStatus As Long,ByRef iDataReg As Long)As Boolean
它的功能是通过CH371直接输入数据和状态,其中iIndex指定CH37设备序号,iStatus指向一个双字单元,用于保存状态数据。Bit7~Bit0对应CH371的D7~D0引脚。IDataReg指向一个双字单元,用于保存数据寄存器的数据。
CH371SetControl(ByVal iIndex As Long, ByVal iCtrData As Byte, ByVal iCtrlAddr As Byte,ByVal iData0e As Boolean, ByVal iAddr0e As Boolean)As Boolean
它的功能是通过CH371直接输出控制信号。ICtrData是准备写入D7~D0数据寄存器的数据, iCtrlAddr是准备写入A3~A0数据寄存器的数据, 它们都必须在输出使能时才可以输出数据。iData0e控制D7~D0输出使能,1输出、0输入。iAddr0e控制A3~A0输出使能,1输出、0输入。
2. VB应用程序
应用程序是用VB编写的,它的核心就是调用上述两个API函数,通过CH371的D7~D0和A3~A0向MAX197写入控制字,启动模数转换,最后读出转换结果。VB要使用CH371动态链接库中的API函数,首先要用Declare语句在全局模块的代码段声明这些函数,CH371芯片厂商在其提供的VB DEMO中,有两个MODULE已经包含了CH371所有的API函数,用户只需要在自己的工程项目中将其加入即可。通过这两个函数调用,向MAX197写入控制字,设定模数转换器的工作方式、选择输入通道、启动模数转换,最后读入转换结果,存入电脑,再做进一步处理
参考链接:http://www.picavr.com/news/2008-02/4172.htm
由于CH371芯片的功能有限,对于新客户建议用下列芯片代替CH371,
新的芯片比CH371功能更多,更易使用,数据传输速度更快,成本更低
1、如果应用电路中有单片机或者DSP等,打算通过USB与计算机通讯,
那么建议用CH372或者CH375或者CH374代替CH371,
因为CH372/CH375/CH374的缓冲区是CH371的8倍,所以传输速度更快,
可达每秒300K甚至800K字节以上,即使是MCS51单片机也能够达到300KB
2、如果应用电路中没有单片机和DSP,只是打算通过CH371直接控制
外部逻辑电路,那么建议用CH341代替CH371,
因为CH341可以提供异步串口、并口以及类似I2C的两线串行接口,
CH341的串口波特率支持从50bps到2000000bps,支持速率控制,
CH341的并口有两种时序,分别是8位仿EPP并口和8位仿MEM并口,
并口的速度可达每秒300K字节,不但速度快而且容易I/O扩展,
CH341的仿I2C接口的时钟约为200KHz,传输速度约为每秒7KB
3、CH372或CH375或CH374必须在单片机或DSP的控制下才能与计算机通讯,
CH375和CH374还能与USB设备(如U盘、USB打印机、USB摄像头)通讯,
CH341可以直接与计算机通讯,不需要单片机或者DSP,可以用于
I/O扩展,I/O控制,简单的AD或者DA,USB转串口、USB转并口等。
4、网站上有用CH375或者CH374或者CH372升级CH371的详细说明,
注意,CH372/CH375/CH374和CH341与CH371的部分引脚不同
5、如果有其它技术问题,请联系技术支持EMAIL:
tech@winchiphead.com
用PHP的ob_start();控制您的浏览器cache!
Output Control 函数可以让你自由控制脚本中数据的输出。它非常地有用,特别是对于:当你想在数据已经输出后,再输出文件头的情况。输出控制函数不对使用 header() 或 setcookie(), 发送的文件头信息产生影响,只对那些类似于 echo() 和 PHP 代码的数据块有作用。
我们先举一个简单的例子,让大家对Output Control有一个大致的印象:
Example 1.
所有对header()函数有了解的人都知道,这个函数会发送一段文件头给浏览器,但是如果在使用这个函数之前已经有了任何输出(包括空输出,比如空格,回车和换行)就会提示出错。如果我们去掉第一行的ob_start(),再执行此程序,我们会发现得到了一条错误提示:"Header had all ready send by"!但是加上ob_start,就不会提示出错,原因是当打开了缓冲区,echo后面的字符不会输出到浏览器,而是保留在服务器,直到你使用 flush或者ob_end_flush才会输出,所以并不会有任何文件头输出的错误!
一、 相关函数简介:
1、Flush:刷新缓冲区的内容,输出。
函数格式:flush()
说明:这个函数经常使用,效率很高。
2、ob_start :打开输出缓冲区
函数格式:void ob_start(void)
说明:当缓冲区激活时,所有来自PHP程序的非文件头信息均不会发送,而是保存在内部缓冲区。为了输出缓冲区的内容,可以使用ob_end_flush()或flush()输出缓冲区的内容。
3 、ob_get_contents :返回内部缓冲区的内容。
使用方法:string ob_get_contents(void)
说明:这个函数会返回当前缓冲区中的内容,如果输出缓冲区没有激活,则返回 FALSE 。
4、ob_get_length:返回内部缓冲区的长度。
使用方法:int ob_get_length(void)
说明:这个函数会返回当前缓冲区中的长度;和ob_get_contents一样,如果输出缓冲区没有激活。则返回 FALSE。
5、ob_end_flush :发送内部缓冲区的内容到浏览器,并且关闭输出缓冲区。
使用方法:void ob_end_flush(void)
说明:这个函数发送输出缓冲区的内容(如果有的话)。
6、ob_end_clean:删除内部缓冲区的内容,并且关闭内部缓冲区
使用方法:void ob_end_clean(void)
说明:这个函数不会输出内部缓冲区的内容而是把它删除!
7、ob_implicit_flush:打开或关闭绝对刷新
使用方法:void ob_implicit_flush ([int flag])
说明:使用过Perl的人都知道$|=x的意义,这个字符串可以打开/关闭缓冲区,而ob_implicit_flush函数也和那个一样,默认为关闭缓冲区,打开绝对输出后,每个脚本输出都直接发送到浏览器,不再需要调用 flush()
二、深入了解:
1. 关于Flush函数:
这个函数在PHP3中就出现了,是一个效率很高的函数,他有一个非常有用的功能就是刷新browser的cache.我们举一个运行效果非常明显的例子来说明flush.
Example 2.
CODE<?php
for($i = 1; $i <= 300; $i++ ) print(" ");
// 这一句话非常关键,cache的结构使得它的内容只有达到一定的大小才能从浏览器里输出
// 换言之,如果cache的内容不达到一定的大小,它是不会在程序执行完毕前输出的。经
// 过测试,我发现这个大小的底限是256个字符长。这意味着cache以后接收的内容都会
// 源源不断的被发送出去。
For($j = 1; $j <= 20; $j++) {
echo $j."
";
flush(); //这一部会使cache新增的内容被挤出去,显示到浏览器上
sleep(1); //让程序"睡"一秒钟,会让你把效果看得更清楚
}
?>
具体效果你可以到这里看看http://www.php2000.com/~uchinaboy/out.php
PHP2000的最新的PHP聊天室就是用的这个技术,可惜的是源代码未公开 L
注:如果在程序的首部加入ob_implicit_flush()打开绝对刷新,就可以在程序中不再使用flush(),这样做的好处是:提高效率!
2. 关于ob系列函数:
我想先引用我的好朋友y10k的一个例子:
Example 3.
比如你用得到服务器和客户端的设置信息,但是这个信息会因为客户端的不同而不同,如果想要保存phpinfo()函数的输出怎么办呢?在没有缓冲区控制之前,可以说一点办法也没有,但是有了缓冲区的控制,我们可以轻松的解决:
CODE<?php
ob_start(); //打开缓冲区
phpinfo(); //使用phpinfo函数
$info=ob_get_contents(); //得到缓冲区的内容并且赋值给$info
$file=fopen(\'info.txt\',\'w\'); //打开文件info.txt
fwrite($file,$info); //写入信息到info.txt
fclose($file); //关闭文件info.txt
?>
用以上的方法,就可以把不同用户的phpinfo信息保存下来,这在以前恐怕没有办法办到!其实上面就是将一些"过程"转化为"函数"的方法!
或许有人会问:"难道就这个样子吗?还有没有其他用途?"当然有了,比如笔者论坛的PHP 语法加亮显示就和这个有关(PHP默认的语法加亮显示函数会直接输出,不能保存结果,如果在每次调用都显示恐怕会很浪费CPU,笔者的论坛就把语法加亮函数显示的结果用控制缓冲区的方法保留了),大家如果感兴趣的话可以来看看http://www.zphp.com/bbs/!
可能现在大家对ob_start()的功能有了一定的了解,上面的一个例子看似简单,但实际上已经掌握了使用ob_start()的要点。
<1>.使用ob_start打开browser的cache,这样可以保证cache的内容在你调用flush(),ob_end_flush()(或程序执行完毕)之前不会被输出。
< 2>.现在的你应该知道你所拥有的优势:可以在任何输出内容后面使用header,setcookie以及session,这是ob_start一个很大的特点;也可以使用ob_start的参数,在cache被写入后,然后自动运行命令,比如ob_start(\"ob_gzhandler\ ");而我们最常用的做法是用ob_get_contents()得到cache中的内容,然后再进行处理……
<3>.当处理完毕后,我们可以使用各种方法输出,flush(),ob_end_flush(),以及等到程序执行完毕后的自动输出。当然,如果你用的是ob_get_contents(),那么就要你自己控制输出方式了。
来,让我们看看能用ob系列函数做些什么……
一、 静态模版技术
简介:所谓静态模版技术就是通过某种方式,使得用户在client端得到的是由PHP产生的html页面。如果这个html页面不会再被更新,那么当另外的用户再次浏览此页面时,程序将不会再调用PHP以及相关的数据库,对于某些信息量比较大的网站,例如sina,163,sohu。类似这种的技术带来的好处是非常巨大的。
我所知道的实现静态输出的有两种办法:
<1>.通过y10k修改的phplib的一个叫template.inc.php类实现。
<2>.使用ob系列函数实现。
对于第一种方法,因为不是这篇文章所要研究的问题,所以不再赘述。
我们现在来看一看第二种方法的具体实现:
Example 4.
CODE<?php
ob_start();//打开缓冲区
?>
php页面的全部输出
<?
$content = ob_get_contents();//取得php页面输出的全部内容
$fp = fopen("output00001.html", "w"); //创建一个文件,并打开,准备写入
fwrite($fp, $content); //把php页面的内容全部写入output00001.html,然后……
fclose($fp);
?>
这样,所谓的静态模版就很容易的被实现了……
二、 捕捉输出
以上的Example 4.是一种最简单的情况,你还可以在写入前对$content进行操作……
你可以设法捕捉一些关键字,然后去对它进行再处理,比如Example 3.所述的PHP语法高亮显示。个人认为,这个功能是此函数最大的精华所在,它可以解决各种各样的问题,但需要你有足够的想象力……
Example 5.
CODE<?
Function run_code($code) {
If($code) {
ob_start();
eval($code);
$contents = ob_get_contents();
ob_end_clean();
}else {
echo "错误!没有输出";
exit();
}
return $contents;
}
以上这个例子的用途不是很大,不过很典型$code的本身就是一个含有变量的输出页面,而这个例子用eval把$code中的变量替换,然后对输出结果再进行输出捕捉,再一次的进行处理……
Example 6. 加快传输
CODE<?
/*
** Title.........: PHP4 HTTP Compression Speeds up the Web
** Version.......: 1.20
** Author........: catoc <catoc@163.net>
** Filename......: gzdoc.php
** Last changed..: 18/10/2000
** Requirments...: PHP4 >= 4.0.1
** PHP was configured with --with-zlib[=DIR]
** Notes.........: Dynamic Content Acceleration compresses
** the data transmission data on the fly
** code by sun jin hu (catoc) <catoc@163.net>
** Most newer browsers since 1998/1999 have
** been equipped to support the HTTP 1.1
** standard known as \"content-encoding.\"
** Essentially the browser indicates to the
** server that it can accept \"content encoding\"
** and if the server is capable it will then
** compress the data and transmit it. The
** browser decompresses it and then renders
** the page.
**
** Modified by John Lim (jlim@natsoft.com.my)
** based on ideas by Sandy McArthur, Jr
** Usage........:
** No space before the beginning of the first \'<?\' tag.
** ------------Start of file----------
** |<?
** | include(\'gzdoc.php\');
** |? >
** |<HTML>
** |... the page ...
** |</HTML>
** |<?
** | gzdocout();
** |? >
** -------------End of file-----------
*/
ob_start();
ob_implicit_flush(0);
function CheckCanGzip(){
global $HTTP_ACCEPT_ENCODING;
if (headers_sent() || connection_timeout() || connection_aborted()){
return 0;
}
if (strpos($HTTP_ACCEPT_ENCODING, \'x-gzip\') !== false) return \"x-gzip\";
if (strpos($HTTP_ACCEPT_ENCODING,\'gzip\') !== false) return \"gzip\";
return 0;
}
/* $level = compression level 0-9, 0=none, 9=max */
function GzDocOut($level=1,$debug=0){
$ENCODING = CheckCanGzip();
if ($ENCODING){
print \"n<!-- Use compress $ENCODING -->n\";
$Contents = ob_get_contents();
ob_end_clean();
if ($debug){
$s = \"<p>Not compress length: \".strlen($Contents);
$s .= \"
Compressed length: \".strlen(gzcompress($Contents,$level));
$Contents .= $s;
}
header(\"Content-Encoding: $ENCODING\");
print \"x1fx8bx08x00x00x00x00x00\";
$Size = strlen($Contents);
$Crc = crc32($Contents);
$Contents = gzcompress($Contents,$level);
$Contents = substr($Contents, 0, strlen($Contents) - 4);
print $Contents;
print pack(\'V\',$Crc);
print pack(\'V\',$Size);
exit;
}else{
ob_end_flush();
exit;
}
}
?>
这是catoc的一段很早以前的代码,是在weblogs.com看到的,他利用了zlib的函数,对传输的内容进行了压缩,测试表明,对于10k以上的页面,会产生效果,而且页面越大,效果越明显…
Output Control 函数可以让你自由控制脚本中数据的输出。它非常地有用,特别是对于:当你想在数据已经输出后,再输出文件头的情况。输出控制函数不对使用 header() 或 setcookie(), 发送的文件头信息产生影响,只对那些类似于 echo() 和 PHP 代码的数据块有作用。
我们先举一个简单的例子,让大家对Output Control有一个大致的印象:
Example 1.
所有对header()函数有了解的人都知道,这个函数会发送一段文件头给浏览器,但是如果在使用这个函数之前已经有了任何输出(包括空输出,比如空格,回车和换行)就会提示出错。如果我们去掉第一行的ob_start(),再执行此程序,我们会发现得到了一条错误提示:"Header had all ready send by"!但是加上ob_start,就不会提示出错,原因是当打开了缓冲区,echo后面的字符不会输出到浏览器,而是保留在服务器,直到你使用 flush或者ob_end_flush才会输出,所以并不会有任何文件头输出的错误!
一、 相关函数简介:
1、Flush:刷新缓冲区的内容,输出。
函数格式:flush()
说明:这个函数经常使用,效率很高。
2、ob_start :打开输出缓冲区
函数格式:void ob_start(void)
说明:当缓冲区激活时,所有来自PHP程序的非文件头信息均不会发送,而是保存在内部缓冲区。为了输出缓冲区的内容,可以使用ob_end_flush()或flush()输出缓冲区的内容。
3 、ob_get_contents :返回内部缓冲区的内容。
使用方法:string ob_get_contents(void)
说明:这个函数会返回当前缓冲区中的内容,如果输出缓冲区没有激活,则返回 FALSE 。
4、ob_get_length:返回内部缓冲区的长度。
使用方法:int ob_get_length(void)
说明:这个函数会返回当前缓冲区中的长度;和ob_get_contents一样,如果输出缓冲区没有激活。则返回 FALSE。
5、ob_end_flush :发送内部缓冲区的内容到浏览器,并且关闭输出缓冲区。
使用方法:void ob_end_flush(void)
说明:这个函数发送输出缓冲区的内容(如果有的话)。
6、ob_end_clean:删除内部缓冲区的内容,并且关闭内部缓冲区
使用方法:void ob_end_clean(void)
说明:这个函数不会输出内部缓冲区的内容而是把它删除!
7、ob_implicit_flush:打开或关闭绝对刷新
使用方法:void ob_implicit_flush ([int flag])
说明:使用过Perl的人都知道$|=x的意义,这个字符串可以打开/关闭缓冲区,而ob_implicit_flush函数也和那个一样,默认为关闭缓冲区,打开绝对输出后,每个脚本输出都直接发送到浏览器,不再需要调用 flush()
二、深入了解:
1. 关于Flush函数:
这个函数在PHP3中就出现了,是一个效率很高的函数,他有一个非常有用的功能就是刷新browser的cache.我们举一个运行效果非常明显的例子来说明flush.
Example 2.
CODE<?php
for($i = 1; $i <= 300; $i++ ) print(" ");
// 这一句话非常关键,cache的结构使得它的内容只有达到一定的大小才能从浏览器里输出
// 换言之,如果cache的内容不达到一定的大小,它是不会在程序执行完毕前输出的。经
// 过测试,我发现这个大小的底限是256个字符长。这意味着cache以后接收的内容都会
// 源源不断的被发送出去。
For($j = 1; $j <= 20; $j++) {
echo $j."
";
flush(); //这一部会使cache新增的内容被挤出去,显示到浏览器上
sleep(1); //让程序"睡"一秒钟,会让你把效果看得更清楚
}
?>
具体效果你可以到这里看看http://www.php2000.com/~uchinaboy/out.php
PHP2000的最新的PHP聊天室就是用的这个技术,可惜的是源代码未公开 L
注:如果在程序的首部加入ob_implicit_flush()打开绝对刷新,就可以在程序中不再使用flush(),这样做的好处是:提高效率!
2. 关于ob系列函数:
我想先引用我的好朋友y10k的一个例子:
Example 3.
比如你用得到服务器和客户端的设置信息,但是这个信息会因为客户端的不同而不同,如果想要保存phpinfo()函数的输出怎么办呢?在没有缓冲区控制之前,可以说一点办法也没有,但是有了缓冲区的控制,我们可以轻松的解决:
CODE<?php
ob_start(); //打开缓冲区
phpinfo(); //使用phpinfo函数
$info=ob_get_contents(); //得到缓冲区的内容并且赋值给$info
$file=fopen(\'info.txt\',\'w\'); //打开文件info.txt
fwrite($file,$info); //写入信息到info.txt
fclose($file); //关闭文件info.txt
?>
用以上的方法,就可以把不同用户的phpinfo信息保存下来,这在以前恐怕没有办法办到!其实上面就是将一些"过程"转化为"函数"的方法!
或许有人会问:"难道就这个样子吗?还有没有其他用途?"当然有了,比如笔者论坛的PHP 语法加亮显示就和这个有关(PHP默认的语法加亮显示函数会直接输出,不能保存结果,如果在每次调用都显示恐怕会很浪费CPU,笔者的论坛就把语法加亮函数显示的结果用控制缓冲区的方法保留了),大家如果感兴趣的话可以来看看http://www.zphp.com/bbs/!
可能现在大家对ob_start()的功能有了一定的了解,上面的一个例子看似简单,但实际上已经掌握了使用ob_start()的要点。
<1>.使用ob_start打开browser的cache,这样可以保证cache的内容在你调用flush(),ob_end_flush()(或程序执行完毕)之前不会被输出。
< 2>.现在的你应该知道你所拥有的优势:可以在任何输出内容后面使用header,setcookie以及session,这是ob_start一个很大的特点;也可以使用ob_start的参数,在cache被写入后,然后自动运行命令,比如ob_start(\"ob_gzhandler\ ");而我们最常用的做法是用ob_get_contents()得到cache中的内容,然后再进行处理……
<3>.当处理完毕后,我们可以使用各种方法输出,flush(),ob_end_flush(),以及等到程序执行完毕后的自动输出。当然,如果你用的是ob_get_contents(),那么就要你自己控制输出方式了。
来,让我们看看能用ob系列函数做些什么……
一、 静态模版技术
简介:所谓静态模版技术就是通过某种方式,使得用户在client端得到的是由PHP产生的html页面。如果这个html页面不会再被更新,那么当另外的用户再次浏览此页面时,程序将不会再调用PHP以及相关的数据库,对于某些信息量比较大的网站,例如sina,163,sohu。类似这种的技术带来的好处是非常巨大的。
我所知道的实现静态输出的有两种办法:
<1>.通过y10k修改的phplib的一个叫template.inc.php类实现。
<2>.使用ob系列函数实现。
对于第一种方法,因为不是这篇文章所要研究的问题,所以不再赘述。
我们现在来看一看第二种方法的具体实现:
Example 4.
CODE<?php
ob_start();//打开缓冲区
?>
php页面的全部输出
<?
$content = ob_get_contents();//取得php页面输出的全部内容
$fp = fopen("output00001.html", "w"); //创建一个文件,并打开,准备写入
fwrite($fp, $content); //把php页面的内容全部写入output00001.html,然后……
fclose($fp);
?>
这样,所谓的静态模版就很容易的被实现了……
二、 捕捉输出
以上的Example 4.是一种最简单的情况,你还可以在写入前对$content进行操作……
你可以设法捕捉一些关键字,然后去对它进行再处理,比如Example 3.所述的PHP语法高亮显示。个人认为,这个功能是此函数最大的精华所在,它可以解决各种各样的问题,但需要你有足够的想象力……
Example 5.
CODE<?
Function run_code($code) {
If($code) {
ob_start();
eval($code);
$contents = ob_get_contents();
ob_end_clean();
}else {
echo "错误!没有输出";
exit();
}
return $contents;
}
以上这个例子的用途不是很大,不过很典型$code的本身就是一个含有变量的输出页面,而这个例子用eval把$code中的变量替换,然后对输出结果再进行输出捕捉,再一次的进行处理……
Example 6. 加快传输
CODE<?
/*
** Title.........: PHP4 HTTP Compression Speeds up the Web
** Version.......: 1.20
** Author........: catoc <catoc@163.net>
** Filename......: gzdoc.php
** Last changed..: 18/10/2000
** Requirments...: PHP4 >= 4.0.1
** PHP was configured with --with-zlib[=DIR]
** Notes.........: Dynamic Content Acceleration compresses
** the data transmission data on the fly
** code by sun jin hu (catoc) <catoc@163.net>
** Most newer browsers since 1998/1999 have
** been equipped to support the HTTP 1.1
** standard known as \"content-encoding.\"
** Essentially the browser indicates to the
** server that it can accept \"content encoding\"
** and if the server is capable it will then
** compress the data and transmit it. The
** browser decompresses it and then renders
** the page.
**
** Modified by John Lim (jlim@natsoft.com.my)
** based on ideas by Sandy McArthur, Jr
** Usage........:
** No space before the beginning of the first \'<?\' tag.
** ------------Start of file----------
** |<?
** | include(\'gzdoc.php\');
** |? >
** |<HTML>
** |... the page ...
** |</HTML>
** |<?
** | gzdocout();
** |? >
** -------------End of file-----------
*/
ob_start();
ob_implicit_flush(0);
function CheckCanGzip(){
global $HTTP_ACCEPT_ENCODING;
if (headers_sent() || connection_timeout() || connection_aborted()){
return 0;
}
if (strpos($HTTP_ACCEPT_ENCODING, \'x-gzip\') !== false) return \"x-gzip\";
if (strpos($HTTP_ACCEPT_ENCODING,\'gzip\') !== false) return \"gzip\";
return 0;
}
/* $level = compression level 0-9, 0=none, 9=max */
function GzDocOut($level=1,$debug=0){
$ENCODING = CheckCanGzip();
if ($ENCODING){
print \"n<!-- Use compress $ENCODING -->n\";
$Contents = ob_get_contents();
ob_end_clean();
if ($debug){
$s = \"<p>Not compress length: \".strlen($Contents);
$s .= \"
Compressed length: \".strlen(gzcompress($Contents,$level));
$Contents .= $s;
}
header(\"Content-Encoding: $ENCODING\");
print \"x1fx8bx08x00x00x00x00x00\";
$Size = strlen($Contents);
$Crc = crc32($Contents);
$Contents = gzcompress($Contents,$level);
$Contents = substr($Contents, 0, strlen($Contents) - 4);
print $Contents;
print pack(\'V\',$Crc);
print pack(\'V\',$Size);
exit;
}else{
ob_end_flush();
exit;
}
}
?>
这是catoc的一段很早以前的代码,是在weblogs.com看到的,他利用了zlib的函数,对传输的内容进行了压缩,测试表明,对于10k以上的页面,会产生效果,而且页面越大,效果越明显…