jimmy's profileJDlogPhotosBlogLists Tools Help
    September 15

    恢复对运营和产品的关注

    恢复对运营和产品的关注
    jimmy | 15 九月, 2006 22:28


    很多人认为技术人员是最死板的,眼睛只是盯着自己要负责的一亩三分代码,脑子里面只有任务和如同机器码的0未完成 OR 1完成。我也收到了一些意见,对产品、对运营、对销售的关心太少了。

    自我感觉,我对于自己的状态还是比较了解的,对非技术的关注减少确实是非我情愿所致。因为长期以来,产品、运营甚至销售对技术的需求是社区最迫切解决的问题。去年底层改进后带来的PV繁荣,掩盖了PV导向匆忙改版留下的众多隐患,而技术人员被忙乱的湮没在层出不穷的新需求中。技术部门的工作困难程度和承担的工作压力其实是很多人并不了解的。所以,提高工作效率,控制技术成本,对我而言是当时最重要的任务。由过去无序的繁忙转变为现在有序的繁忙,还算是初见成效的。非常感谢组内成员的共同努力,现在终于能够有点时间考虑技术之外的东西了。

    事实上,从上个月末开始,已经逐渐为非技术部分划出更多的精力,与产品人员的交流也比以往增多了。最近两周,我坚持每天用两个小时来看社区的内容,看内容的特点,看社区的特点,看用户的行为特点,来不断更新自己已经老旧了的思路和理念,不断反思自己对用户的判断是否已经有了偏差。

    互连网的变化是非常快的,可能很多分析和经验,在半年或者一年后就已经完全不适用了。而我真正混在社区里面,真正在社区中浸淫已经是很多年以前了。当真正静下心来再去看今天的社区,确实有很多已经不同了。这段时间,对很多数据进行了分析,尤其是对页面点击,很多分析结果与我的主观判断有很大出入。比如,通常广告价格第二屏、第三屏是2:1,谈判时能把第三屏争取成第二屏也会是很成功。但是,统计的结果显示,第二屏跟第三屏并无区别。是社区的特点?还是因为版式?更新观念的同时,也会引发更多思考。

    当初为工作开这个博客的时候,特意设置了一个分类叫“触类旁通”,目的就是分析和研究更多与技术并不直接相关的东西。非常惭愧,这个分类下面现在还基本是空的。事实上,这种触类旁通的思考和学习是非常重要的,尤其是在因果不明晰情况下要作出判断的时候,借鉴或者是灵感触发的作用就会非常有意义。年底之前,计划跟踪20个网站,深入分析5个。从技术角度去看产品和模式及其运营,可能跟Donews上有很多不同。希望届时可以有更多东西跟大家分享。

    另外,在跟别人探讨的时候,谈了很多“本体价值”的想法。交流的过程中,自己对本体价值的概念也比以前明晰了很多。在以后会找时间把这个想法系统的描述出来。


    ~~呵呵~~

    参考:Iconv的编码列表

    参考:Iconv的编码列表
    jimmy | 12 九月, 2006 17:00


    European languages
    ASCII, ISO-8859-{1,2,3,4,5,7,9,10,13,14,15,16}, KOI8-R, KOI8-U, KOI8-RU, CP{1250,1251,1252,1253,1254,1257}, CP{850,866}, Mac{Roman,CentralEurope,Iceland,Croatian,Romania}, Mac{Cyrillic,Ukraine,Greek,Turkish}, Macintosh
    Semitic languages
    ISO-8859-{6,8}, CP{1255,1256}, CP862, Mac{Hebrew,Arabic}
    Japanese
    EUC-JP, SHIFT_JIS, CP932, ISO-2022-JP, ISO-2022-JP-2, ISO-2022-JP-1
    Chinese
    EUC-CN, HZ, GBK, GB18030, EUC-TW, BIG5, CP950, BIG5-HKSCS, ISO-2022-CN, ISO-2022-CN-EXT
    Korean
    EUC-KR, CP949, ISO-2022-KR, JOHAB
    Armenian
    ARMSCII-8
    Georgian
    Georgian-Academy, Georgian-PS
    Tajik
    KOI8-T
    Thai
    TIS-620, CP874, MacThai
    Laotian
    MuleLao-1, CP1133
    Vietnamese
    VISCII, TCVN, CP1258
    Platform specifics
    HP-ROMAN8, NEXTSTEP
    Full Unicode
    UTF-8
    UCS-2, UCS-2BE, UCS-2LE
    UCS-4, UCS-4BE, UCS-4LE
    UTF-16, UTF-16BE, UTF-16LE
    UTF-32, UTF-32BE, UTF-32LE
    UTF-7
    C99, JAVA
    Full Unicode, in terms of uint16_t or uint32_t (with machine dependent endianness and alignment)
    UCS-2-INTERNAL, UCS-4-INTERNAL
    Locale dependent, in terms of `char' or `wchar_t' (with machine dependent endianness and alignment, and with OS and locale dependent semantics)
    char, wchar_t
    The empty encoding name "" is equivalent to "char": it denotes the locale dependent character encoding.
    When configured with the option --enable-extra-encodings, it also provides support for a few extra encodings:
    European languages
    CP{437,737,775,852,853,855,857,858,860,861,863,865,869,1125}
    Semitic languages
    CP864
    Japanese
    EUC-JISX0213, Shift_JISX0213, ISO-2022-JP-3
    Turkmen
    TDS565
    Platform specifics
    RISCOS-LATIN1
    It can convert from any of these encodings to any other, through Unicode conversion.

    It has also some limited support for transliteration, i.e. when a character cannot be represented in the target character set, it can be approximated through one or several similarly looking characters. Transliteration is activated when "//TRANSLIT" is appended to the target encoding name.


    没有gb2312?

    ~~呵呵~~

    SQLite研究——自定函数

    SQLite研究——自定函数
    jimmy | 14 九月, 2006 14:28
     
    SQLite是一个轻量级引擎,尤其在PHP中内置的2版本,并不带有类似MySQL那样的实用函数。
    但是它提供了一套非常灵活的自定义函数方式。用户可以将需要使用的功能,先用PHP函数实现,然后注册到SQLite里面,就可以在SQL语句中使用了。
    一个最简单的例子:
    function url2host($url) {
     
        $parts = parse_url($url);
     
        return "$parts[scheme]://$parts[host]";
     
    }
     
    // Tell SQLite to associate PHP function url2host( ) with the
    // SQL function host( ). Say that host( ) will only take 1 argument.
     
    sqlite_create_function($db, 'host', 'url2host', 1);
     
    // Do the query
    $r = sqlite_query($db, 'SELECT DISTINCT host(lower(url)) AS clean_host   FROM access_log ORDER BY clean_host;');

    SQLite只支持Count,不支持Averag。所以类似功能也要写函数实现。
    因为需要对多项结果进行累加,注册方式与普通函数注册不同。注意:请严格按照格式进行书写。看起来似乎很复杂,但是如果你用过array_walk,就会感觉到似曾相识了。
    // average_step( ) is called on each row.
    function average_step(&$existing_data, $new_data) {
        $existing_data['total'] += $new_data;
        $existing_data['count']++;
    }
     
    // average_final( ) computes the average and returns it.
    function average_final(&$existing_data) {
        return $existing_data['total'] / $existing_data['count'];
    }
     
    //regist average , using average_step and average_final
    sqlite_create_aggregate($db, 'average', 'average_step', 'average_final');
     
    $r = sqlite_query($db, 'SELECT average(number) FROM numbers');
    需要注意的是: SQLite对COUNT的语法支持与MySQL不同。
    MySQL: select class, count(*) as cnt group by class where cnt > 3
    SQLite: select class, count(*) as cnt group by class HAVING cnt >3
    印象里面SQL2的规范方式就是这样的,只是MySQL为了方便更灵活处理了而已。
    另外,对于自定义函数,还有一点需要说明:
    如果数据是二进制(比如图象),需要进行解码和编码处理。因为函数是在SQLite内部运行的,二进制数据在SQLite内部是编码存储的。
    $data = sqlite_udf_binary_decode($encoded_data);
    .... .... //deal with $data
    $result = sqlite_udf_binary_encode($return_value);

    ~~呵呵~~

    SQLite研究——拾遗补漏

    SQLite研究——拾遗补漏
    jimmy | 12 九月, 2006 17:07


    SQLiteManager虽然强大,但是对环境还是有一些要求,同时程序也过于庞大(2M?)

    有一个替换的方案:phpSQLiteAdmin

    目前版本是0.2,只有不到100K。配置部署也非常简单,放到Web的目录里面就可以了。

     

     

    下面是一些实例代码,最常用的几种方法。分别实现: 执行非查询SQL,返回全部查询,逐条返回查询。

    echo "<hr>PDO��<hr>";
    try {
    $conn = new PDO('sqlite2:jimmy.sqlite');
    $string = 'working...<br>';
    echo $conn->quote($string);echo 'PDO Connection Ok','<br>';
    $conn->beginTransaction();
    $conn->exec("INSERT INTO test values(null,'pdo','pdo_test...')");
    echo $conn->commit();
    echo 'A Transaction: Insert Data ok','<br>';
    } catch (PDOException $e) {
    echo 'Connection failed: ' . $e->getMessage();
    } echo 'get all data','<br>';
    $query=$conn->query('SELECT * FROM test');
    $result=$query->fetchAll();
    trace( $result); echo 'get data line by line', '<br>n';
    $query = $conn->prepare("SELECT * FROM test where id > ?");
    if ($query->execute(array('1'))) {
    while ($row = $query->fetch()) {
    trace($row);
    }
    }

    PDO模式下注意,官方资料new PDO('sqlite:xxx');
    有误,要声明为:$conn = new PDO('sqlite2:jimmy.sqlite') 才能工作。

    echo "<hr>SQLiteç±»<hr>";
    $db = new SQLiteDatabase('jimmy2');
    $db->query("INSERT INTO test VALUES(null,'sqlite','sqlite class')");
    echo 'get data all','<br>';
    $result = $db->arrayQuery('SELECT * FROM test LIMIT 25', SQLITE_ASSOC);
    foreach ($result as $entry) {
    echo 'title: ' . $entry['title'] . ' content: ' . $entry['content'];
    }
    echo '<br>get data line by line','<br>';
    $result = $db->query("SELECT * FROM test LIMIT 25");
    while($row=$result->fetch()){
    print_r($row);
    }

    echo "<hr>Zendç±»<hr>";
    require_once 'Zend.php';
    Zend::loadClass('Zend_Db');
    $params = array ('dbname' => 'jimmy.sqlite','sqlite2' => TRUE);
    $db = Zend_Db::factory('PDO_SQLITE', $params);try {
    $db->beginTransaction();
    $db->query("INSERT INTO test VALUES(null,'sqlite','zend sqlite')");
    echo "<br>Insert OK ".$db->lastInsertId();;
    $db->commit();
    }
    catch (Exception $e) {
    $db->rollBack();
    echo $e->getMessage();
    }
    $result = $db->fetchAll("SELECT * FROM test");
    trace($result);$query = $db->query("SELECT * FROM test");
    while($row=$query->fetch()){
    trace($row);
    }


    Pear的省略了,不是今后的方向。

    在这里我并没有使用API方式,具体使用API可以参照下表:

    MySQL 
    SQLite

    mysqli_connect( ) 
    sqlite_connect( )

    mysqli_close( ) 
    sqlite_close( )

    mysqli_query( ) 
    sqlite_query( )

    mysqli_fetch_row( ) 
    sqlite_fetch_array( )

    mysqli_fetch_assoc( ) 
    sqlite_fetch_array( )

    mysqli_num_rows( ) 
    sqlite_num_rows( )

    mysqli_insert_id( ) 
    sqlite_last_insert_rowid( )

    mysqli_real_escape_string( ) 
    sqlite_escape_string( )

     

    ~~呵呵~~

    SQLite研究——性能优化

    SQLite研究——性能优化
    jimmy | 11 九月, 2006 16:55


    很多人直接就使用了,并未注意到SQLite也有配置参数,可以对性能进行调整。有时候,产生的结果会有很大影响。

    主要通过pragma指令来实现。

    比如: 空间释放、磁盘同步、Cache大小等。


    不要打开。前文提高了,Vacuum的效率非常低!

    PRAGMA auto_vacuum;
    PRAGMA auto_vacuum = 0 | 1;

    查询或设置数据库的auto-vacuum标记。

    正常情况下,当提交一个从数据库中删除数据的事务时,数据库文件不改变大小。未使用的文件页被标记并在以后的添加操作中 再次使用。这种情况下使用VACUUM命令释放删除得到的空间。

    当开启auto-vacuum,当提交一个从数据库中删除数据的事务时,数据库文件自动收缩, (VACUUM命令在auto-vacuum开启的数据库中不起作用)。数据库会在内部存储一些信息以便支持这一功能,这使得 数据库文件比不开启该选项时稍微大一些。

    只有在数据库中未建任何表时才能改变auto-vacuum标记。试图在已有表的情况下修改不会导致报错。


    建议改为8000

    PRAGMA cache_size;
    PRAGMA cache_size = Number-of-pages;

    查询或修改SQLite一次存储在内存中的数据库文件页数。每页使用约1.5K内存,缺省的缓存大小是2000. 若需要使用改变大量多行的UPDATE或DELETE命令,并且不介意SQLite使用更多的内存的话,可以增大缓存以提高性能。

    当使用cache_size pragma改变缓存大小时,改变仅对当前对话有效,当数据库关闭重新打开时缓存大小恢复到缺省大小。 要想永久改变缓存大小,使用default_cache_size pragma.


    打开。不然搜索中文字串会出错。

    PRAGMA case_sensitive_like;
    PRAGMA case_sensitive_like = 0 | 1;

    LIKE运算符的缺省行为是忽略latin1字符的大小写。因此在缺省情况下'a' LIKE 'A'的值为真。可以通过打开 case_sensitive_like pragma来改变这一缺省行为。当启用case_sensitive_like,'a' LIKE 'A'为假而 'a' LIKE 'a'依然为真。


    打开。便于调试

    PRAGMA count_changes;
    PRAGMA count_changes = 0 | 1;

    查询或更改count-changes标记。正常情况下INSERT, UPDATE和DELETE语句不返回数据。 当开启count-changes,以上语句返回一行含一个整数值的数据——该语句插入,修改或删除的行数。 返回的行数不包括由触发器产生的插入,修改或删除等改变的行数。

    PRAGMA page_size;
    PRAGMA page_size = bytes;

    查询或设置page-size值。只有在未创建数据库时才能设置page-size。页面大小必须是2的整数倍且大于等于512小于等于8192。 上限可以通过在编译时修改宏定义SQLITE_MAX_PAGE_SIZE的值来改变。上限的上限是32768.


    如果有定期备份的机制,而且少量数据丢失可接受,用OFF

    PRAGMA synchronous;
    PRAGMA synchronous = FULL; (2)
    PRAGMA synchronous = NORMAL; (1)
    PRAGMA synchronous = OFF; (0)

    查询或更改"synchronous"标记的设定。第一种形式(查询)返回整数值。 当synchronous设置为FULL (2), SQLite数据库引擎在紧急时刻会暂停以确定数据已经写入磁盘。 这使系统崩溃或电源出问题时能确保数据库在重起后不会损坏。FULL synchronous很安全但很慢。 当synchronous设置为NORMAL, SQLite数据库引擎在大部分紧急时刻会暂停,但不像FULL模式下那么频繁。 NORMAL模式下有很小的几率(但不是不存在)发生电源故障导致数据库损坏的情况。但实际上,在这种情况 下很可能你的硬盘已经不能使用,或者发生了其他的不可恢复的硬件错误。 设置为synchronous OFF (0)时,SQLite在传递数据给系统以后直接继续而不暂停。若运行SQLite的应用程序崩溃, 数据不会损伤,但在系统崩溃或写入数据时意外断电的情况下数据库可能会损坏。另一方面,在synchronous OFF时 一些操作可能会快50倍甚至更多。

    在SQLite 2中,缺省值为NORMAL.而在3中修改为FULL.

    使用2,内存模式。

    PRAGMA temp_store;
    PRAGMA temp_store = DEFAULT; (0)
    PRAGMA temp_store = FILE; (1)
    PRAGMA temp_store = MEMORY; (2)

    查询或更改"temp_store"参数的设置。当temp_store设置为DEFAULT (0),使用编译时的C预处理宏 TEMP_STORE来定义储存临时表和临时索引的位置。当设置为MEMORY (2)临时表和索引存放于内存中。 当设置为FILE (1)则存放于文件中。temp_store_directory pragma 可用于指定存放该文件的目录。当改变temp_store设置,所有已存在的临时表,索引,触发器及视图将被立即删除。


    经测试,在类BBS应用上,通过以上调整,效率可以提高2倍以上。


    ~~呵呵~~

    SQLite研究——结构与应用

    SQLite研究——结构与应用
    jimmy | 11 九月, 2006 16:26


    SQLite一些不支持的功能:

    外键约束(FOREIGN KEY constraints) 
     
    外键约束会被解析但不会被执行。

    完整的触发器支持(Complete trigger support) 
     
    现在有一些触发器的支持,但是还不完整。 缺少的特性包括 FOR EACH STATEMENT 触发器(现在所有的触发器都必须是 FOR EACH ROW ), 在表上的 INSTEAD OF 触发器(现在 INSTEAD OF 触发器只允许在视图上), 以及递归触发器——触发自身的触发器。

    完整的 ALTER TABLE 支持(Complete ALTER TABLE support) 
     
    只支持 ALTER TABLE 命令的 RENAME TABLE 和 ADD COLUMN。 其他类型的 ALTER TABLE 操作如 DROP COLUMN,ALTER COLUMN,ADD CONSTRAINT 等等均被忽略。

    嵌套事务(Nested transactions) 
     
    现在的实现只允许单一活动事务。

    RIGHT 和 FULL OUTER JOIN(RIGHT and FULL OUTER JOIN) 
     
    LEFT OUTER JOIN 已经实现,但还没有 RIGHT OUTER JOIN 和 FULL OUTER JOIN。

    可写视图(Writing to VIEWs) 
     
    SQLite 中的视图是只读的。无法在一个视图上执行 DELETE,INSERT,UPDATE。 不过你可以创建一个试图在视图上 DELETE,INSERT,UPDATE 时触发的触发器,然后在触发器中完成你所需要的工作。

    GRANT 和 REVOKE(GRANT and REVOKE) 
     
    由于 SQLite 读和写的是一个普通的磁盘文件, 因此唯一可以获取的权限就是操作系统的标准的文件访问权限。 一般在客户机/服务器架构的关系型数据库系统上能找到的 GRANT 和 REVOKE 命令对于一个嵌入式的数据库引擎来说是没有意义的, 因此也就没有去实现。

     

    建议多建索引。前文可以看出,建索引对SQLite的消耗并不大,但是效果是非常明显的。

    SQLite的维护工具还不完全。看到一个有趣的例子,对表进行优化:
    create TABLE wibble2 AS SELECT * FROM wibble;
    DELETE FROM wibble;
    INSERT INTO wibble SELECT * FROM wibble2 ORDER BY KEY;
    DROP TABLE wibble2;

    在数据量不大的情况下未偿不可。因为官方介绍“VACUUM 命令会清空“空闲列表”,把数据库尺寸缩到最小。注意, VACUUM 会耗费一些时间(在 Linux 系统下大约0.5秒/兆)并且要使用两倍于数据库文件大小的磁盘空间。”。用复制的方式可能会更快。

    前面已经提到,SQLite是无数据类型存储的,但是还是建议不要在你的表里面使用无类型。同时,在程序侧对录入数据进行类型检查。

    官方将之称为:type or column affinity

    具体在应用中可能发生的是:

    1,一个整型字段中,存进去一个字符串。

    2,声明一个VARCHAR(10),SQLite一样可以让你存放500个字符在里面。 并且它们会始终完整无缺——决不会被截断。

    那么设置类型还有什么用呢?A,索引;B,整理;C,防止你自己忘记。:)

    SQLite支持的数据结构:

    1. Storage Classes

    NULL. The value is a NULL value.

    INTEGER. The value is a signed integer, stored in 1, 2, 3, 4, 6, or 8 bytes depending on the magnitude of the value.

    REAL. The value is a floating point value, stored as an 8-byte IEEE floating point number.

    TEXT. The value is a text string, stored using the database encoding (UTF-8, UTF-16BE or UTF-16-LE).

    BLOB. The value is a blob of data, stored exactly as it was input.

    2. Column Affinity
    TEXT
    NUMERIC
    INTEGER
    REAL
    NONE

    SQLite支持的语法:
    ALTER TABLE
    ANALYZE
    ATTACH DATABASE
    BEGIN TRANSACTION
    注释
    COMMIT TRANSACTION
    COPY
    CREATE INDEX
    CREATE TABLE
    CREATE TRIGGER
    CREATE VIEW
    DELETE
    DETACH DATABASE
    DROP INDEX
    DROP TABLE
    DROP TRIGGER
    DROP VIEW
    END TRANSACTION
    EXPLAIN
    表达式
    INSERT
    ON CONFLICT子句
    PRAGMA
    REINDEX
    REPLACE
    ROLLBACK TRANSACTION
    SELECT
    UPDATE
    VACUUM

    最后: 如果你在Windows用,最好用filename.sqlite做文件名。或者,不用扩展名。


    Procedural name 
    Object-oriented name

    $db = sqlite_open($table) 
    $db = new SQLiteDatabase($table)

    sqlite_close($db) 
    unset($db)

    $r = sqlite_query($db, $sql) 
    $r = $db->query($sql)

    $r = sqlite_query_array($db, $sql) 
    $r = $db->arrayQuery($sql)

    $r = sqlite_query_unbuffered($db, $sql) 
    $r = $db->unbufferedQuery($sql)

    sqlite_fetch_array($r) 
    $r->fetch( )

    sqlite_fetch_single($r) 
    $r->fetchSingle( )

    $safe = sqlite_escape_string($s) 
    $safe = $db->escapeString($s)

    $id = sqlite_last_insert_rowid($r) 
    $id = $db->lastInsertRowid($r)


    ~~呵呵~~

    SQLite研究——特性

    SQLite研究——特性
    jimmy | 11 九月, 2006 14:48


    SQLite是一种无数据类型的数据库。

    即使设置了列的类型为Integer,仍然可以将String值存放进去。

    唯一的例外: 作为PrimaryKey的Integer。

    另外,PrimaryKey的Integer还有一个特性,就是Insert时为null,会自动按照自增量存放。

    在我的上一篇中的测试程序可以看到这一点。


    在进行更多分析之前,先抄录一些对比数据:
    Test 1: 1000 INSERTs
    CREATE TABLE t1(a INTEGER, b INTEGER, c VARCHAR(100));
    INSERT INTO t1 VALUES(1,13153,'thirteen thousand one hundred fifty three');
    INSERT INTO t1 VALUES(2,75560,'seventy five thousand five hundred sixty');
    ... 995 lines omitted
    INSERT INTO t1 VALUES(998,66289,'sixty six thousand two hundred eighty nine');
    INSERT INTO t1 VALUES(999,24322,'twenty four thousand three hundred twenty two');
    INSERT INTO t1 VALUES(1000,94142,'ninety four thousand one hundred forty two');SQLite 3.3.3 (sync): 3.823
    SQLite 3.3.3 (nosync): 1.668
    SQLite 2.8.17 (sync): 4.245
    SQLite 2.8.17 (nosync): 1.743
    PostgreSQL 8.1.2: 4.922
    MySQL 5.0.18 (sync): 2.647
    MySQL 5.0.18 (nosync): 0.329
    FirebirdSQL 1.5.2: 0.320

    Test 2: 25000 INSERTs in a transaction
    BEGIN;
    CREATE TABLE t2(a INTEGER, b INTEGER, c VARCHAR(100));
    INSERT INTO t2 VALUES(1,298361,'two hundred ninety eight thousand three hundred sixty one');
    ... 24997 lines omitted
    INSERT INTO t2 VALUES(24999,447847,'four hundred forty seven thousand eight hundred forty seven');
    INSERT INTO t2 VALUES(25000,473330,'four hundred seventy three thousand three hundred thirty');
    COMMIT;SQLite 3.3.3 (sync): 0.764
    SQLite 3.3.3 (nosync): 0.748
    SQLite 2.8.17 (sync): 0.698
    SQLite 2.8.17 (nosync): 0.663
    PostgreSQL 8.1.2: 16.454
    MySQL 5.0.18 (sync): 7.833
    MySQL 5.0.18 (nosync): 7.038
    FirebirdSQL 1.5.2: 4.280

    Test 3: 25000 INSERTs into an indexed table
    BEGIN;
    CREATE TABLE t3(a INTEGER, b INTEGER, c VARCHAR(100));
    CREATE INDEX i3 ON t3(c);
    ... 24998 lines omitted
    INSERT INTO t3 VALUES(24999,442549,'four hundred forty two thousand five hundred forty nine');
    INSERT INTO t3 VALUES(25000,423958,'four hundred twenty three thousand nine hundred fifty eight');
    COMMIT;SQLite 3.3.3 (sync): 1.778
    SQLite 3.3.3 (nosync): 1.832
    SQLite 2.8.17 (sync): 1.526
    SQLite 2.8.17 (nosync): 1.364
    PostgreSQL 8.1.2: 19.236
    MySQL 5.0.18 (sync): 11.524
    MySQL 5.0.18 (nosync): 12.427
    FirebirdSQL 1.5.2: 6.351

    Test 4: 100 SELECTs without an index
    SELECT count(*), avg(b) FROM t2 WHERE b>=0 AND b<1000;
    SELECT count(*), avg(b) FROM t2 WHERE b>=100 AND b<1100;
    SELECT count(*), avg(b) FROM t2 WHERE b>=200 AND b<1200;
    ... 94 lines omitted
    SELECT count(*), avg(b) FROM t2 WHERE b>=9700 AND b<10700;
    SELECT count(*), avg(b) FROM t2 WHERE b>=9800 AND b<10800;
    SELECT count(*), avg(b) FROM t2 WHERE b>=9900 AND b<10900;SQLite 3.3.3 (sync): 3.153
    SQLite 3.3.3 (nosync): 3.088
    SQLite 2.8.17 (sync): 3.993
    SQLite 2.8.17 (nosync): 3.983
    PostgreSQL 8.1.2: 5.740
    MySQL 5.0.18 (sync): 2.718
    MySQL 5.0.18 (nosync): 1.641
    FirebirdSQL 1.5.2: 2.976

    Test 5: 100 SELECTs on a string comparison
    SELECT count(*), avg(b) FROM t2 WHERE c LIKE '%one%';
    SELECT count(*), avg(b) FROM t2 WHERE c LIKE '%two%';
    SELECT count(*), avg(b) FROM t2 WHERE c LIKE '%three%';
    ... 94 lines omitted
    SELECT count(*), avg(b) FROM t2 WHERE c LIKE '%ninety eight%';
    SELECT count(*), avg(b) FROM t2 WHERE c LIKE '%ninety nine%';
    SELECT count(*), avg(b) FROM t2 WHERE c LIKE '%one hundred%';SQLite 3.3.3 (sync): 4.853
    SQLite 3.3.3 (nosync): 4.868
    SQLite 2.8.17 (sync): 4.511
    SQLite 2.8.17 (nosync): 4.500
    PostgreSQL 8.1.2: 6.565
    MySQL 5.0.18 (sync): 3.424
    MySQL 5.0.18 (nosync): 2.090
    FirebirdSQL 1.5.2: 5.803

    Test 6: INNER JOIN without an index
    SELECT t1.a FROM t1 INNER JOIN t2 ON t1.b=t2.b; SQLite 3.3.3 (sync): 14.473
    SQLite 3.3.3 (nosync): 14.445
    SQLite 2.8.17 (sync): 47.776
    SQLite 2.8.17 (nosync): 47.750
    PostgreSQL 8.1.2: 0.176
    MySQL 5.0.18 (sync): 3.421
    MySQL 5.0.18 (nosync): 3.443
    FirebirdSQL 1.5.2: 0.141

    Test 7: Creating an index
    CREATE INDEX i2a ON t2(a);
    CREATE INDEX i2b ON t2(b); SQLite 3.3.3 (sync): 0.552
    SQLite 3.3.3 (nosync): 0.526
    SQLite 2.8.17 (sync): 0.650
    SQLite 2.8.17 (nosync): 0.605
    PostgreSQL 8.1.2: 0.276
    MySQL 5.0.18 (sync): 1.159
    MySQL 5.0.18 (nosync): 0.275
    FirebirdSQL 1.5.2: 0.264

    Test 8: 5000 SELECTs with an index
    SELECT count(*), avg(b) FROM t2 WHERE b>=0 AND b<100;
    SELECT count(*), avg(b) FROM t2 WHERE b>=100 AND b<200;
    SELECT count(*), avg(b) FROM t2 WHERE b>=200 AND b<300;
    ... 4994 lines omitted
    SELECT count(*), avg(b) FROM t2 WHERE b>=499700 AND b<499800;
    SELECT count(*), avg(b) FROM t2 WHERE b>=499800 AND b<499900;
    SELECT count(*), avg(b) FROM t2 WHERE b>=499900 AND b<500000;SQLite 3.3.3 (sync): 1.872
    SQLite 3.3.3 (nosync): 1.853
    SQLite 2.8.17 (sync): 2.444
    SQLite 2.8.17 (nosync): 2.478
    PostgreSQL 8.1.2: 199.823
    MySQL 5.0.18 (sync): 3.763
    MySQL 5.0.18 (nosync): 3.725
    FirebirdSQL 1.5.2: 5.187

    * Performance of PostgreSQL in this test is most probably heavily impacted by psql command line utility. Same test when run form pgAdmin III GUI completed in 5 seconds.
    Test 9: 1000 UPDATEs without an index
    BEGIN;
    UPDATE t1 SET b=b*2 WHERE a>=0 AND a<10;
    UPDATE t1 SET b=b*2 WHERE a>=10 AND a<20;
    ... 996 lines omitted
    UPDATE t1 SET b=b*2 WHERE a>=9980 AND a<9990;
    UPDATE t1 SET b=b*2 WHERE a>=9990 AND a<10000;
    COMMIT;SQLite 3.3.3 (sync): 0.562
    SQLite 3.3.3 (nosync): 0.573
    SQLite 2.8.17 (sync): 0.543
    SQLite 2.8.17 (nosync): 0.532
    PostgreSQL 8.1.2: 1.663
    MySQL 5.0.18 (sync): 1.930
    MySQL 5.0.18 (nosync): 4.656
    FirebirdSQL 1.5.2: 1.804

    Test 10: 25000 UPDATEs with an index
    BEGIN;
    UPDATE t2 SET b=271822 WHERE a=1;
    UPDATE t2 SET b=28304 WHERE a=2;
    ... 24996 lines omitted
    UPDATE t2 SET b=442549 WHERE a=24999;
    UPDATE t2 SET b=423958 WHERE a=25000;
    COMMIT;SQLite 3.3.3 (sync): 1.883
    SQLite 3.3.3 (nosync): 1.894
    SQLite 2.8.17 (sync): 1.994
    SQLite 2.8.17 (nosync): 1.973
    PostgreSQL 8.1.2: 23.933
    MySQL 5.0.18 (sync): 16.348
    MySQL 5.0.18 (nosync): 17.383
    FirebirdSQL 1.5.2: 15.542

    Test 11: 25000 text UPDATEs with an index
    BEGIN;
    UPDATE t2 SET c='four hundred sixty eight thousand twenty six' WHERE a=1;
    UPDATE t2 SET c='one hundred twenty one thousand nine hundred twenty eight' WHERE a=2;
    ... 24996 lines omitted
    UPDATE t2 SET c='thirty five thousand sixty five' WHERE a=24999;
    UPDATE t2 SET c='three hundred forty seven thousand three hundred ninety three' WHERE a=25000;
    COMMIT;SQLite 3.3.3 (sync): 1.386
    SQLite 3.3.3 (nosync): 1.365
    SQLite 2.8.17 (sync): 1.168
    SQLite 2.8.17 (nosync): 1.121
    PostgreSQL 8.1.2: 24.672
    MySQL 5.0.18 (sync): 16.469
    MySQL 5.0.18 (nosync): 15.491
    FirebirdSQL 1.5.2: 21.583

    Test 12: INSERTs from a SELECT
    BEGIN;
    INSERT INTO t1 SELECT * FROM t2;
    INSERT INTO t2 SELECT * FROM t1;
    COMMIT; SQLite 3.3.3 (sync): 1.179
    SQLite 3.3.3 (nosync): 1.116
    SQLite 2.8.17 (sync): 1.864
    SQLite 2.8.17 (nosync): 1.526
    PostgreSQL 8.1.2: 1.091
    MySQL 5.0.18 (sync): 0.986
    MySQL 5.0.18 (nosync): 0.933
    FirebirdSQL 1.5.2: 4.782

    Test 13: INNER JOIN with index on one side
    SELECT t1.a FROM t1 INNER JOIN t2 ON t1.b=t2.b; SQLite 3.3.3 (sync): 0.371
    SQLite 3.3.3 (nosync): 0.369
    SQLite 2.8.17 (sync): 0.273
    SQLite 2.8.17 (nosync): 0.275
    PostgreSQL 8.1.2: 5.981
    MySQL 5.0.18 (sync): 0.408
    MySQL 5.0.18 (nosync): 0.603
    FirebirdSQL 1.5.2: 1.099

    Test 14: INNER JOIN on text field with index on one side
    SELECT t1.a FROM t1 INNER JOIN t3 ON t1.c=t3.c; SQLite 3.3.3 (sync): 0.383
    SQLite 3.3.3 (nosync): 0.376
    SQLite 2.8.17 (sync): 0.309
    SQLite 2.8.17 (nosync): 0.291
    PostgreSQL 8.1.2: 1.324
    MySQL 5.0.18 (sync): 0.404
    MySQL 5.0.18 (nosync): 0.558
    FirebirdSQL 1.5.2: 0.454

    Test 15: 100 SELECTs with subqueries. Subquery is using an index
    SELECT t1.a FROM t1 WHERE t1.b IN (SELECT t2.b FROM t2 WHERE t2.b>=0 AND t2.b<1000);
    SELECT t1.a FROM t1 WHERE t1.b IN (SELECT t2.b FROM t2 WHERE t2.b>=100 AND t2.b<1100);
    SELECT t1.a FROM t1 WHERE t1.b IN (SELECT t2.b FROM t2 WHERE t2.b>=200 AND t2.b<1200);
    ... 94 lines omitted
    SELECT t1.a FROM t1 WHERE t1.b IN (SELECT t2.b FROM t2 WHERE t2.b>=9700 AND t2.b<10700);
    SELECT t1.a FROM t1 WHERE t1.b IN (SELECT t2.b FROM t2 WHERE t2.b>=9800 AND t2.b<10800);
    SELECT t1.a FROM t1 WHERE t1.b IN (SELECT t2.b FROM t2 WHERE t2.b>=9900 AND t2.b<10900);SQLite 3.3.3 (sync): 7.877
    SQLite 3.3.3 (nosync): 8.040
    SQLite 2.8.17 (sync): 4.387
    SQLite 2.8.17 (nosync): 4.381
    PostgreSQL 8.1.2: 6.245
    MySQL 5.0.18 (sync): 16.891
    MySQL 5.0.18 (nosync): 38.447
    FirebirdSQL 1.5.2: 37.439

    Test 16: DELETE without an index
    DELETE FROM t2 WHERE c LIKE '%fifty%'; SQLite 3.3.3 (sync): 0.528
    SQLite 3.3.3 (nosync): 0.429
    SQLite 2.8.17 (sync): 1.228
    SQLite 2.8.17 (nosync): 0.984
    PostgreSQL 8.1.2: 0.336
    MySQL 5.0.18 (sync): 0.394
    MySQL 5.0.18 (nosync): 0.532
    FirebirdSQL 1.5.2: 0.404

    Test 17: DELETE with an index
    DELETE FROM t2 WHERE a>10 AND a<20000; SQLite 3.3.3 (sync): 0.866
    SQLite 3.3.3 (nosync): 0.627
    SQLite 2.8.17 (sync): 1.275
    SQLite 2.8.17 (nosync): 0.817
    PostgreSQL 8.1.2: 0.283
    MySQL 5.0.18 (sync): 0.541
    MySQL 5.0.18 (nosync): 1.336
    FirebirdSQL 1.5.2: 5.033

    Test 18: A big INSERT after a big DELETE
    INSERT INTO t2 SELECT * FROM t1; SQLite 3.3.3 (sync): 0.973
    SQLite 3.3.3 (nosync): 0.865
    SQLite 2.8.17 (sync): 1.680
    SQLite 2.8.17 (nosync): 1.336
    PostgreSQL 8.1.2: 0.727
    MySQL 5.0.18 (sync): 0.762
    MySQL 5.0.18 (nosync): 1.088
    FirebirdSQL 1.5.2: 4.171

    Test 19: A big DELETE followed by many small INSERTs
    BEGIN;
    DELETE FROM t1;
    INSERT INTO t1 VALUES(1,29676,'twenty nine thousand six hundred seventy six');
    ... 2997 lines omitted
    INSERT INTO t1 VALUES(2999,37835,'thirty seven thousand eight hundred thirty five');
    INSERT INTO t1 VALUES(3000,97817,'ninety seven thousand eight hundred seventeen');
    COMMIT;SQLite 3.3.3 (sync): 0.155
    SQLite 3.3.3 (nosync): 0.133
    SQLite 2.8.17 (sync): 0.160
    SQLite 2.8.17 (nosync): 0.255
    PostgreSQL 8.1.2: 2.635
    MySQL 5.0.18 (sync): 1.402
    MySQL 5.0.18 (nosync): 1.133
    FirebirdSQL 1.5.2: 0.667

    Test 20: DROP TABLE
    DROP TABLE t1;
    DROP TABLE t2; SQLite 3.3.3 (sync): 0.138
    SQLite 3.3.3 (nosync): 0.392
    SQLite 2.8.17 (sync): 0.188
    SQLite 2.8.17 (nosync): 0.257
    PostgreSQL 8.1.2: 0.229
    MySQL 5.0.18 (sync): 0.125
    MySQL 5.0.18 (nosync): 0.058
    FirebirdSQL 1.5.2: 0.133

     

    以上数据引自SQLite.org。相信是很多PostgreSQL和MySQL的FANS感情上不能接受。

    当然,这个测试有些偏向SQLite,但是从中也是可以分析得到很多有意事实的:

    1,SQLite已经比以往版本有了长足进步。在轻量级数据情况下足以与常规DBM分庭抗礼。

    2,在事务测试中表现优异,与其简单的文件存储方式有关。可以不用像MySQL那样对事务采取回避态度。

    3,对Index的依赖度较高。尤其在Join操作上。

    4,对字串的操作能力较差,尽量减少字符串比较。

    5,DELETE消耗明显比UPDATE大。与其文件存储的结构有关。设计上可采用删除标志位方式。

    测试外隐含的信息:

    1,未测试并发性——推测:SQLlite对并发支持很差,尤其在重任务情况下。

    2,无数据库中表的数量、存储数据的数量增加情况下的测试——不断的增加、删除数据,表数量也变得越来越多,这是一般应用中最常见的。推测:SQLite单一文件存储方式,对复杂结构的支持较弱。随着应用不断深入,性能会越来越差。

    值得指出的是:

    1,PostgreSQL虽然在各项测试中都表现不理想,但是在实际应用中表现并不差。因为它提供了很多优化工具,同时对锁和调度的处理非常优异,重负载情况下尤其突出。

    2,MySQL的MyISAM与InnoDB的性能差异竟然到了如此小的程度?甚至很多项目中InnoDB都超越了MyISAM。我不是质疑测试结果,只是感慨。MyISAM的性能上确实已经很久没有什么改进了。在InnoDB上投入那么多,最后还是面临引擎断粮。MYSQL要解决的问题很多,不只是SELECT嵌套所暴露出来的那么简单。

    综上所述,SQLite在如下方面具有优势:

    1,独立产品,代码与数据库简单,封装后重复部署

    2,数据量少,表结构简单

    3,单次插入,多次读取,读取远高于插入

    4,累增不删

    5,表关联少

    6,并发度低,对锁依赖低

    在PHP应用中,有很多具有以上特征的产品。将代码与数据库一同打包,然后方便的进行部署或迁移,对提高开发效率、减少维护工作量具有重大意义。

    ~~呵呵~~

    SQLite研究——安装与环境

    SQLite研究——安装与环境
    jimmy | 11 九月, 2006 12:06

     

    PHP已经内置了对SQLite的支持。

    用如下代码可以测试当前PHP是否带有SQLite支持:
    <?
    $db_name='sqlite.db';
    $db=new SQLiteDatabase($db_name, 0644, $error);
    $db->Query("CREATE TABLE test ( id INTEGER NOT NULL PRIMARY KEY , title VARCHAR ( 20 ) NOT NULL , content VARCHAR ( 200 ) NOT NULL )");
    $db->Query("INSERT INTO test (id, title, content) VALUES ('1','test','someword')");$result_info=$db->arrayQuery("SELECT * FROM test  DESC LIMIT 200");
    foreach($result_info as $val){
    print_r($val);
    }
    ?>

    但是,仅有支持还是不够的。就像PhpMyAdmin极大的推动了MySQL在PHP下的应用一样,管理工具是非常重要的。比较推荐使用的是SQLiteManager。虽然官方声称在PHP4下也能正常工作,但是推荐使用PHP5,并且安装PDO。

    Windows: 下载PHP5.1以上版本

    编辑php.ini

    extension=php_pdo.dll
    extension=php_pdo_sqlite.dll
    extension=php_sqlite.dll

    重启Apache。

    下载:SQLiteManager (http://www.sqlitemanager.org/

    解压到htdocs/SQlite/

    编辑 ./include/user_defined.inc.php,调整这三个参数。

    define("INCLUDE_LIB", 'e:/htdocs/SQLite/SQLiteManager/include/');

    define ("SQLiteDb", 'e:htdocsSQLiteSQLiteManagerincludeconfig.db');

    define("DEFAULT_DB_PATH", 'e:/htdocs/SQLite/');

    编辑: ./lang/simplified_chinese.inc.php Line21:

    12=>"简体中文",13=>"繁体中文"

    修改为:

    13=>"简体中文",12=>"繁体中文"

    是个BUG,作者将这两个搞反了。:)

    然后可以运行一下了:

    http://localhost/SQLite/SQLiteManager/index.php

    把test库删除,新建一个。看到如下视图说明OK了:

     


    然后我们来看Linux下的:
    需要 --enable-pdo --with-pdo-sqlite --with-sqlite
    官方说明上指出,如果--enable-pdo=shared,那么都要用shared。不过,还是不要用shared的更方便些。
    一个参考的配置:
    ./configure --prefix=/usr/local/php5.1 --with-mysql=/usr/local/mysql --with-iconv --with-apxs2=/usr/local/apache2/bin/apxs --with-zlib --with-xsl --enable-mbstring --with-zlib --enable-pdo --with-pdo-sqlite --with-sqlite
    上传SQLiteManager。修改user_define.inc.php。
    记得将include目录、DB存储目录改为可写。
    # chown nobody include/ -R
    # chgrp nobody include/ -R
    OK,可以进行开发工作了。
    更多对SQLite的研究将后续增加。
    ~~呵呵~~

    PHP预定义变量、常量

    PHP预定义变量、常量
    jimmy | 10 九月, 2006 20:23


    除了平时最常用到的_SERVER/_POST/_FILE/_COOKIE/_REQUEST这些变量以外,还有一些使用较少的。

    供参考:

    PHP 的“魔术常量”
    名称 说明
    __LINE__ 文件中的当前行号。
    __FILE__ 文件的完整路径和文件名。
    __FUNCTION__ 函数名称(这是 PHP 4.3.0 新加的)。
    __CLASS__ 类的名称(这是 PHP 4.3.0 新加的)。
    __METHOD__ 类的方法名(这是 PHP 5.0.0 新加的)。

     

    内核预定义常量
    内核预定义常量 -- 在 PHP 内核、Zend 和 SAPI 模块中定义的常量
    描述

    这些常量在 PHP 的内核中定义。它包含 PHP、Zend 引擎和 SAPI 模块。

    PHP_VERSION (string)

    PHP_OS (string)

    DEFAULT_INCLUDE_PATH (string)

    PEAR_INSTALL_DIR (string)

    PEAR_EXTENSION_DIR (string)

    PHP_EXTENSION_DIR (string)

    PHP_BINDIR (string)

    PHP_LIBDIR (string)

    PHP_DATADIR (string)

    PHP_SYSCONFDIR (string)

    PHP_LOCALSTATEDIR (string)

    PHP_CONFIG_FILE_PATH (string)

    PHP_OUTPUT_HANDLER_START (integer)

    PHP_OUTPUT_HANDLER_CONT (integer)

    PHP_OUTPUT_HANDLER_END (integer)

    E_ERROR (integer)

    E_WARNING (integer)

    E_PARSE (integer)

    E_NOTICE (integer)

    E_CORE_ERROR (integer)

    E_CORE_WARNING (integer)

    E_COMPILE_ERROR (integer)

    E_COMPILE_WARNING (integer)

    E_USER_ERROR (integer)

    E_USER_WARNING (integer)

    E_USER_NOTICE (integer)

    E_ALL (integer)

    标准预定义常量
    标准预定义常量 -- PHP 中默认定义的常量
    描述

    这些常量是 PHP 默认定义的。

    EXTR_OVERWRITE (integer)

    EXTR_SKIP (integer)

    EXTR_PREFIX_SAME (integer)

    EXTR_PREFIX_ALL (integer)

    EXTR_PREFIX_INVALID (integer)

    EXTR_PREFIX_IF_EXISTS (integer)

    EXTR_IF_EXISTS (integer)

    SORT_ASC (integer)

    SORT_DESC (integer)

    SORT_REGULAR (integer)

    SORT_NUMERIC (integer)

    SORT_STRING (integer)

    CASE_LOWER (integer)

    CASE_UPPER (integer)

    COUNT_NORMAL (integer)

    COUNT_RECURSIVE (integer)

    ASSERT_ACTIVE (integer)

    ASSERT_CALLBACK (integer)

    ASSERT_BAIL (integer)

    ASSERT_WARNING (integer)

    ASSERT_QUIET_EVAL (integer)

    CONNECTION_ABORTED (integer)

    CONNECTION_NORMAL (integer)

    CONNECTION_TIMEOUT (integer)

    INI_USER (integer)

    INI_PERDIR (integer)

    INI_SYSTEM (integer)

    INI_ALL (integer)

    M_E (float)

    M_LOG2E (float)

    M_LOG10E (float)

    M_LN2 (float)

    M_LN10 (float)

    M_PI (float)

    M_PI_2 (float)

    M_PI_4 (float)

    M_1_PI (float)

    M_2_PI (float)

    M_2_SQRTPI (float)

    M_SQRT2 (float)

    M_SQRT1_2 (float)

    CRYPT_SALT_LENGTH (integer)

    CRYPT_STD_DES (integer)

    CRYPT_EXT_DES (integer)

    CRYPT_MD5 (integer)

    CRYPT_BLOWFISH (integer)

    DIRECTORY_SEPARATOR (string)

    SEEK_SET (integer)

    SEEK_CUR (integer)

    SEEK_END (integer)

    LOCK_SH (integer)

    LOCK_EX (integer)

    LOCK_UN (integer)

    LOCK_NB (integer)

    HTML_SPECIALCHARS (integer)

    HTML_ENTITIES (integer)

    ENT_COMPAT (integer)

    ENT_QUOTES (integer)

    ENT_NOQUOTES (integer)

    INFO_GENERAL (integer)

    INFO_CREDITS (integer)

    INFO_CONFIGURATION (integer)

    INFO_MODULES (integer)

    INFO_ENVIRONMENT (integer)

    INFO_VARIABLES (integer)

    INFO_LICENSE (integer)

    INFO_ALL (integer)

    CREDITS_GROUP (integer)

    CREDITS_GENERAL (integer)

    CREDITS_SAPI (integer)

    CREDITS_MODULES (integer)

    CREDITS_DOCS (integer)

    CREDITS_FULLPAGE (integer)

    CREDITS_QA (integer)

    CREDITS_ALL (integer)

    STR_PAD_LEFT (integer)

    STR_PAD_RIGHT (integer)

    STR_PAD_BOTH (integer)

    PATHINFO_DIRNAME (integer)

    PATHINFO_BASENAME (integer)

    PATHINFO_EXTENSION (integer)

    CHAR_MAX (integer)

    LC_CTYPE (integer)

    LC_NUMERIC (integer)

    LC_TIME (integer)

    LC_COLLATE (integer)

    LC_MONETARY (integer)

    LC_ALL (integer)

    LC_MESSAGES (integer)

    ABDAY_1 (integer)

    ABDAY_2 (integer)

    ABDAY_3 (integer)

    ABDAY_4 (integer)

    ABDAY_5 (integer)

    ABDAY_6 (integer)

    ABDAY_7 (integer)

    DAY_1 (integer)

    DAY_2 (integer)

    DAY_3 (integer)

    DAY_4 (integer)

    DAY_5 (integer)

    DAY_6 (integer)

    DAY_7 (integer)

    ABMON_1 (integer)

    ABMON_2 (integer)

    ABMON_3 (integer)

    ABMON_4 (integer)

    ABMON_5 (integer)

    ABMON_6 (integer)

    ABMON_7 (integer)

    ABMON_8 (integer)

    ABMON_9 (integer)

    ABMON_10 (integer)

    ABMON_11 (integer)

    ABMON_12 (integer)

    MON_1 (integer)

    MON_2 (integer)

    MON_3 (integer)

    MON_4 (integer)

    MON_5 (integer)

    MON_6 (integer)

    MON_7 (integer)

    MON_8 (integer)

    MON_9 (integer)

    MON_10 (integer)

    MON_11 (integer)

    MON_12 (integer)

    AM_STR (integer)

    PM_STR (integer)

    D_T_FMT (integer)

    D_FMT (integer)

    T_FMT (integer)

    T_FMT_AMPM (integer)

    ERA (integer)

    ERA_YEAR (integer)

    ERA_D_T_FMT (integer)

    ERA_D_FMT (integer)

    ERA_T_FMT (integer)

    ALT_DIGITS (integer)

    INT_CURR_SYMBOL (integer)

    CURRENCY_SYMBOL (integer)

    CRNCYSTR (integer)

    MON_DECIMAL_POINT (integer)

    MON_THOUSANDS_SEP (integer)

    MON_GROUPING (integer)

    POSITIVE_SIGN (integer)

    NEGATIVE_SIGN (integer)

    INT_FRAC_DIGITS (integer)

    FRAC_DIGITS (integer)

    P_CS_PRECEDES (integer)

    P_SEP_BY_SPACE (integer)

    N_CS_PRECEDES (integer)

    N_SEP_BY_SPACE (integer)

    P_SIGN_POSN (integer)

    N_SIGN_POSN (integer)

    DECIMAL_POINT (integer)

    RADIXCHAR (integer)

    THOUSANDS_SEP (integer)

    THOUSEP (integer)

    GROUPING (integer)

    YESEXPR (integer)

    NOEXPR (integer)

    YESSTR (integer)

    NOSTR (integer)

    CODESET (integer)

    LOG_EMERG (integer)

    LOG_ALERT (integer)

    LOG_CRIT (integer)

    LOG_ERR (integer)

    LOG_WARNING (integer)

    LOG_NOTICE (integer)

    LOG_INFO (integer)

    LOG_DEBUG (integer)

    LOG_KERN (integer)

    LOG_USER (integer)

    LOG_MAIL (integer)

    LOG_DAEMON (integer)

    LOG_AUTH (integer)

    LOG_SYSLOG (integer)

    LOG_LPR (integer)

    LOG_NEWS (integer)

    LOG_UUCP (integer)

    LOG_CRON (integer)

    LOG_AUTHPRIV (integer)

    LOG_LOCAL0 (integer)

    LOG_LOCAL1 (integer)

    LOG_LOCAL2 (integer)

    LOG_LOCAL3 (integer)

    LOG_LOCAL4 (integer)

    LOG_LOCAL5 (integer)

    LOG_LOCAL6 (integer)

    LOG_LOCAL7 (integer)

    LOG_PID (integer)

    LOG_CONS (integer)

    LOG_ODELAY (integer)

    LOG_NDELAY (integer)

    LOG_NOWAIT (integer)

    LOG_PERROR (integer)
    预定义变量

    自 PHP 4.1.0 起,取得外部变量的首选方法是用下面提及的超全局变量。在此之前,人们要么依赖 register_globals,要么就是长长的预定义 PHP 数组($HTTP_*_VARS)。 在 PHP 5.0.0 中,长的 PHP 预定义数组可以通过设置 register_long_arrays 来屏蔽。
    服务器变量:$_SERVER

    注: 在 PHP 4.1.0 及以后版本使用。之前的版本,使用 $HTTP_SERVER_VARS。

    $_SERVER 是一个包含诸如头部(headers)、路径(paths)和脚本位置(script locations)的数组。数组的实体由 web 服务器创建。不能保证所有的服务器都能产生所有的信息;服务器可能忽略了一些信息,或者产生了一些未在下面列出的新的信息。这意味着,大量的这些变量在 CGI 1.1 specification 中说明,所以您应该仔细研究它。

    这是一个“superglobal”,或者可以描述为自动全局变量。这只不过意味这它在所有的脚本中都有效。在函数或方法中您不需要使用 global $_SERVER; 访问它,就如同使用 $HTTP_SERVER_VARS 一样。

    $HTTP_SERVER_VARS 包含着同样的信息,但是不是一个自动全局变量。(注意: $HTTP_SERVER_VARS 和 $_SERVER 是不同的变量,PHP 处理它们的方式不同。)

    如果设置了 register_globals 指令,这些变量也在所有脚本中可用;也就是,分离了 $_SERVER 和 $HTTP_SERVER_VARS 数组。相关信息,请参阅安全的相关章节 使用 Register Globals。这些单独的全局变量不是自动全局变量。

    您或许会发现下面列出的某些 $_SERVER 元素并不可用。注意,如果以命令行方式运行 PHP,下面列出的元素几乎没有有效的(或是没有任何实际意义的)。


    “PHP_SELF”

    当前正在执行脚本的文件名,与 document root相关。举例来说,在URL地址为 http://example.com/test.php/foo.bar 的脚本中使用 $_SERVER['PHP_SELF'] 将会得到 /test.php/foo.bar 这个结果。

    如果 PHP 以命令行方式运行,该变量无效。
    “argv”

    传递给该脚本的参数。当脚本运行在命令行方式时,argv 变量传递给程序 C 语言样式的命令行参数。当调用 GET 方法时,该变量包含请求的数据。
    “argc”

    包含传递给程序的命令行参数的个数(如果运行在命令行模式)。
    “GATEWAY_INTERFACE”

    服务器使用的 CGI 规范的版本。例如,“CGI/1.1”。
    'SERVER_NAME'

    当前运行脚本所在服务器主机的名称。如果该脚本运行在一个虚拟主机上,该名称是由那个虚拟主机所设置的值决定。
    'SERVER_SOFTWARE'

    服务器标识的字串,在响应请求时的头部中给出。
    “SERVER_PROTOCOL”

    请求页面时通信协议的名称和版本。例如,“HTTP/1.0”。
    “REQUEST_METHOD”

    访问页面时的请求方法。例如:“GET”、“HEAD”,“POST”,“PUT”。
    “QUERY_STRING”

    查询(query)的字符串。
    “DOCUMENT_ROOT”

    当前运行脚本所在的文档根目录。在服务器配置文件中定义。
    “HTTP_ACCEPT”

    当前请求的 Accept: 头部的内容。
    “HTTP_ACCEPT_CHARSET”

    当前请求的 Accept-Charset: 头部的内容。例如:“iso-8859-1,*,utf-8”。
    “HTTP_ACCEPT_ENCODING”

    当前请求的 Accept-Encoding: 头部的内容。例如:“gzip”。
    “HTTP_ACCEPT_LANGUAGE”

    当前请求的 Accept-Language: 头部的内容。例如:“en”。
    “HTTP_CONNECTION”

    当前请求的 Connection: 头部的内容。例如:“Keep-Alive”。
    “HTTP_HOST”

    当前请求的 Host: 头部的内容。
    “HTTP_REFERER”

    链接到当前页面的前一页面的 URL 地址。不是所有的用户代理(浏览器)都会设置这个变量,而且有的还可以手工修改 HTTP_REFERER。因此,这个变量不总是正确真实的。
    “HTTP_USER_AGENT”

    当前请求的 User_Agent: 头部的内容。该字符串表明了访问该页面的用户代理的信息。一个典型的例子是:Mozilla/4.5 [en] (X11; U; Linux 2.2.9 i586)。您也可以使用 get_browser() 得到这个信息。
    “REMOTE_ADDR”

    正在浏览当前页面用户的 IP 地址。
    'REMOTE_HOST'

    正在浏览当前页面用户的主机名。反向域名解析基于该用户的 REMOTE_ADDR。

    注: 必须配置 Web 服务器来建立此变量。例如 Apache 需要在 httpd.conf 中有 HostnameLookups On。参见 gethostbyaddr()。
    “REMOTE_PORT”

    用户连接到服务器时所使用的端口。
    “SCRIPT_FILENAME”

    当前执行脚本的绝对路径名。
    “SERVER_ADMIN”

    该值指明了 Apache 服务器配置文件中的 SERVER_ADMIN 参数。如果脚本运行在一个虚拟主机上,则该值是那个虚拟主机的值。
    “SERVER_PORT”

    服务器所使用的端口。默认为“80”。如果你使用 SSL 安全连接,则这个值为您所设置的 HTTP 端口。
    “SERVER_SIGNATURE”

    包含服务器版本和虚拟主机名的字符串。
    “PATH_TRANSLATED”

    当前脚本所在文件系统(不是文档根目录)的基本路径。这是在服务器进行虚拟到真实路径的映像后的结果。
    “SCRIPT_NAME”

    包含当前脚本的路径。这在页面需要指向自己时非常有用。
    “REQUEST_URI”

    访问此页面所需的 URI。例如,“/index.html”。
    “PHP_AUTH_USER”

    当 PHP 运行在 Apache 模块方式下,并且正在使用 HTTP 认证功能,这个变量便是用户输入的用户名。
    “PHP_AUTH_PW”

    当 PHP 运行在 Apache 模块方式下,并且正在使用 HTTP 认证功能,这个变量便是用户输入的密码。
    “AUTH_TYPE”

    当 PHP 运行在 Apache 模块方式下,并且正在使用 HTTP 认证功能,这个变量便是认证的类型。

    环境变量:$_ENV

    注: 在 PHP 4.1.0 及以后版本使用。之前的版本,使用 $HTTP_ENV_VARS。

    在解析器运行时,这些变量从环境变量转变为 PHP 全局变量名称空间(namespace)。它们中的许多都是由 PHP 所运行的系统决定。完整的列表是不可能的。请查看您系统的文档以确定其特定的环境变量。

    其它环境变量(包括 CGI 变量),无论 PHP 是以服务器模块或是以 CGI 处理方式运行,都在这里列出了。

    这是一个“superglobal”,或者可以描述为自动全局变量。这只不过意味这它在所有的脚本中都有效。在函数或方法中您不需要使用 global $_ENV; 来访问它,就如同使用 $HTTP_ENV_VARS 一样。

    $HTTP_ENV_VARS 包含着同样的信息,但是不是一个自动全局变量。(注意: HTTP_ENV_VARS 和 $_ENV 是不同的变量,PHP 处理它们的方式不同。)

    如果设置了 register_globals 指令,这些变量也在所有脚本中可用;也就是,分离了 $_ENV 和 $HTTP_ENV_VARS 数组。相关信息,请参阅安全的相关章节 使用 Register Globals。这些单独的全局变量不是自动全局变量。
    HTTP Cookies:$_COOKIE

    注: 在 PHP 4.1.0 及以后版本使用。之前的版本,使用 $HTTP_COOKIE_VARS。

    通过 HTTP cookies 传递的变量组成的数组。是自动全局变量。

    这是一个“superglobal”,或者可以描述为自动全局变量。这只不过意味这它在所有的脚本中都有效。在函数或方法中您不需要使用 global $_COOKIE; 来访问它,就如同使用 $HTTP_COOKIE_VARS 一样。

    $HTTP_COOKIE_VARS 包含着同样的信息,但是不是一个自动全局变量。(注意: HTTP_COOKIE_VARS 和 $_COOKIE 是不同的变量,PHP 处理它们的方式不同。)

    如果设置了 register_globals 指令,这些变量也在所有脚本中可用;也就是,分离了 $_COOKIE 和 $HTTP_COOKIE_VARS 数组。相关信息,请参阅安全的相关章节 使用 Register Globals。这些单独的全局变量不是自动全局变量。
    HTTP GET 变量:$_GET

    注: 在 PHP 4.1.0 及以后版本使用。之前的版本,使用 $HTTP_GET_VARS。

    通过 HTTP GET 方法传递的变量组成的数组。是自动全局变量。

    这是一个“superglobal”,或者可以描述为自动全局变量。这只不过意味这它在所有的脚本中都有效。在函数或方法中您不需要使用 global $_GET; 来访问它,就如同使用 $HTTP_GET_VARS 一样。

    $HTTP_GET_VARS 包含着同样的信息,但是不是一个自动全局变量。(注意: HTTP_GET_VARS 和 $_GET 是不同的变量,PHP 处理它们的方式不同。)

    如果设置了 register_globals 指令,这些变量也在所有脚本中可用;也就是,分离了 $_GET 和 $HTTP_GET_VARS 数组。相关信息,请参阅安全的相关章节 使用 Register Globals。这些单独的全局变量不是自动全局变量。
    HTTP POST 变量:$_POST

    注: 在 PHP 4.1.0 及以后版本使用。之前的版本,使用 $HTTP_POST_VARS。

    通过 HTTP POST 方法传递的变量组成的数组。是自动全局变量。

    这是一个“superglobal”,或者可以描述为自动全局变量。这只不过意味这它在所有的脚本中都有效。在函数或方法中您不需要使用 global $_POST; 来访问它,就如同使用 $HTTP_POST_VARS 一样。

    $HTTP_POST_VARS 包含着同样的信息,但是不是一个自动全局变量。(注意: HTTP_POST_VARS 和 $_POST 是不同的变量,PHP 处理它们的方式不同。)

    如果设置了 register_globals 指令,这些变量也在所有脚本中可用;也就是,分离了 $_POST 和 $HTTP_POST_VARS 数组。相关信息,请参阅安全的相关章节 使用 Register Globals。这些单独的全局变量不是自动全局变量。
    HTTP 文件上传变量:$_FILES

    注: 在 PHP 4.1.0 及以后版本使用。之前的版本,使用 $HTTP_POST_FILES。

    通过 HTTP POST 方法传递的已上传文件项目组成的数组。是自动全局变量。

    这是一个“superglobal”,或者可以描述为自动全局变量。这只不过意味这它在所有的脚本中都有效。在函数或方法中您不需要使用 global $_FILES; 来访问它,就如同使用 $HTTP_POST_FILES 一样。

    $HTTP_POST_FILES 包含着同样的信息,但是不是一个自动全局变量。

    如果设置了 register_globals 指令,这些变量也在所有脚本中可用;也就是,分离了 $_FILES 和 $HTTP_POST_FILES 数组。相关信息,请参阅安全的相关章节 使用 Register Globals。这些单独的全局变量不是自动全局变量。
    Request 变量:$_REQUEST

    注: 在 PHP 4.1.0 及以后版本使用。之前的版本,没有等价的数组。

    注: 在 PHP 4.3.0 之前,$_FILES 也被包括在 $_REQUEST 数组中。

    此关联数组包含 $_GET,$_POST 和 $_COOKIE 中的全部内容。

    这是一个“superglobal”,或者可以描述为自动全局变量。这只不过意味着它在所有的脚本中都有效。在函数或方法中您不需要使用 global $_REQUEST; 来访问它。

    如果设置了 register_globals 指令,这些变量也在所有脚本中可用;也就是,分离了 $_REQUEST 数组。相关信息,请参阅安全的相关章节 使用 Register Globals。这些单独的全局变量不是自动全局变量。
    Session 变量:$_SESSION

    注: 在 PHP 4.1.0 及以后版本使用。之前的版本,使用 $HTTP_SESSION_VARS。

    包含当前脚本中 session 变量的数组。参阅 Session 函数 文档以获得更多信息。

    这是一个“superglobal”,或者可以描述为自动全局变量。这只不过意味这它在所有的脚本中都有效。在函数或方法中您不需要使用 global $_SESSION; 来访问它,就如同使用 $HTTP_SESSION_VARS 一样。

    $HTTP_SESSION_VARS 包含着同样的信息,但是不是一个自动全局变量。

    如果设置了 register_globals 指令,这些变量也在所有脚本中可用;也就是,分离了 $_SESSION 和 $HTTP_SESSION_VARS 数组。相关信息,请参阅安全的相关章节 使用 Register Globals。这些单独的全局变量不是自动全局变量。
    Global 变量:$GLOBALS

    注: $GLOBALS 在 PHP 3.0.0 及以后版本中适用。

    由所有已定义全局变量组成的数组。变量名就是该数组的索引。

    这是一个“superglobal”,或者可以描述为自动全局变量。这只不过意味这它在所有的脚本中都有效。在函数或方法中您不需要使用 global $GLOBALS; 来访问它。
    前一个错误消息:$php_errormsg

    $php_errormsg 是包含 PHP 产生的上一错误消息内容的变量。该变量在发生错误并且track_errors 选项打开(默认为关闭)后才有效。

    September 06

    NCR编码:任意字符集下正常显示文字

    NCR编码:任意字符集下正常显示文字

    jimmy | 05 九月, 2006 22:16

    NCR(Numeric character reference) 。

    今天做xslt,意外留意到XSLTProcessor ->transformToDoc后输出的是NCR编码,觉得有必要提一下。其实就是把字符转Unicode,然后写成 &#x????; 其中,????是字符的十六进制。比如:泰拳

    有两个特例:

    1,ASC128以内的不用转。英文特权。

    2,16进制的0xFEFF不用转。这个是Unicode开头的标志。判断一个文件的格式是不是Unicode的,用十六进制模式看开头的两个字节,是FEFF那就是了。

    另外,意外的发现,NCR编码后字串,在Google中能够按解码后的进行搜索:)

    编码的函数:

    $str = iconv("GB2312", "UTF-16BE", $str);
    for ($i = 0; $i < strlen($str); $i++,$i++) {
    $code = ord($str{$i}) * 256 + ord($str{$i + 1});
    if ($code < 128) {
    $result .= chr($code);
    } else if ($code != 65279) {
    $result .= "&#".$code.";";
    }
    }


    如果想得到别的语言的编码,可以改变页面的字符集然后提交,ICONV改成相应的编码。其实最常用的就是国家名或者语言名。这个在新版的PhpMyAdmin里面就有现成的:

    ~~呵呵~~

    将xml+xslt输出为HTML格式

    将xml+xslt输出为HTML格式

    jimmy | 05 九月, 2006 21:16

    为兼容性考虑,有时候需要将XML转换为HTML格式输出。

    PHP需要XSLT相关函数支持。PHP4和PHP5有较大的变化:

    PHP4: --enable-xslt --with-xslt-sablot

    PHP5: --width-xsl

    安装PHP5系统需要 libxslt-devel, libgpg-error-devel, libgcrypt-devel

    参考编译选项:

    ./configure --prefix=/usr/local/php5.1 --with-mysql=/usr/local/mysql --with-iconv --with-apxs2=/usr/local/apache2/bin/apxs --with-zlib --with-xsl

    程序相对简单,

    <?
    $xml_file=$_GET[xml];
    $xslt_file=$_GET[xslt];
    $xml=new DOMDocument;
    $xml->load($xml_file);
    $xsl=new DOMDocument;
    $xsl->load($xslt_file);

    $proc = new XSLTProcessor;
    $proc->importStyleSheet($xsl);

    $content=$proc->transformToDoc($xml);
    $result=$content->saveXML();
    if ($result) {
    echo $result;
    } else {
    echo "Error: 转æ?¢xmlæ?°æ?®å?°HTMLæ?¶å?ºé??";
    }
    ?>

    如果是直接处理变量,用 DomDocument->loadXML($string)

    这里有一个需要注意的地方,根据PHP文档

    XSLTProcessor->transFromToDoc的范例,里面使用:

    echo trim($proc->transformToDoc($xml)->firstChild->wholeText();

    这个用法是有问题的。因为firstChild可能为空,会给调试带来很多困惑。


    一个有意思的附带结果是,输出内容被编码为NCR(Numeric character reference) 编码:

    爱好泰拳的美国性感小猫

    关于NCR编码,以后有时间会另文来介绍。

    ~~呵呵~~

    做缩略图的函数

    做缩略图的函数

    jimmy | 04 九月, 2006 14:47

    改一个别组的产品,里面还在用PHPImage的函数,改成用ImageMagick的。

    用的是以前写的lz_thumb基本代码。


    <code>

    function makesmallpic($image_name,$thumb_name,$thumb_width,$thumb_height) {
    if(!$image_info=getimagesize($image_name)){
    showerr("å?¾è±¡æ ¼å¼?é??误ï¼?");
    exit;
    }
    switch(trim($image_info[mime])){
    case 'image/jpeg': $file_ext=".jpg";break;
    case 'image/gif': $file_ext=".gif";break;
    case 'image/png': $file_ext=".png";break;
    default: $fill_ext=".jpg";
    }

    $image_rate=$image_info[0]/$image_info[1];
    $thumb_name="$thumb_path/".md5($image_src).$file_ext;
    $quality=100;
    $thumb_rate=$thumb_width/$thumb_height;
    if($image_rate >= $thumb_rate){

    $cmd="/usr/bin/convert {$image_name} -resize x{$thumb_height} -crop {$thumb_width}x{$thumb_height}+0+0 -quality {$quality} -sharpen 20 {$thumb_name}";
    echo `$cmd`;
    }else{

    $cmd="/usr/bin/convert {$image_name} -resize {$thumb_width}x -crop {$thumb_width}x{$thumb_height}+0+0 -quality {$quality} -sharpen 20 {$thumb_name}";
    echo `$cmd`;
    }
    }

    </code>

    如何用JS获取Cookie的domain和path?

    如何用JS获取Cookie的domain和path?

    jimmy | 01 九月, 2006 21:27

    基于HTTP1.1协议,JS和PHP对Cookie的封装都很简易,基本上是拿来就用。

    但是,在复杂应用中常常遇到这样的困惑: 为什么有的时候删除了Cookie但是值还存在?常常是因为Cookie的Domain和Path造成的。但是PHP和JS并没有提供直接的方法来判断读取到的cookie是属于哪个域名和路径。

    这里提供一个思路。架设当前域名和路经是: domain3.dumain2.domain1.com/path1/path2

    1,保存当前Cookie值。

    2,setcookie(cookiename,'',-100,'/path1/path2','domain3.domain2.domain1.com');

    3,再次加载读取Cookie,如果Cookie存在,说明不是/path1/path2与domain3.domain2.domain1.com下的Cookie值。

    4,尝试 /path1/path2 + domain2.domain1.com

    以后依次尝试 /path1 , / , domain1.com ... 的不同组合,直至找到该Cookie。则当前的路径和域名就是该Cookie的路径和域名。

    5,最后恢复原始cookie值。

    另一个启示是,如果需要确切删除一个Cookie值时,将所有路径与域名的组合都进行一遍setcookie,才能确保Cookie被清除。

    ~~呵呵~~

    Lucene- zend search- 笔记3

    Lucene- zend search- 笔记3

    jimmy | 24 八月, 2006 21:53

    从Zend.com下载 ZendFramework-0.1.5.tar.gz ,解压。

    实例:将数据库内容进行索引

    <?
    include("include/config.inc.php");
    require_once('Zend/Search/Lucene.php');
    $q=new DB_test;


    if($step==2){
    $index = new Zend_Search_Lucene('/opt/htdocs/search/test-index', true);
    $doc = new Zend_Search_Lucene_Document();
    $counter=0;
    $q->query("SELECT * FROM club_sort");
    while($tmpinfo=$q->next_record()){
    if($counter>100){$counter=0;echo ".";
    $index->commit();
    }
    else $counter++;
    $doc->addField(Zend_Search_Lucene_Field::Text('title', $tmpinfo[name]));
    $doc->addField(Zend_Search_Lucene_Field::Keyword('jimmyid', $tmpinfo[id]));
    $doc->addField(Zend_Search_Lucene_Field::UnStored('contents', iconv("GB2312","UTF-8",$tmpinfo[lastpost])));
    $index->addDocument($doc);
    }
    $index->commit();
    }
    if($step==1 && $keyword){
    echo "


    $keyword
    ";
    $index = new Zend_Search_Lucene('/opt/htdocs/search/test-index');
    $query = new Zend_Search_Lucene_Search_Query_MultiTerm();
    $query->addTerm(new Zend_Search_Lucene_Index_Term($keyword), null);

    $hits = $index->find($query);
    foreach ($hits as $hit) {
    echo $counter++;echo "


    ";
    $document = $hit->getDocument();
    print_r($document);
    }
    }
    ?>
    "Content-Type" content="text/html; charset=utf-8">

    1>


    E文搜索正确,中文不正常。

    根据ZF的手册,Zend-search工作在UTF-8下。但是实测中,将数据进行了UTF-8编码后,仍然不能正常搜索中文。

    留个疑问,有时间了来解决这个问题。Zend-search还在不断改进,应该后续版本对编码的兼容性有更好的解决。

    ~~呵呵~~

    Lucene- zend search- 笔记2

    Lucene- zend search- 笔记2

    jimmy | 23 八月, 2006 21:37

    Lucene的安装:

    从Sun.com下载 jdk-1_5_0_08-linux-i586-rpm.bin

    chmod +x jdk-1_5_0_08-linux-i586-rpm.bin

    ./jdk-1_5_0_08-linux-i586-rpm.bin

    Redhat默认的Java解释器为gcj:

    lrwxrwxrwx 1 root root 22 Jun 6 00:49 /usr/bin/java -> /etc/alternatives/java

    lrwxrwxrwx 1 root root 35 Jun 6 00:49 java -> /usr/lib/jvm/jre-1.4.2-gcj/bin/java

    需要修改成新安装的JDK:

    cd /etc/alternatives

    mv java java.old

    ln -s /usr/java/jdk1.5.0_08/bin/java java

    成为这个样子:

    lrwxrwxrwx 1 root root 30 Sep 4 10:47 java -> /usr/java/jdk1.5.0_08/bin/java

    然后,从apache.org下载lucene:

    lucene-2.0.0.tar.gz

    安装过程:

    tar -xzvf lucene-2.0.0.tar.gz

    mv lucene-2.0.0 /usr/local

    CLASSPATH=/usr/local/lucene-2.0.0/lucene-core-2.0.0.jar:/usr/local/lucene-2.0.0/lucene-demos-2.0.0.jar

    export CLASSPATH

    OK。然后可以测试了:

    java org.apache.lucene.demo.IndexFiles /usr/local/apache2/htdocs/

    java org.apache.lucene.demo.SearchFiles

    提示你输入一个检索的字串,输入后显示出结果。

    安装OK。

    ~~呵呵~~

    Lucene- zend search- 笔记1

    Lucene- zend search- 笔记1

    jimmy | 22 八月, 2006 15:34

    常用的三种索引:

    $doc = new Zend_Search_Lucene_Document();

    $doc->addField(Zend_Search_Lucene_Field::Keyword('doctype',
    'autogenerated'));

    $doc->addField(Zend_Search_Lucene_Field::Text('annotation',
    'Document annotation text'));

    $doc->addField(Zend_Search_Lucene_Field::UnStored('contents',
    'My document content'));

    Keyword: 关键字,不分词的。比如,日期,ID

    Text:短文本。比如:标题,URL,Nickname

    UnStored:大文本,仅索引,不存储。比如:正文。

    注意:

    1,创建索引时,

    <code>

    $index = new Zend_Search_Lucene('/data/my-index', true);

    $index = new Zend_Search_Lucene('/data/my-index');
    </code>

    第一个为新建,第二个为打开。

    2,

    <code>$index->commit()</code> 的使用频率。控制在4M所有索引数据时进行一次提交比较合适。

    令人感动的团队

    令人感动的团队

    jimmy | 14 八月, 2006 11:33

    昨天是周日,下午来到公司看到的一幕令我非常感动。

    安安静静的公司,走到社区的工位,却是热闹非凡,简直让人有种错觉:这是不是休息日?技术的同学在,运营的同学在,旅游的同学也在。因为十二层施工,旅游加班的同学下来借机器用,把社区挤的满满的,我都不得不另找其它位置坐。

    大亮,唐唐,薛延超,橘子,小溪,宋扬,巍巍…… 这些都是加班的常客了。令我惊奇的是,晶晶也在。晶晶住的非常远,要公交地铁城铁才能到公司,路上要近两个小时。没有人要求,都是凭着对工作的责任心,凭着对社区团队的责任心,尽自己的努力去把工作做好。我没有说什么,但是感动一直在我心里。尤其是晶晶,如果我提前知道,一定不会让她这么远赶过来,哪怕是推后任务的期限,哪怕是我来替她分担些。

    晚上回家的路上,我在回忆初来社区的时候。周六周日,社区的工位上只有指定值班的一个运营人员。而我们旁边,新闻频道,娱乐频道,都是有很多人。社区夹在中间,空空的静静的。而现在,整个11层,只有社区这里是热闹的,大家不是沉闷的而是充满活力的在工作着。

    我并不是迷信加班文化,我感动是因为从中看到大家的责任心,看到大家的团队精神。强令别人加班,其实是很容易的事情,效果通常也不会太好。然而,当一个团队的成员能够积极主动的来做,而且愉快的来做的时候,那就是完全的不同了。

    曾经走过很多艰苦的经历,曾经为这个团队付出过很多,在这一刻能够感觉到,一切都是值得。

    我为在这样一个团队中而开心,也坚信这个团队会带给每个成员更多的自豪。

    September 05

    很久没有更新了,去了趟丽江

    很久没有更新了,去了趟丽江

    jimmy | 12 八月, 2006 09:53

    一直是非常想去的地方,也是“一辈子必需要去过的地方”。

    确实很美,包括周边的旅游景区。到了那里以后,才发现居然那么多著名的景点都只是几个小时的路程而已:虎跳峡、长江第一湾、香各里拉、泸沽湖、玉龙雪山、大理、哈巴雪山……奇怪为什么优美的地方都抓堆呢?

    没有去很多地方,主要时间都是在一个叫束河的小城里面。很安静,节奏很慢,感觉很舒服。


    几张小城的照片。

    JS中escape方法在PHP中的实现

    JS中escape方法在PHP中的实现

    jimmy | 27 七月, 2006 10:49

    使用Ajax,用escape对字符进行编码是较为轻松的一种方式。

    但是escape与PHP提供的url/utf编码,并不能很好对应,需要自己写一个函数来处理。

    非常奇怪的是,很简单的一个函数,网上能找到很多,但是居然没有一个没有BUG的?换了两个版本后,觉得很失望,自己写吧。

    参考了其他版本,在正则上进行了一些调整。

    很多机器并没有装Iconv的,这个是个问题。或许有时间了会再写一个GB USC2之间的转码函数,就不用Iconv了。

    ~~呵呵~~


    <code>

    function unescape($str) {
    $str = urldecode($str);
    preg_match_all("/(?:%u.{4}|&#x.;|&#d+;|.+)/U",$str,$r);
    $ar = $r[0];
    foreach($ar as $k=>$v) {
    if(substr($v,0,2) == "%u")
    $ar[$k] = iconv("UCS-2","GB2312",pack("H4",substr($v,-4)));
    elseif(substr($v,0,3) == "&#x")
    $ar[$k] = iconv("UCS-2","GB2312",pack("H4",substr($v,3,-1)));
    elseif(substr($v,0,2) == "&#") {
    $ar[$k] = iconv("UCS-2","GB2312",pack("n",substr($v,2,-1)));
    }
    }
    return join("",$ar);
    }

    function escape($str) {
    preg_match_all("/[x80-xff].|[x01-x7f]+/",$str,$r);
    $ar = $r[0];
    foreach($ar as $k=>$v) {
    if(ord($v[0]) < 128)
    $ar[$k] = rawurlencode($v);
    else
    $ar[$k] = "%u".bin2hex(iconv("GB2312","UCS-2",$v));
    }
    return join("",$ar);
    }

    </code>

    JSON.PHP对中文乱码的解决

    JSON.PHP对中文乱码的解决

    jimmy | 27 七月, 2006 09:54

    传递GB2312时候,发现有丢失内容情况,还会有乱码。

    查看源代码,发现JSON试图将非ASCII字符转成UTF16格式,而处理过程中并未对GB有特殊处理,所以会导致错误。

    分析了Json.js,在Script这一层上,Json并未对中文进行特殊编码处理。为何在PHP中要多此一举呢? 大概是为了跨平台传输的原因。

    解决方法三个:

    1,写一个GB2UTF16函数放进去。

    2,采用其他编码作为中介。比如:nbase64

    3,干脆不做处理。这个最简单。

    根据需求,后台与前端均采用GB,UTF转码并无意义。动手改就很容易了。


    decode函数中,找到:

    case 'string':

    将处理编码的地方全去掉:

    case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
    // characters U-00000000 - U-0000007F (same as ASCII)
    $ascii .= $var{$c};
    break;

    case (($ord_var_c & 0xE0) == 0xC0):
    // characters U-00000080 - U-000007FF, mask 110XXXXX
    // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
    $char = pack('C*', $ord_var_c, ord($var{$c + 1}));
    $c += 1;
    $utf16 = $this->utf82utf16($char);
    $ascii .= sprintf('u%04s', bin2hex($utf16));
    break;

    case (($ord_var_c & 0xF0) == 0xE0):
    // characters U-00000800 - U-0000FFFF, mask 1110XXXX
    // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
    $char = pack('C*', $ord_var_c,
    ord($var{$c + 1}),
    ord($var{$c + 2}));
    $c += 2;
    $utf16 = $this->utf82utf16($char);
    $ascii .= sprintf('u%04s', bin2hex($utf16));
    break;

    case (($ord_var_c & 0xF8) == 0xF0):
    // characters U-00010000 - U-001FFFFF, mask 11110XXX
    // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
    $char = pack('C*', $ord_var_c,
    ord($var{$c + 1}),
    ord($var{$c + 2}),
    ord($var{$c + 3}));
    $c += 3;
    $utf16 = $this->utf82utf16($char);
    $ascii .= sprintf('u%04s', bin2hex($utf16));
    break;

    case (($ord_var_c & 0xFC) == 0xF8):
    // characters U-00200000 - U-03FFFFFF, mask 111110XX
    // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
    $char = pack('C*', $ord_var_c,
    ord($var{$c + 1}),
    ord($var{$c + 2}),
    ord($var{$c + 3}),
    ord($var{$c + 4}));
    $c += 4;
    $utf16 = $this->utf82utf16($char);
    $ascii .= sprintf('u%04s', bin2hex($utf16));
    break;

    case (($ord_var_c & 0xFE) == 0xFC):
    // characters U-04000000 - U-7FFFFFFF, mask 1111110X
    // see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
    $char = pack('C*', $ord_var_c,
    ord($var{$c + 1}),
    ord($var{$c + 2}),
    ord($var{$c + 3}),
    ord($var{$c + 4}),
    ord($var{$c + 5}));
    $c += 5;
    $utf16 = $this->utf82utf16($char);
    $ascii .= sprintf('u%04s', bin2hex($utf16));
    break;

    然后加上:

    default:
    $ascii .=chr($ord_var_c);
    break;

    测试OK。

    encode函数中也是一样,把编码的部分去掉,换上

    default: $utf8 .= chr($ord_chrs_c);

    ~~呵呵~~