字符串编码转换小结2

| | 评论(0)
 今天早上,网页忽然正常显示了,原来是修改了注册表的原因。
 在数据库迁移后(sql server :gbk2312 到 Oracle : UTF8),可能出现页面字符乱码的原因:

1.oracle字符集设置不正确。

数据库服务器字符集select * from nls_database_parameters,其来源于props$,是表示数据库的字符集。
客户端字符集环境select * from nls_instance_parameters,其来源于v$parameter,表示客户端的字符集的设置。
可能是参数文件,环境变量或者是注册表会话字符集环境select * from nls_session_parameters,
其来源于v$nls_parameters,表示会话自己的设置,可能是会话的环境变量或者是alter session完成,
如果会话没有特殊的设置,将与nls_instance_parameters一致。

客户端的字符集要求与服务器一致,才能正确显示数据库的非Ascii字符。如果多个设置存在的时候,
alter session>环境变量>注册表>参数文件字符集要求一致,但是语言设置却可以不同,语言设置建议用英文。
如字符集是zhs16gbk,则nls_lang可以是American_America.zhs16gbk;如果字符集是utf8,则要改成
SIMPLIFIED CHINESE_CHINA.AL32UTF8。
(即hkey_local_machine => software => oracle =>NLS_LANG改为SIMPLIFIED CHINESE_CHINA.AL32UTF8)


2.迁移过程中字符编码转换不正确,如何转换编码可参照总结1。
在php中,可以使用mb_string 的mb_detect_encoding来检测字符串是什么编码。

3.脚本代码要另存为utf8格式。

4.页面的header 要设置为utf8。

 

介绍一个自动完成的js类库autocomplete

| | 评论(0)
下载地址:http://createwebapp.com/
文档地址:http://createwebapp.com/autocomplete 文档非常详细。
 需要注意的一点是
<script>
    new Autocomplete("consumerName", function() {
       
        return "consumers.php?q=" + this.value;
    });
</script>
这段js要写在

<form>
    <input type="hidden" name="consumerID" id="consumerID"/>
    <input type="text" name="consumerName"/>
</form>

之后。
截图如下: autocomplete.jpg

字符串编码转换小结1

| | 评论(0)
 基础:

中文编码基础知识介绍(理论基础)

Java 编程技术中汉字问题的分析及解决

String.getBytes()方法中的中文编码问题 (这篇最为简单易懂且结合实际)

Unicode和UTF-8之间的转换详解

附录:

unicode编码表

GBK 汉字内码扩展规范编码表(二)

代码示例:

