月度归档:2012 年五月

用C#动态创建Access数据库[转]

记得以前要动态的创建Access数据库的mdb文件都是采用DAO,用VC开发,一大堆的API,很是麻烦。现在好像也鲜有人提起DAO。其实动态的创建mdb数据的最简单的方法还是ADOX。
用ADOX创建access数据库方法很简单,只需要new一个Catalog对象,然后调用它的Create方法就可以了,如下:
ADOX.Catalog catalog = new Catalog();
catalog.Create(“Provider=Microsoft.Jet.OLEDB.4.0;Data Source=d:\\test.mdb;Jet OLEDB:Engine Type=5″);

仅仅两行代码就搞定了。下来我主要介绍一下在c#中的实现细节。首先你要添加引用,在“Add reference”对话框里切换到Com页面,选择“Microsoft ADO Ext. 2.8 for DDL and Security”,然后点击OK。在文件的开头using ADOX名字空间。然后添加如上面所示的代码就可以成功的创建Access 数据库了,代码如下:
[csharp]
using System;
using System.Collections.Generic;
using System.Text;
using ADOX;

namespace testADOX
{
class Program
{
static void Main(string[] args)
{
ADOX.Catalog catalog = new Catalog();
catalog.Create("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=d:\\test.mdb;Jet OLEDB:Engine Type=5");
}
}
}
[/csharp]

创建了数据库文件是没有实际用处的,我们还要创建表。在创建表之前,我们必须连接目标数据库,用来连接数据的桥梁居然是ADO的Connection对象,所以我们不得不再次添加对ADO的应用,在添加引用对话框中切换到Com页面,选择“Microsoft ActiveX Data Objects 2.8 Library”,然后点击OK。下边是创建表的完整代码:
[csharp]
using System;
using System.Collections.Generic;
using System.Text;
using ADOX;

namespace testADOX
{
class Program
{
static void Main(string[] args)
{
ADOX.Catalog catalog = new Catalog();
catalog.Create("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=d:\\test.mdb;Jet OLEDB:Engine Type=5");

ADODB.Connection cn = new ADODB.Connection();

cn.Open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=d:\\test.mdb", null, null, -1);
catalog.ActiveConnection = cn;

ADOX.Table table = new ADOX.Table();
table.Name = "FirstTable";

ADOX.Column column = new ADOX.Column();
column.ParentCatalog = catalog;
column.Name = "RecordId";
column.Type = DataTypeEnum.adInteger;
column.DefinedSize = 9;
column.Properties["AutoIncrement"].Value = true;
table.Columns.Append(column, DataTypeEnum.adInteger, 9);
table.Keys.Append("FirstTablePrimaryKey", KeyTypeEnum.adKeyPrimary, column, null, null);
table.Columns.Append("CustomerName", DataTypeEnum.adVarWChar, 50);
table.Columns.Append("Age", DataTypeEnum.adInteger, 9);
table.Columns.Append("Birthday", DataTypeEnum.adDate, 0);
catalog.Tables.Append(table);

cn.Close();
}
}
}
[/csharp]
上面的代码中,创建了一个名为FirstTable的表,在表里加入了4个字段,并设置了一个主键。表里的字段分别输入4中不同的常用类型,第一个字段是一个自动增长的整数类型,这个类型比较特殊,你必须为这个字段设置ParentCatalog属性,并将“AutoIncrement”的属性值设为true.。Access里的Text类型对应的就是adVarWchar,而日期类型对应的是adDate。
键的设置如table.Keys.Append(“FirstTablePrimaryKey”, KeyTypeEnum.adKeyPrimary, column, null, null)所示,如果是外键的话,你还必须要设置关联的表和关联的字段,也就是Append方法的后两个字段。
你也可以参照上边的代码创建索引和视图。
转自:http://www.cnblogs.com/guanjinke/archive/2006/11/30/577241.html

MySQL行锁深入研究[转]

  做项目时由于业务逻辑的需要,必须对数据表的一行或多行加入行锁,举个最简单的例子,图书借阅系统。假设 id=1 的这本书库存为 1 ,但是有 2 个人同时来借这本书,此处的逻辑为
  view plaincopy to clipboardprint?
  Select restnum from book where id =1 ;
  – 如果 restnum 大于 0 ,执行 update
  Update book set restnum=restnum-1 where id=1 ;
  问题就来了,当 2 个人同时来借的时候,有可能第一个人执行 select 语句的时候,第二个人插了进来,在第一个人没来得及更新 book 表的时候,第二个人查到数据了,其实是脏数据,因为第一个人会把 restnum 值减 1 ,因此第二个人本来应该是查到 id=1 的书 restnum 为 0 了,因此不会执行 update ,而会告诉它 id=1 的书没有库存 了,可是数据库哪懂这些,数据库只负责执行一条条 SQL 语句,它才不管中间有没有其他 sql 语句插进来,它也不知道要把一个 session 的 sql 语句执行完再执行另一个 session 的。因此会导致并发的时候 restnum 最后的结果为 -1 ,显然这是不合理的,所以,才出现锁的概念, Mysql 使用 innodb 引擎可以通过索引 对数据行加锁。以上借书的语句变为:
  view plaincopy to clipboardprint?
  Begin;
  Select restnum from book where id =1 for update ;
  – 给 id=1 的行加上排它锁且 id 有索引
  Update book set restnum=restnum-1 where id=1 ;
  Commit;
  这样,第二个人执行到 select 语句的时候就会处于等待状态直到第一个人执行 commit 。从而保证了第二个人不会读到第一个人修改前的数据。
  那这样是不是万无一失了呢,答案是否定的。看下面的例子。
  跟我一步一步来,先建立表
  view plaincopy to clipboardprint?
  CREATE TABLE `book` (
  `id` int(11) NOT NULL auto_increment,
  `num` int(11) default NULL,
  `name` varchar(0) default NULL,
  PRIMARY KEY (`id`),
  KEY `asd` (`num`)
  ) ENGINE=InnoDB DEFAULT CHARSET=gbk
  其中 num 字段加了索引
  然后插入数据,运行,
  view plaincopy to clipboardprint?
  insert into book(num) values(11),(11),(11),(11),(11);
  insert into book(num) values(22),(22),(22),(22),(22);
  然后打开 2 个 mysql 控制台窗口,其实就是建立 2 个 session 做并发操作
  ********************************************************************
  在第一个 session 里运行:
  begin;
  select * from book where num=11 for update;
  出现结果:
  +—-+—–+——+
  | id | num | name |
  +—-+—–+——+
  | 11 | 11 | NULL |
  | 12 | 11 | NULL |
  | 13 | 11 | NULL |
  | 14 | 11 | NULL |
  | 15 | 11 | NULL |
  +—-+—–+——+
  5 rows in set
  然后在第二个 session 里运行:
  begin;
  select * from book where num=22 for update;
  出现结果:
  +—-+—–+——+
  | id | num | name |
  +—-+—–+——+
  | 16 | 22 | NULL |
  | 17 | 22 | NULL |
  | 18 | 22 | NULL |
  | 19 | 22 | NULL |
  | 20 | 22 | NULL |
  +—-+—–+——+
  5 rows in set
  好了,到这里什么问题都没有,是吧,可是接下来问题就来了,大家请看:
  回到第一个 session ,运行:
  update book set name=’abc’ where num=11;
  ********************************************************************************************
  问题来了, session 竟然处于等待状态 ,可是 num=11 的行不是被第一个 session 自己锁住的么,为什么不能更新呢?好了,打这里大家也许有自己的答案,先别急,再请看一下操作。
  把 2 个 session 都关闭,然后运行:
  view plaincopy to clipboardprint?
  delete from book where num=11 limit 3;
  delete from book where num=22 limit 3;
  其实就是把 num=11 和 22 的记录各删去 3 行,
  然后重复 “***********************” 之间的操作
  竟然发现,运行 update book set name=’abc’ where num=11; 后,有结果出现了,说明没有被锁住,
  这是为什么呢,难道 2 行数据和 5 行数据,对 MySQL 来说,会产生锁行和锁表两种情况吗 。经过跟网友讨论和翻阅资料,仔细分析后发现:
  在以上实验数据作为测试数据的情况下,由于 num 字段重复率太高,只有 2 个值,分别是 11 和 12. 而数据量相对于这两个值来说却是比较大的,是 10 条, 5 倍的关系。
  那么 mysql 在解释 sql 的时候,会忽略索引,因为它的优化器发现:即使使用了索引,还是要做全表扫描,故而放弃了索引,也就没有使用行锁,却使用了表锁。 简单的讲,就是 MYSQL 无视了你的索引,它觉得与其行锁,还不如直接表锁,毕竟它觉得表锁所花的代价比行锁来的小。以上问题即便你使用了 force index 强制索引,结果还是一样,永远都是表锁。
  所以 mysql 的行锁用起来并不是那么随心所欲的,必须要考虑索引。再看下面的例子。
  view plaincopy to clipboardprint?
  select id from items where id in (select id from items where id <6) for update;
  –id字段加了索引
  select id from items where id in (1,2,3,4,5) for update;
  大部分会认为结果一样没什么区别,其实差别大了,区别就是第一条 sql 语句会产生表锁,而第二个 sql 语句是行锁,为什么呢?因为第一个 sql 语句用了子查询外围查询故而没使用索引,导致表锁。
  好了,回到借书的例子,由于 id 是唯一的,所以没什么问题,但是如果有些表出现了索引有重复值,并且 mysql 会强制使用表锁的情况,那怎么办呢?一般来说只有重新设计表结构和用新的 SQL 语句实现业务逻辑,但是其实上面借书的例子还有一种办法。请看下面代码:
  view plaincopy to clipboardprint?
  Set sql_mode=
  ’STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION’;
  Begin;
  Select restnum from book where id =1 ; — 取消排它锁 , 设置 restnum 为 unsigned
  Update book set restnum=restnum-1 where id=1 ;
  If(update 执行成功 ) commit;
  Else rollback;
  上面是个小技巧,通过把数据库模式临时设置为严格模式,当 restnum 被更新为 -1 的时候,由于 restnum 是 unsigned 类型的,因此 update 会执行失败,无论第二个 session 做了什么数据库操作,都会被回滚,从而确保了数据的正确性,这个目的只是为了防止并发的时候极小概率出现的 2 个 session 的 sql 语句嵌套执行导致数据脏读。当然最好的办法还是修改表结构和 sql 语句,让 MYSQL 通过索引来加行锁, MySQL 测试版本为 5.0.75-log 和 5.1.36-community