public String changeCharset(String str)
            throws UnsupportedEncodingException {
        if (str != null) {
           //得到gbk编码的字节串
             byte[] bs = str.getBytes("GBK");
             System.out.println("gbk:");          
             System.out.println("hex format is:"+encodeHex(bs));
          //得到utf8编码的字节串 
             byte[] ns = str.getBytes("UTF-8");
             System.out.println("utf8:");         
             System.out.println("hex format is:"+encodeHex(ns));
             System.out.println("Bin format is:"+encodeBin(ns)
                );
         //将编码为utf8的字节串再生成新的字符串,然后解码,看看转换过程中是否出错
             String newutf=new String(ns,"UTF-8");
             System.out.println("convert back from utf8:"+encodeHex(newutf.getBytes("UTF-8")));
             return newutf;
}

public static final String encodeHex (byte[] bytes)
    {
        StringBuffer buff =
        new StringBuffer(bytes.length * 2);
        String b;
        for (int i=0; i<bytes.length ; i++)
        {
            b = Integer.toHexString(bytes[i]); 
            // byte是两个字节的, 而上面的Integer.toHexString会把字节扩展为4个字节
            buff.append(b.length() > 2 ? b.substring(6,8) : b); 
            buff.append(" ");
        }
        return buff.toString();
    }
public static final String encodeBin (byte[] bytes)
    {
        StringBuffer buff =
        new StringBuffer(bytes.length * 2);
        String b;
        for (int i=0; i<bytes.length ; i++)
        {
            b = Integer.toBinaryString(bytes[i]); 
            // byte是两个字节的, 而上面的Integer.toHexString会把字节扩展为4个字节
            buff.append(b.substring(24,b.length())); 
            buff.append(" ");
        }
        return buff.toString();
    }

在Java中,String.getBytes("GBK")获得的是gbk编码的字节串,打印出来之后得到的是对应编码的十进制值,转换成16进制后就和编码表中的值一样了。
最后可以根据输出的二进制编码,和unicode表对比。

示例:
str: 中国
gbk:
hex format is:d6 d0 b9 fa
utf8:
hex format is:e4 b8 ad e5 9b bd
Bin format is:11100100 10111000 10101101 11100101 10011011 10111101
convert back from utf8:e4 b8 ad e5 9b bd
其中,“中”的unicode编码是4e2d,二进制表示为0100 1110 0010 1101,从低位到高位按六位截取及补齐高位后就可以得到11100100 10111000 1010110 ,即为utf8编码。


深居简出的生活

| | 评论(2)
 yiding:昨天中午吃的那家味道不错,不过有点贵,而且只适合两个人同吃,因为分量较小
 bear:在哪里啊?
 yiding:在禾祥西,快到小肥羊的地方
 bear:嗯。。。太远。。-_-

 bear:你的香水很好闻耶,哪买的?
 nancy: 中山路。。
 bear:哇,好远。。

 虫:来我家吃饭啊
 bear: 湖里太远。。

 小猫:饿了,我要猫粮。。
 bear:乖,新华都猫粮卖完了,你自己坐车去城达吃好不好



随感

| | 评论(0)
看了某个朋友的blog,立刻很羞愧,觉得自己正是他所说的浮躁的那种人。
最近在想,为什么都没做出点什么东西来,我想主要是缺乏钻研的精神吧。
一直以来,就像蜻蜓点水一样,什么都学一点,但是什么都不明白,要问原理,就说不出一二。埋在自己的小圈子里久了,都看不到世界变成什么样子了。最近有个学习的机会,但愿可以抓住,然后静静的学习。
有点恒心,有点毅力,想想自己究竟想做什么样的人。

2007回顾

| | 评论(6)
1月:写网页连通测试,学习Java多线程,遗憾的是学习的不够透彻,现在如果不再把书翻出来看看的话,估计想不起来怎么做了。

2月:回家

3月:修改汇文系统,不过汇文在6月份的时候又推出了新版,所以我们改的基本上都作废了。

4月:写tag应用,还好这个还继续用的上,虽然也花了一点时间把它加在汇文新版上。借此机会,学习了一下ajax。值得一提的是,Lib2.0会议在厦门召开,乘机见了不少大牛、帅哥和美女,也有了很多启发。

5月:继续改汇文部分应用,略微了解了一点smarty的应用。并且开始了解OPAC。

6月:开始考虑Mylibrary。好像我们翻译的书这个月出版了,小小自夸一下,虽然其实我也没有从中学到什么东西,而且稿费还上交了。(继续想念我的稿费,我连是多少都忘了。。-_-)

7月:放假,翻译某本书,不过后来没出版。

8月:去桂林参加数字图书馆2007研讨班。记了一些笔记,想了一些应用。

 9月:开始奔波,那个啥啥啥也是要见公婆的。。。

10月:好心痛机票钱,国庆回家真贵。
 
11月:继续写Mylibrary,还有opac部分改写。。因为我们系统升级了。。-_-

12月:继续写Mylibrary,继续学习ZendFramework。有几天了解了一下书目推荐,刚开始学习一个开源软件taste时,老大发话继续写Mylibrary,开始把学科导航整合到Mylibrary。
 
————————花絮分割线————————

代码花絮:
 
MyLibrary的痛苦编写经历:
6月,小成。不过是基于mysql的。
9月,把汇文的大部分mylibrary功能写进mylibrary,不过后来弃用。因为汇文写的更好,如果我们自己写,需要一段时间来完善和改善用户体验。
10月,11月,改写成oracle的,zf虽然不错,但是在插入数据库上,mysql和oracle有很大不同。
12月,没有灵感,压榨sogg小成,改投书目推荐2星期。之后再继续回来拥抱Mylibrary,可以初步导入del的收藏,具体完善打算压榨代码小机器人。

汇文修改:
A:“为什么汇文续借要这么麻烦?”
B:"咋没记录转预约经手人?"
C:“Opac咋不能用了?”
D:"保存帐户时间能否长点?"
E:"....."
rtx自动答复:有事请联系小马哥先。

————工作花絮——————

工作小花絮:
某日,一群人在小黑屋里讨论,一小时内飞速搞定。原因有二:一小时后要去烧烤,哈哈;以充分的理由,飞速把任务推给不在场的人,比如可怜的sogg就是其中的受害者。

某日,网络收看上海Lib2.0会议,看完很high,中午吃饭的时候讨论了一堆,没有回去午睡,结果晚上想整理的时候,发现大部分都忘了。。。

————宿舍——————

宿舍:

一只羊去了深圳,虫打电话给她:“亲爱的羊羊,我们好想你”,太e了,完全不考虑旁人的感受。。
一只鸭子去了宁波,估计宁波有某个帅哥,不然这丫头咋一年都不回来。
值得大喜的一件事情,小鹿结婚了,可惜不能参加婚礼,郁闷的是咋不参加婚礼也要送礼金,哈哈。

——————伪装分割线——————

熊:

熊家在昆明买了套房子。

厦门这边新住进一只小浣,某天从一条街带回来的,哈哈,好喜欢它(某只旁白,你喜欢它还把它放在纸袋里,至今不给它洗澡=_=)。

楼下的小猫5月的时候跑到我家生了一窝小小猫,,两只小黄一只小白。如今小小猫已经长成小猫了,丢了一只小黄,另外两只长得不错,人见人爱,人见人夸:‘太胖了“。现在的小黄喜欢和小白腻在一起,不得不控诉的是,昨晚小黄找不到小白,吵了我一晚上,郁闷。小小的遗憾是,它们小时候我怕它们被人摸了长不大,没有乘机抱它们,而且还不许某人抱它们(某人对此一直很不满),好想回到5个月前可以蹂躏小小猫的时候。。。

小小蜜蜂出生了,哈哈,好可爱呢。sogg的小外甥很可爱,某人的小侄子也很可爱。基于青春的美丽pp动人,我相信小小青春也会很pp,哈哈,好想摸摸她/他的小脸,嗯,还想做她/他的干妈:P

2007年在(饭)团的光辉普照下,经历了无数次腐败的我茁壮成长了,革命的友谊也因此而建立,感谢大家。太e的话,现在说不出来,或许过了几年会可以说出口,嘿嘿。虽然心里默默感谢,不过不好意思说不出来,脸皮薄的人就这个缺点,唉。。(窃笑)

最后,小小的e一下,2007年某人越来越可爱,哈哈。



Zend Framework中对oracle数据库操作总结

| | 评论(0)
说明: 摘自ZF手册中文版
1.执行查询并返回结果
跳过废话
1.1 使用 Zend_Db_Adapter
 一旦你得到了一个Zend_Db_Adapter 实例, 你可以直接 执行sql语句进行查询. Zend_Db_Adapter 传送这些sql语 句到底层的PDO对象,由PDO对象组合并执行他们,在有查询结果的情况 下,返回一个PDOStatement对象以便对结果进行处理。

<?php

// 创建一个$db对象,然后查询数据库
// 使用完整的sql语句直接进行查询.
$sql = $db->quoteInto(
'SELECT * FROM example WHERE date > ?',
'2006-01-01'
);
$result = $db->query($sql);

// 使用PDOStatement对象$result将所有结果数据放到一个数组中
$rows = $result->fetchAll();

?>


或者使用fetch开头系列方法获得结果集:

对于每一种 fetch系列 的方法来说,你需 要传送一个select的sql语句;假如你在操作语句中使用指定的占位符,你也可以 传送一个绑定数据的数组对你的操作语句进行处理和替换。 Fetch系列 的方法包括:

  • fetchAll()

  • fetchAssoc()

  • fetchCol()

  • fetchOne()

  • fetchPairs()

  • fetchRow()


<?php

// 创建一个 $db对象, 然后...

// 取回结果集中所有字段的值,作为连续数组返回
$result = $db->fetchAll(
"SELECT * FROM round_table WHERE noble_title = :title",
array('title' => 'Sir')
);

// 取回结果集中所有字段的值,作为关联数组返回
// 第一个字段作为码
$result = $db->fetchAssoc(
"SELECT * FROM round_table WHERE noble_title = :title",
array('title' => 'Sir')
);

// 取回所有结果行的第一个字段名
$result = $db->fetchCol(
"SELECT first_name FROM round_table WHERE noble_title = :title",
array('title' => 'Sir')
);

// 只取回第一个字段值
$result = $db->fetchOne(
"SELECT COUNT(*) FROM round_table WHERE noble_title = :title",
array('title' => 'Sir')
);

// 取回一个相关数组,第一个字段值为码
// 第二个字段为值
$result = $db->fetchPairs(
"SELECT first_name, favorite_color FROM round_table WHERE noble_title = :title",
array('title' => 'Sir')
);

// 只取回结果集的第一行
$result = $db->fetchRow(
"SELECT * FROM round_table WHERE first_name = :name",
array('name' => 'Lancelot')
);



?>
1.2 使用Zend_Db_Select方法

使用Zend_Db_Select方法是一种不受数据库约束构建select的sql语句的工具 (ares注:用户可以使用该方法生成查询的sql语句,而不需要考虑各种数据 库sql语句的差别)。虽然该方法明显还不完善,但是的确为我们提供一种方 法,帮助我们在不同的后台数据库进行相同的查询工作。除此之外,它还可 以避免sql语句攻击。

创建一个zend_db_select实例最简单的方法就是使用zend_db_adapter::select()方法



<? php

//在model中取得连接,并进行相应数据库操作

$this->db = Zend_Registry::get('db');       

$select = $this->db->select();
$select->from('link_info', 'link_info.*')
               ->join('link_tag_collect', 'link_info.linkid=link_tag_collect.linkid')
               ->where('user_friend.userid=?',$userid)

               ->distinct(link_info.linkid)
               ->order('link_tag_collect.addtime DESC')
               -2007-12-18>limit(10,0);
$sql = $select->__toString();
       
$result = $this->db->fetchALL($sql);

?>

1.3 使用 Zend_Db_Table
Zend_Db_Table 是Zend Framework的表模块.它通过zend_db_adapter连接到数据库,为数据库模式检查表对象,
并对该表进行操作和查询.
<?php
class RoundTable extends Zend_Db_Table {}

$table = new RoundTable();
$db = $table->getAdapter();

// SELECT * FROM round_table
// WHERE noble_title = "Sir"
// ORDER BY first_name
// LIMIT 10 OFFSET 20

$where = $db->quoteInto('noble_title = ?', 'Sir');
$order = 'first_name';
$count = 10;
$offset = 20;

$rowset = $table->fetchAll($where, $order, $count, $offset);
?>

以上都为废话,从ZF手册中皆能得到。

  • 从model中获得数据库连接,然后使用ZEND_DB_SELECT。
在tag.php中

<?php
 public function getTopTag(){
       
        $select = $this->db->select();
        $select->from($this->_name, '*')
               ->order('TAGTOTAL DESC')
               ->limit(10,0);
             

        $sql = $select->__toString();
        $result = $this->db->fetchALL($sql);
        return $result;
    }
?>

在TagController.php中
<?php
class TagController extends Zend_Controller_Action
private $tag;
function init() {
parent::init();
Zend_Loader::loadClass('Tag');
$this->tag = new Tag();
}
function topAction(){
$thi->tag->getTopTag();
...
}
?>

  • 使用ZEND_DB_TABLE
在Tag.php中

<?php
class Tag extends Zend_Db_Table
{
protected $_name = "TAG_INFO";
protected $_primary = 'TAGID';
}
?>
在TagController.php中
<?php
class TagController extends Zend_Controller_Action
private $tag;
function init() {
parent::init();
Zend_Loader::loadClass('Tag');
$this->tag = new Tag();
}
function topAction(){
$order = 'TAGTOTAL';
$count = 10;
$offset = 0;
  $thi->tag->fetchAll( $order, $count, $offset);
...
}
?>

最好还是选用方法一,能够将对数据的操作都封装在model中。
2.插入数据
无论是DB还是Table类,都使用insert()方法。
对于Oracle来说,如果要使用sequence作为自增的主键的话,需要使用trigger。
比如,有tag表,主键为tagid,其对应的sequence为tag_seq,要插入数据时,需要先新建trigger:

create or replace trigger tag_tri
before insert on tag
for each row
declare
nextid number;
begin
IF :new.tagid IS NULL or :new.tagid=0 THEN
select tag_seq.nextval
into nextid
from sys.dual;
:new.tagid:=nextid;
end if;
end tag_tri;

其余部分和插入其它数据库相同
<?php
$table_name='TAG';
$row = array (
'TAGNAME' => $tagname,
'TAGTOTAL' => '1'
);
$this->db->insert($table_name,$row);
?>


3.更新数据
3.1直接执行update语句,参见文档。
3.2如果update语句中,有包含数据库的特殊关键字时,需要先将数据选出,然后再更新
<?php
$where = $this->db->quoteInto('tagname = ?',$tagname);
$rowset = $this->tag->fetchAll($where);
$count=$rowset->count();
$tag = $rowset->current();
if($count!=0){
$tagid=$tag->TAGID;
//tagtotal+1

$tag->TAGTOTAL ++; //应判断一下当前用户是否
$tag->save();
}
?>

4.删除数据
<?php
//删除已有的collect表中记录
// where条件语句
$where = $this->db->quoteInto('USERID = ?', $userid)
.$this->db->quoteInto('AND LINKID = ?', $linkid);

// 删除数据并得到影响的行数
$rows_affected = $this->collect->delete($where);
?>


总结完毕:
tips:
注意表名、字段名等的大小写!

《暗恋桃花源》

| | 评论(0)
轻轻的,风起,两片叶子在空中相遇; 眨眼风过,云散,叶落。

爱恋如水晶般透明,没有过去,没有将来,这世界只有我们,一切都停止了。 你的眼睛,像草尖上上的露珠,你的微笑,像雨后的彩虹,而你,是白色的山茶花。 走在路上,看昏黄的灯。这么巧,你从远方来,又那么巧,在此相遇。 不会在今天,也会在明天,不会在今年,也会在明年,总会相遇。 这么小的人儿偏偏就在眼前。

不需要华丽的背景,也不需要繁复的音乐。

ZF读取配置文件

| | 评论(0)

1.加载配置文件:
require_once 'Zend/Config/Ini.php';
$config['nestSeparator'] = ':';
$config = new Zend_Config_Ini('/path/to/config.ini', 'staging', $config);

另一种加载文件的方法
Zend_Loader::loadClass('AppController','../application/controllers'); //加载基本控制器
// 加载配置
$config= new Zend_Config_Ini('../application/config.ini', 'reader');

2.config.ini文件示例
[general]
db.adapter = PDO_Oci
db.config.username = cat
db.config.password = dog
db.config.dbname = rabbit

[reader]
reader.LIB_CODE_REDRSTS_CANCEL = 0
reader.LIB_CODE_REDRSTS_ENABLE = 1
reader.LIB_CODE_CERTSTS_CANCEL = 0

3.读取配置文件

$redr=$config->reader->redr_lose;

参考资料:http://www.phpeye.com/zf/zend.config.adapters.ini.html