原文出处:http://www.cnblogs.com/Robin2005/archive/2010/02/27/1674691.html

df和du看到的总数不一样

今天发现磁盘用完了,查看一下应该是mysql给用完了,删除了一些大备份表后用df -lh查看并没有释放多少空间,但用du -sh看到数据目录占用的空间很少。
后来查了一下发现是由于删除的时候没有停止mysql服务。

上传下载大点的数据文件,WCF用默认配置不能正常的序列化和反序列化[转]

今天遇到两个问题,一个主要问题,一个次要问题。

主要问题:上传下载大点的数据文件,WCF用默认配置不能正常的序列化和反序列化。

运行WCF,上传13K的XML数据出错。错误如下:

格式化程序尝试对消息反序列化时引发异常,对操作”SetFigureData”的请求消息正文进行反序列化时出现错误。读取XML数据时,超出最大字符串内容长度配额(8192)。通过更改在创建XML读取器时所使用的XmlDictionaryReaderQuotas对象的MaxStringContentLenght属性,可增加此配额。第156行,位置为48。

解决办法,有位园友写到了,可以参考如下:

http://www.cnblogs.com/upzone/archive/2009/01/20/1378655.html

大致思路:上传不行,就看服务器端的App.config;下载不行,就看客户端的App.config。我没从这出发,我在做上传的时候,老拘泥于客户端的App.config文件,其实早配对了,还是报错,出错原因是在服务器端的App.config中,没配置,就是用缺省的设置了。当然,网上还有个人,说去改machine.config文件,更是小题大作,把问题想远了。我们都知道machine.config是根,不应该随便动的,应该专事专办。

我再补充下,WCF生成的文件App.config文件,是不包含bindings节点的。(就为这个,浪费我40分钟时间,我把下面两部分没当成在一个文件里,但是切记它们实际是在一个文件里。)








name="DomainWS.DomainServiceV2">







次要问题:

在解决上述问题的时候,引入的另一个问题,尝试按MSDN博客上一个人的方法,修改客户端的App.config,结果客户端的Binding方式变了,从wsHttpBinding改为basicHttpBinding,却忘了改服务器的Binding方式,还是用的wsHttpBinding。当然对不上号了,一运行如下错误出现:

服务 http: 不支持内容类型 text/xml; charset=utf-8。客户端和服务绑定可能不匹配。

按关键字一搜,就找到类似问题了。不过那个楼主在看到真正的答案的时候,好像也没意识到。哎,可惜了。

总结来说,分析问题的能力很重要,老外管它叫“Trouble Shooting Ability”。

http://blog.csdn.net/sam1012/article/details/6265472

解决sphinx编译出错:undefined reference to `libiconv’

编译安装sphinx出错undefined reference to `libiconv’

编译shhinx出现如下错误:

libsphinx.a(sphinx.o): In function `xmlUnknownEncoding’:
/data/src/sphinx-0.9.8-rc2/src/sphinx.cpp:17161: undefined reference to `libiconv_open’
/data/src/sphinx-0.9.8-rc2/src/sphinx.cpp:17179: undefined reference to `libiconv’
/data/src/sphinx-0.9.8-rc2/src/sphinx.cpp:17185: undefined reference to `libiconv_close’
libsphinx.a(tokenizer_zhcn.o): In function `CSphTokenizer_zh_CN_GBK::SetBuffer(unsigned char*, int)’:
/data/src/sphinx-0.9.8-rc2/src/tokenizer_zhcn.cpp:280: undefined reference to `libiconv’
libsphinx.a(tokenizer_zhcn.o): In function `CSphTokenizer_zh_CN_UTF8_Private::GetConverter(char const*, char const*)’:
/data/src/sphinx-0.9.8-rc2/src/tokenizer_zhcn.cpp:55: undefined reference to `libiconv_open’
/data/src/sphinx-0.9.8-rc2/src/tokenizer_zhcn.cpp:58: undefined reference to `libiconv’
libsphinx.a(tokenizer_zhcn.o): In function `~CSphTokenizer_zh_CN_UTF8_Private’:
/data/src/sphinx-0.9.8-rc2/src/tokenizer_zhcn.cpp:34: undefined reference to `libiconv_close’
/data/src/sphinx-0.9.8-rc2/src/tokenizer_zhcn.cpp:34: undefined reference to `libiconv_close’
/data/src/sphinx-0.9.8-rc2/src/tokenizer_zhcn.cpp:34: undefined reference to `libiconv_close’
collect2: ld 返回 1
make[2]: *** [indexer] 错误 1
make[2]: Leaving directory `/data/src/sphinx-0.9.8-rc2/src’
make[1]: *** [all] 错误 2
make[1]: Leaving directory `/data/src/sphinx-0.9.8-rc2/src’
make: *** [all-recursive] 错误 1

修改sphinx-0.9.8-rc2/src/Makefile,


LIBS = -lm -lexpat -L/usr/local/lib
改成
LIBS = -lm -lexpat -liconv -L/usr/local/lib

重新编译即可。

PHP高保真图片缩放处理

在一些有较多图片的网站,为了加速响应和优化储存,上传图片时一般会做图片大小格式化的处理 .
在PHP中有两种处理方法,一种是用 gd2 ,一种是用 imagick , 这两种方法都要求打开相应的扩展模块.
具体实现如下:

1.gb2
/**
* 图片大小的格式化,使之成为固定大小的文件图片
* @param string $srcImage 原图片的路径信息
* @param int $width 指定图片格式化后的宽度(图片高度按照宽度缩放比率,自适应)
* @param string $fileDir 生成的文件的存放目录 如 /test/images/
* @return bool
*/
public function imageSizeFormate($srcImage,$width,$fileDir)
{
// 获得原图片尺寸
$srcSize = getimagesize($srcImage);
/* 对于超出大小或尺寸限制的文件进行缩放处理 */
if ($srcSize[0] > $width)
{
/* 按照图片宽度,计算等比例缩放的图片高度*/
$height = ($width/$srcSize[0])*$srcSize[1];
/* 创建真彩色的临时文件,指定大小 */
$tmpImage = imagecreatetruecolor($width,$height);
// 原图片的资源
$srcImageSource = imagecreatefromjpeg($srcImage);
// 重新采样拷贝图像并调整大小
imagecopyresampled($tmpImage,$srcImageSource,0,0,0,0,
$width,$height,$srcSize[0],$srcSize[1]);
/* 生成 JPEG 格式的新文件,存放在test目录下 */
// 以时间戳作为文件名
$fileName = mktime();
$dstPath = realpath(“.”).$fileDir.$fileName.”.jpg”;
if( imagejpeg($tmpImage,$dstPath) )
{
/* 最后删除原文件 */
return unlink($srcImage);
}
return false;
}
}

2.imagick
/**
* 图片大小的格式化,
* @param string $srcImage 原图片的路径信息
* @param int $width 指定图片格式化后的宽度(图片高度按照宽度缩放比率,自适应)
* @param string $fileDir 缩放后的文件存放路径
* @param string $type 图片格式化类型,默认为 jpg 格式
* @param string $bestFit 是否强制调整大小以获取最佳效果
* @return bool
*/
public function imageSizeFormate($srcImage,$width,$fileDir,$type =’jpg’,$bestFit=true)
{
// 获得原图片尺寸
$srcSize = getimagesize($srcImage);
/* 对于超出大小或尺寸限制的文件进行缩放处理 */
if($srcSize[0] > $width)
{
//图片的自适应宽度
$height = ($width/$srcSize[0])*$srcSize[1];
$imageick = new Imagick ($srcImage);
/* 缩略图大小设置 */
$imageick->thumbnailImage($width,$height,$bestFit);
/* 缩略图的格式化类型 */
$imageick->setImageFormat ($type);
// 用时间戳作为生成文件的文件名
$fileName = mktime();
$file = realpath(“.”).$fileDir.$fileName.”.”.$type;
//生成图片
if( $imagick->writeImage($file) )
{
//删除原来的图片
return unlink($srcImage);
}
return false;
}
}

CentOS 5.5 编译安装mysql 5.5.18[转]

利用CentOS Linux系统自带的yum命令安装、升级所需的程序库(RedHat等其他Linux发行版可从安装光盘中找到这些程序库的RPM包,进行安装):

sudo -s
LANG=C
yum -y install gcc gcc-c++ autoconf libjpeg libjpeg-devel libpng libpng-devel \
freetype freetype-devel libxml2 libxml2-devel zlib zlib-devel glibc glibc-devel \
glib2 glib2-devel bzip2 bzip2-devel ncurses ncurses-devel \
curl curl-devel e2fsprogs e2fsprogs-devel krb5 krb5-devel \
libidn libidn-devel openssl openssl-devel \
openldap openldap-devel nss_ldap \
openldap-clients openldap-servers

#先下载cmake

wget http://www.cmake.org/files/v2.8/cmake-2.8.4.tar.gz

#安装cmake
tar xvzf cmake-2.8.4.tar.gz
./configure
make
make install

#创建mysql用户名及组
/usr/sbin/groupadd mysql
/usr/sbin/useradd -g mysql mysql
#下载最新的mysql
wget ftp://mirror.switch.ch/mirror/mysql/Downloads/MySQL-5.5/mysql-5.5.18.tar.gz
#解压
tar zxvf mysql-5.5.18.tar.gz
cd mysql-5.5.18
#开始编译并安装

/usr/local/bin/cmake
-DCMAKE_INSTALL_PREFIX=/usr/local/webserver/mysql \
-DMYSQL_UNIX_ADDR=/tmp/mysql.sock \
-DDEFAULT_CHARSET=utf8 \
-DDEFAULT_COLLATION=utf8_general_ci \
-DWITH_EXTRA_CHARSETS:STRING=utf8,gbk,gb2312 \
-DWITH_MYISAM_STORAGE_ENGINE=1 \
-DWITH_INNOBASE_STORAGE_ENGINE=1 \
-DWITH_MEMORY_STORAGE_ENGINE=1 \
-DWITH_READLINE=1 \
-DENABLED_LOCAL_INFILE=1 \
-DMYSQL_DATADIR=/var/mysql/data \
-DMYSQL_USER=mysql -DWITH_DEBUG=0 \

make && make install
chmod +w /usr/local/webserver/mysql
chown -R mysql:mysql /usr/local/webserver/mysql
cp support-files/my-small.cnf /etc/my.cnf
chown mysql:mysql /etc/my.cnf
cp mysql.server /etc/rc.d/init.d/mysqld

执行下面的
/usr/local/webserver/mysql/scripts/mysql_install_db \
–user=mysql \
–basedir=/usr/local/webserver/mysql \
–datadir=/var/mysql/data

vi /etc/init.d/mysqld
#编辑此文件,查找并修改以下变量内容:
basedir=/usr/local/mysql
datadir=/var/mysql/data

chkconfig –add mysqld
chkconfig –level 345 mysqld on

在/etc/my.cnf 打开下面的InnoDB配置以减少内存即可:
default-storage-engine=MyISAM
server-id = 1
innodb_buffer_pool_size = 21M
innodb_additional_mem_pool_size = 2M
innodb_log_file_size = 5M
innodb_log_buffer_size = 8M
innodb_flush_log_at_trx_commit = 1
innodb_lock_wait_timeout = 50

启动:
service mysqld start
#修改密码
/usr/local/webserver/mysql/bin/mysqladmin -u root password newpassword

转自:http://www.cnblogs.com/fangbo/archive/2011/04/01/2002637.html

PHP生成静态HTML页面-PHP ob_start()生成html[转]

Output Control 函数可以让你自由控制脚本中数据的输出。它非常地有用,特别是对于:当你想在数据已经输出后,再输出文件头的情况。输出控制函数不对使用 header() 或 setcookie(), 发送的文件头信息产生影响,只对那些类似于 echo() 和 PHP 代码的数据块有作用。

我们先举一个简单的例子,让大家对Output Control有一个大致的印象:
Example 1.
[php]
ob_start(); //打开缓冲区
echo "Hello\n"; //输出
header(“location:index.php”); //把浏览器重定向到index.php
ob_end_flush();//输出全部内容到浏览器
?>
[/php]

所有对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.

[php]
for($i = 1; $i <= 300; $i++ ) print(“ “);
// 这一句话非常关键,cache的结构使得它的内容只有达到一定的大小才能从浏览器里输出
// 换言之,如果cache的内容不达到一定的大小,它是不会在程序执行完毕前输出的。经
// 过测试,我发现这个大小的底限是256个字符长。这意味着cache以后接收的内容都会
// 源源不断的被发送出去。
For($j = 1; $j <= 20; $j++) {
echo $j.”
”;
flush(); //这一部会使cache新增的内容被挤出去,显示到浏览器上
sleep(1); //让程序“睡”一秒钟,会让你把效果看得更清楚
}
?>
[/php]

注:如果在程序的首部加入ob_implicit_flush()打开绝对刷新,就可以在程序中不再使用flush(),这样做的好处是:提高效率!

2. 关于ob系列函数:
我想先引用我的好朋友y10k的一个例子:
Example 3.

比如你用得到服务器和客户端的设置信息,但是这个信息会因为客户端的不同而不同,如果想要保存phpinfo()函数的输出怎么办呢?在没有缓冲区控制之前,可以说一点办法也没有,但是有了缓冲区的控制,我们可以轻松的解决:

[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
?>
[/php]

用以上的方法,就可以把不同用户的phpinfo信息保存下来,这在以前恐怕没有办法办到!其实上面就是将一些“过程”转化为“函数”的方法!

可能现在大家对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.

[php]
ob_start();//打开缓冲区
?>
[/php]
php页面的全部输出
[php]
$content = ob_get_contents();//取得php页面输出的全部内容
$fp = fopen(“output00001.html”, “w”); //创建一个文件,并打开,准备写入
fwrite($fp, $content); //把php页面的内容全部写入output00001.html,然后……
fclose($fp);
?>
[/php]

这样,所谓的静态模版就很容易的被实现了……

mod_rewrite最简单的知识(转)
2007-12-27 20:22
开启Apache 的mod_rewrite功能:
在Apahce的配置文件httpd.conf中把#LoadModule rewrite_module modules/mod_rewrite.so
前的#去掉,改为LoadModule rewrite_module modules/mod_rewrite.so
在httpd.conf中找到下面这段


Options FollowSymLinks
AllowOverride None

将AllowOverride None 改成 AllowOverride ALL

这样Apache的mod_rewrite就开启了。

简单使用mod_write。
该功能的使用:一种是将转向规则写在httpd.conf中,这样效率比较高,但缺乏灵活性;
另一种是写在.htaccess文件中,将该文件放到需要运用该重写规则的网站目录的根目录。
比如网站结构
+DocumentRoot
|—News
|—BBS
|—Blog
以上结构中我只希望在新闻模块运用mod_write则只需将.htaccess
文件放到 /News目录下,则该目录下的所有请求都会去和.htaacess中的地址重写规则匹配。.htaccess虽然灵活但确带来性能上的缺失。

重写规则样例(其中的正则表达式就不在此叙述了):
RewriteEngine On
RewriteRule ^index(.*)$ /test.php [L]
RewriteRule ^index_([0-9]+).html$ getnews.php?id=$1 [L]

第一句RewriteEngine On一定不能少,否则该文件将不起任何作用。
第二句RewriteRule表示规则开始,具体为^index(.*)$ 将对 index,cgi (cgi表示html,php,。。等)的请求让test.php来处理,但地址栏上仍然写的是 index.cgi。[L]表示该规则结束
第二句 ^index_([0-9]+).html 表示 index_(0~9的任何数字任何组合).html, 就等于可以是 index_1.html
index_94.html , index_4565.html …任何的形式
以 index_94.html 为例:
对index_94.html 的请求 将会交给 getnews.php?id=94来请求,可见 $1就代表参数([0-9]+)。

这个例子演变后可以完成大部分的请求:

RewriteRule ^news/([0-9]+)/(delete).html$ news/news_instance.php?news_id=$1&act=$2 [L]

转自:http://hi.baidu.com/sz_xiaofeng/blog/item/58973834b32d4d46251f14dc.html