www.kingmaxyang.cn

不能不说的秘密

Archive for the 'TechTech' Category

热议图吧

每一次漂亮的事件营销活动都有他的不可重现性,下一次你想抄他的时候,就已经不灵了。为什么呢?因为消费者只会对第一次打破常规的事件产生兴趣。因此他们成功的唯一相同之处就是,他们均是业界内第一次发生重大突破的行为。

图吧这次的突破有两个因素,缺一不可。第一是近乎真实的心理式的产品描述,让消费者强烈产生兴趣和共鸣。第二是突破性的超低定价。对于业内领先的“凯立德”、“高德”动辙过百的定价而言,6块钱让大部分人豪不犹豫就买了。一般人会这么想,如果他不好用,甚至我用不上,我只是损失了6元;但如果他好用,碰巧我又经常用,那我就赚了94元。(假设业内均价为100元)所以,实在是值。

对于我而言,我本来在手机导航领域,用Google Map就够了,我习惯了开车时自己盯着地图上的东南西北和软件建议的路线,而不是只靠听着并不聪明的机器完全指挥着我怎么行走。但Google Map有个不足的地方,就是一到了没有手机网络的地方就歇菜了。图吧刚好弥补了这一缺陷,而我前天试用了一下,也确实感觉可以。唯一麻烦的就是下载完基础地图后,占用了我手机1G多的储存空间,着实让我删了几个游戏才装得下。

下一步图吧会怎么走?我猜可能他们自己都未想好。低价占领市场后,获得口碑,再提价?还是发现利润曲线的驼峰就在0.99美元这个点上,索性就一直0.99下去了?我想这会把凯立德和高德一起逼下来的,这样可能会导致恶性低价竞争,不利于行业的发展的。对我个人意见,我认为百元的定价是太高了,大部分可有可无的人不会考虑,而6元又确实太低了一点,30-50是一个比较理想的区间。

今天再想找回两天前图吧那段“热泪盈眶”的程序员心声描述,发现他们改了。只好转向微博,寻找那张原图。共纪念之。

posted by kingmaxyang in Tech and have No Comments

从字体渲染看苹果与微软的文化差异

非常惭愧,我前天看「Joel谈软件」才知道,苹果和微软在字体渲染技术上的思路有本质上的不同。微软会将所有字体进行珊格化处理,而不惜字体位置产生的变化,这是为什么Windows的字体显示更明晰,更适合屏幕阅读;而苹果则以忠于原字体设计者为首要原则,屏幕上的苹果字体虽然有毛茸茸的感觉,但只要像素足够高会越接近出版物。这是为什么苹果会被誉为更适合设计师和出版业,因为它在屏幕上的表现更接近于真实的出版效果,而不是因为它漂亮。而Windows是会为了屏幕的阅读清晰效果而牺牲字体和原设计的接近度,这是为什么Windows下各种字体的差异不明显,然后Web开发只能用一种字体和一种字体大小(因为其他都不好看)的原因。

两种思路,没有对错,这是实用主义(微软)和理想主义(苹果)的分歧。在十年前,屏幕分辨率还很低的时候,微软这一招似乎更加让使用者受惠。但今天iPhone、iPad的Retina高分屏的普及,谁能不承认苹果拥有更佳的显示效果?

posted by kingmaxyang in Tech and have No Comments

神奇的PHP

PHP自带有get_object_vars函数,非常强大,可以将一个对象里的可见属性(Public)转换为数组。这个函数对于一些“历史遗留”的非面向对象程序的适应非常好。

但有一点非常苦恼的是,如果在类里面的代码调用这个get_object_vars,会将所有这个类里面所有可见的属性(包括了public、protected、private三种)都转换到数组,这是我不希望的。究其原因,应该是在类里面的可见度高了。如何解决这个问题?

今天搜索了一下,发现一个鬼佬写了一个强大而又精焊的方法内置在类里面,不由感慨“神奇的PHP”。非常好用,特此分享。

原文:http://www.vancelucas.com/blog/get-only-public-class-properties-for-current-class-in-php/

PHP provides two built-in functions to retrieve properties of a given class –get_object_vars and get_class_vars. Both these functions behave the same exact way, one taking an object as a variable and the other taking a string class name. The tricky thing about the two functions is that they behave differently depending on the call scope, returning all of the class variables available within the called scope. So if you call either function within the current class you need properties from, all properties are returned – public, protected, and private – because the current scope has access to them all. This makes seemingly simple things like returning all the public properties within the current class a bit of a pain if you want to keep the code inside the class itself.

The obvious solution is to use the functions from a different call scope, which means either moving the call outside the class to the implementation code (yuck), or creating a new function outside the class for it. A lot of suggestions in the PHP manual say to create a new function below the class definition and call it within the class (kind of a proxy function as a workaround), but that seems tacky. Luckily, PHP also provides another way to get a new call scope: anonymous functions (and closures as of PHP 5.3).

1
2
3
4
5
6
7
8
9
10
11
12
class BobUser
{
	public $name = 'bob';
	public $publicFlag = true;
	protected $internalFlag = true;

	public function getFields()
	{
		$getFields = create_function('$obj', 'return get_object_vars($obj);');
		return $getFields($this); // Returns only 'name' and 'publicFlag'
	}
}

We can also do this the PHP 5.3 way with a much nicer-looking closure:

1
2
3
4
5
6
7
8
9
class BobUser
{
	// ...
	public function getFields()
	{
		$getFields = function($obj) { return get_object_vars($obj); };
		return $getFields($this);
	}
}

 

posted by kingmaxyang in Tech and have No Comments

Ubuntu 10.04 Server Apache + SVN + SSL配置

Ubuntu 10.04 Server Apache + SVN + SSL配置
2010/12/10 14:08

一、安装准备(安装模块)

#sudo apt-get install apache2

#sudo apt-get install apache2-mpm-prefork

#sudo apt-get install apache2-utils

#sudo apt-get install libapache2-svn

#sudo apt-get install libapache2-mod-auth-pam(可选,用于PAM)

#sudo apt-get install libapache2-mod-auth-sys-group(可选,用于PAM)

#sudo apt-get install subversion

#sudo apt-get install subversion-tools

 

二、SVN配置

配置前说明:

我的Subversion文件仓库放在/home/svn,并且我的项目名称是简单的“myproject”。Subversion组名字是subversion

 

创建Subversion的组:

典型的情况下,您应该创建一个名为“Subversion”的组来拥有文件仓库所在的目录。

 

#sudo addgroup subversion

#sudo usermod -G subversion -a www-data

//subversion是组名,可自己定义,一般不需要更改

验证:

# cat /etc/group|grep subversion

subversion:x:1001:www-data,svnx

//你需要注销然后再登录以便您能够成为subversion组的一员

 

创建SVN库:

# cd /home

# sudo mkdir svn

#cd  svn

# sudo mkdir myproject

//此命令在svn目录下进行

# sudo chown -R root:subversion myproject

//此命令在svn目录下进行

# # sudo chmod -R g+rws myproject

//此命令在svn目录下进行

//赋予组成员对所有新加入文件仓库的文件拥有相应的权限

# sudo svnadmin create myproject  //此命令在svn目录下进行

 

可能的问题:

在后续Check in的时候遇到如下错误:

Can’t open ‘/home/svn/myproject/db/txn-current-lock’: Permission denied

解决方法:可以再次运行命令:

# sudo chown -R root:subversion myproject

 

三、Apache配置

先备份一下Apache2的配置文件:

sudo cp -R /etc/apache2 /etc/apache2_backup

 

通过WebDAV协议访问SVN文件仓库,您必须配置您的Apache 2 Web服务器。您必须加入下面的代码片段到您的/etc/apache2/mods-available/dav_svn.conf中:(加在文件最后面即可)

 

<Location /myproject>      //版本库名字,必须以/开始

DAV svn                    //不用改

SVNPath /home/svn/myproject //版本库路径

AuthType Basic

AuthName “myproject subversion repository”

AuthUserFile /etc/subversion/passwd   //密码文件路径。

<LimitExcept GET PROPFIND OPTIONS REPORT>

Require valid-user

</LimitExcept>

</Location>

 

特别说明:

1、如果需要用户每次登录时都进行用户密码验证,请将<LimitExcept GET PROPFIND OPTIONS REPORT>与</LimitExcept>两行注释掉。

2、当您添加了上面的内容,您必须重新起动Apache 2 Web服务器,请输入下面的命令:

#sudo /etc/init.d/apache2 restart

 

创建passwd 文件:

该文件包含了用户授权的详细信息。要添加用户,您可以执行下面的命令:

#sudo htpasswd -c /etc/subversion/passwd user_name

它会提示您输入密码,当您输入了密码,该用户就建立了。

 

最后,你就可以用客户端来访问了

http://主机IP/myproject

 

这样,就可以通过Web方式访问版本库了,不过这样的密码传输是纯文本方式的,基于安全方面的考虑,我建议你使用SSL。

四、SSL配置

Apache2已经在前面安装好了下面安装SSL模块:
安装SSL模块

#a2enmod ssl

 

我们可以使用openssl来创建,这里我就是此方法创建SSL证书的

#sudo cd /etc/apache2

#sudo mkdir ssl

#sudo cd ssl

#sudo openssl req -x509 -newkey rsa:1024 -keyout apache.pem -out apache.pem -nodes -days 999

 

注:在要求输入Common Name (eg, YOUR name)时,输入你的主机名。

示例过程如下:

Generating a 1024 bit RSA private key
…………………++++++
..++++++
writing new private key to ‘apache.pem’
—–
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter ‘.’, the field will be left blank.
—–
Country Name (2 letter code) [AU]:China
string is too long, it needs to be less than  2 bytes long
Country Name (2 letter code) [AU]:CN
State or Province Name (full name) [Some-State]:Jiangxi
Locality Name (eg, city) []:Nanchang
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Nanchang Unversity
Organizational Unit Name (eg, section) []:Information Center
Common Name (eg, YOUR name) []:LinuxServer
Email Address []:111@gmail.com

复制一份站点配置做为SSL配置的原型
#cp /etc/apache2/sites-available/default /etc/apache2/sites-available/ssl

#ln -s /etc/apache2/sites-available/ssl /etc/apache2/sites-enabled/ssl

编辑SSL的配置

#vi /etc/apache2/sites-enabled/ssl
把端口改为443
加入SSL认证配置
其它的根据需要自己定制与普通配置无异

<VirtualHost *:443>

ServerSignature On

SSLEngine On

SSLCertificateFile /etc/apache2/ssl/apache.pem

………………………

修改普通http方式的配置(apache2这里好像不用改,默认的已经是80端口)

编辑Apache端口配置,加入443端口(这里可以不用加“Listen 443”因为SSL默认认证的443端口已经打开)

 

别忘了把前面生成的SSL密钥文件拷贝过来

# sudo cp apache.pem  /proc/14646/cwd/apache.pem  //在apache.pem目录下

重启apache2

#/etc/init.d/apache2 restart

posted by kingmaxyang in Tech and have No Comments

服务器间大文件传输

转自:http://www.sar4.com/2010/11/21/Linux%E4%B8%8B%E5%A4%A7%E6%96%87%E4%BB%B6%E5%A4%8D%E5%88%B6.html

1,gzip+scp+gunzip
server1压缩并传送:

server1$ gzip -c /backup/mydb/mytable.MYD > mytable.MYD.gz
server1$ scp mytable.MYD.gz root@server2:/var/lib/myql/mydb/

server2解压:

server2$ gunzip /var/lib/mysql/mydb/mytable.MYD.gz

2,通道+ssh
server1压缩通过通道ssh传送到server2并在server2上解压

server1$ gzip -c /backup/mydb/mytable.MYD | ssh root@server2 "gunzip -c - > /var/lib/mysql/mydb/mytable.MYD"

3,通道+netcat
server2监听12345端口:

server2$ nc -l -p 12345 | tar xvzf -

server1传送数据:

server1$ tar cvzf - /var/lib/mysql/mydb/mytable.MYD | nc -q 1 server2 12345

4,rsync

server1$ rsync -ave ssh server2:/var/lib/mysql/mydb/ /home/mydb/

速度对比:
100 Mb/S Ethernet LAN.文件大小为738 MB可压缩至100 MB

Method 				Time (seconds)
rsync without compression 	71
scp without compression 	68
nc without compression 		67
rsync with compression (-z) 	63
gzip, scp, and gunzip 		60(44 + 10 + 6)
ssh with compression 		44
nc with compression 		42

 

posted by kingmaxyang in Tech and have No Comments

彻底搞清楚字符编码: ASCII, ISO_8859, GB2312,UCS, Unicode, UTF-8

第一部分:  字符集历史

电子计算机技术是从美国开始发展起来的,因为美国使用的文字为英文,美国规定的计算机信息交换用的字符编码集是人们熟知的扩展的ASCII码,它以8bit字节为单位存储,ASCII的0-31及127为控制符,32-126为可见字符,包括所有的英文字母,阿拉伯数字和其他一些常见符号,128-255的ASCII码则没有定义。

ASCII对英语国家是够用了,但对其他西欧国家却不够用,因此,人们将ASCII扩展到0-255的范围,形成了ISO-8859-1字符集。值得一提的是,因为考虑到程序中处理的信息大多是西文信息,因此有些WEB容器(如:Tomcat4.x)在处理所接收到的request字符串时,如果您没指定request的编码方式则系统就缺省地采用ISO-8859-1,明白这一点对理解后面的问题会有帮助。

相比西方的拼音文字,东方的文字(如中文)的字符数要大得多,根本不可能在一个字节内将它们表示出来,因此,它们以两个字节为单位存储,以中文国标字符集GB2312为例,它的第一个字节为128-255。系统可以据此判断,若第一个字节大于127,则把与该字节后紧接着的一个字节结合起来共两个字节组成一个中文字符。这种由多个字节存储一个字符的字符集叫多字节字符集(MultiByte Charsets),对应的象ASCII这种用一个字节存储一个字符的字符集叫单字节字符集(SingleByte Charsets)。在GB2312字符集中,ASCII字符仍然用一个字节存储,换句话说该ASCII是该字符集的子集。

GB2312只包含数千个常用汉字,往往不能满足实际需要,因此,人们对它进行扩展,这就有了我们现在广泛使用的GBK字符集,GBK是现阶段Windows及其他一些中文操作系统的缺省字符集。它包含2万多个字符,除了保持和GB2312兼容外,还包含繁体中文字,日文字符和朝鲜字符。值得注意的是GBK只是一个规范而不是国家标准,新的国家标准是GB18030-2000,它是比GBK包含字符更多的字符集。

我国的台湾地区使用的文字是繁体字,其字符集是BIG5,而日本采用的字符集则是SJIS。它们的编码方法与GB2312类似,它们的ASCII字符部分是兼容的,但扩展部分的编码则是不兼容的,比如这几种字符集中都有”中文”这两个字符,但他们在各自的字符集中的编码并不相同,这就是用GB2312写成的网页用BIG5浏览时,看到的是乱糟糟的信息的原因。

可见,在字符集的世界里,呈现给我们的是一个群雄割据的局面,各字符集拥有一块自己的地盘。这给各国和各地区交换信息带来了很大的困难,同时,也给国际化(本地化)编程造成了很大的麻烦。

常言道:”分久必合”,随着国际标准ISO10646定义的通用字符集(Universal Character Set即UCS)的出现,使这种局面发生了彻底的改观。UCS 是所有其他字符集标准的一个超集. 它保证与其他字符集是双向兼容的. 就是说, 如果你将任何文本字符串翻译到 UCS格式, 然后再翻译回原编码, 你不会丢失任何信息。UCS 包含了用于表达所有已知语言的字符。不仅包括拉丁语、希腊语、 斯拉夫语、希伯来语、阿拉伯语、亚美尼亚语和乔治亚语的描述、还包括中文、日文和韩文这样的象形文字、 以及平假名、片假名、 孟加拉语、 旁遮普语果鲁穆奇字符(Gurmukhi)、泰米尔语、印.埃纳德语(Kannada)、Malayalam、泰国语、 老挝语、 汉语拼音(Bopomofo)、Hangul、 Devangari、Gujarati、Oriya、Telugu 以及其他数也数不清的语。对于还没有加入的语言,由于正在研究怎样在计算机中最好地编码它们, 因而最终它们都将被加入。

ISO 10646 定义了一个 31 位的字符集。然而, 在这巨大的编码空间中, 迄今为止只分配了前 65534 个码位 (0×0000 到 0xFFFD)。 这个 UCS 的 16位子集称为基本多语言面 (Basic Multilingual Plane, BMP)。 将被编码在 16 位 BMP 以外的字符都属于非常特殊的字符(比如象形文字), 且只有专家在历史和科学领域里才会用到它们。

UCS 不仅给每个字符分配一个代码, 而且赋予了一个正式的名字。 表示一个 UCS 值的十六进制数, 通常在前面加上 “U+”, 就象 U+0041 代表字符”拉丁大写字母A”。 UCS 字符 U+0000 到 U+007F 与 US-ASCII(ISO 646) 是一致的, U+0000 到 U+00FF 与 ISO 8859-1(Latin-1) 也是一致的。这里要注意的是它是以16bit为单位存储,即便对字母”A”也是用16bit,这是与前面介绍的所有字符集不同的地方。

历史上,在国际标准化组织研究ISO10646标准的同时,另一个由多语言软件制造商组成的协会也在从事创立单一字符集的工作,这就是现在人们熟知的 Unicode。幸运的是,1991年前后ISO10646和Unicode的参与者都认识到,世界上不需要两个不同的单一字符集。他们合并双方的工作成果,并为创立单一编码表而协同工作。两个项目仍都存在并独立地公布各自的标准,都同意保持ISO10646和Unicode的码表兼容,并紧密地共同调整任何未来的扩展。这与当年在PC机上的操作系统MS-dos与PC-dos的情形有些相象。后面,我们将视ISO10646和Unicode为同一个东西。

有了Unicode,字符集问题接近了完美的解决,但不要高兴得过早。由于历史的原因:一些操作系统如:Unix、Linux等都是基于ASCII设计的。此外,还有一些数据库管理系统软件如:Oracle等也是围绕ASCII来设计的(从其8i的白皮书上介绍的设置系统字符集和字段的字符集中可以间接地看到这一点)。在这些系统中直接用Unicode会导致严重的问题。用这些编码的字符串会包含一些特殊的字符, 比如 ‘\0′ 或 ‘/’, 它们在 文件名和其他 C 库函数参数里都有特别的含义。 另外, 大多数使用 ASCII 文件的 UNIX 下的工具,如果不进行重大修改是无法读取 16 位的字符的。 基于这些原因, 在文件名, 文本文件, 环境变量等地方,直接使用Unicode是不合适的。

在 ISO 10646-1 Annex R 和 RFC 2279 里定义的 UTF-8 (Unicode Transformation Form 8-bit form)编码没有这些问题。

UTF-8 有以下一些特性:

UCS 字符 U+0000 到 U+007F (ASCII) 被编码为字节 0×00 到 0x7F (ASCII 兼容)。 这意味着只包含 7 位 ASCII 字符的文件在 ASCII 和 UTF-8 两种编码方式下是一样的。

所有 >U+007F 的 UCS 字符被编码为一个多个字节的串, 每个字节都有标记位集。 因此,ASCII 字节 (0×00-0x7F) 不可能作为任何其他字符的一部分。

表示非 ASCII 字符的多字节串的第一个字节总是在 0xC0 到 0xFD 的范围里, 并指出这个字符包含多少个字节。 多字节串的其余字节都在 0×80 到 0xBF 范围里。 这使得重新同步非常容易, 并使编码无国界,且很少受丢失字节的影响。

UTF-8 编码字符理论上可以最多到 6 个字节长, 然而 16 位 BMP 字符最多只用到 3 字节长。

字节 0xFE 和 0xFF 在 UTF-8 编码中从未用到。

通过,UTF-8这种形式,Unicode终于可以广泛的在各种情况下使用了.

第二部分: 从Unicode到UTF-8的转换

From: http://hi.baidu.com/winnyang/blog/item/d5fd4f3d7b1cbdc19e3d62aa.html

Unicode是一个字符集,而UTF-8是 Unicode的其中一种,Unicode是定长的都为双字节,而UTF-8是可变的,对于汉字来说Unicode占有的字节比UTF-8占用的字节少1 个字节。Unicode为双字节,而UTF-8中汉字占三个字节。
网魂小兵 http://xdotnet.cnblogs.com
UTF-8编码字符理论上可以最多到6个字节长,然而16位BMP(Basic Multilingual Plane)字符最多只用到3字节长。下面看一下UTF-8编码表:

U-00000000 – U-0000007F: 0xxxxxxx
U-00000080 – U-000007FF: 110xxxxx 10xxxxxx
U-00000800 – U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
U-00010000 – U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
U-00200000 – U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
U-04000000 – U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

xxx 的位置由字符编码数的二进制表示的位填入, 越靠右的 x 具有越少的特殊意义,只用最短的那个足够表达一个字符编码数的多字节串。注意在多字节串中, 第一个字节的开头”1″的数目就是整个串中字节的数目。而第一行中以0开头,是为了兼容ASCII编码,为一个字节,第二行就为双字节字符串,第三行为3 字节,如汉字就属于这种,以此类推。(个人认为:其实我们可以简单的把前面的1的个数看成字节数)
网魂小兵 http://xdotnet.cnblogs.com
为了要将Unicode转换为UTF-8,当然要知道他们的区别到底在什么地方。下面来看一下,在Unicode中的编码是怎样转换成UTF-8的,在UTF-8中,如果一个字符的字节小于0×80(128)则为ASCII字符,占一个字节,可以不用转换,因为UTF-8兼容ASCII编码。假如在Unicode中汉字“你”的编码为“u4F60”,把它转换为二进制为100111101100000,然后按照UTF-8的方法进行转换。可以将Unicode二进制从地位往高位取出二进制数字,每次取6位,如上述的二进制就可以分别取出为如下所示的格式,前面按格式填补,不足8位用0填补。

unicode: 100111101100000                  4F60 

utf-8:    11100100,10111101,10100000       E4BDA0

从上面就可以很直观的看出Unicode到UTF-8之间的转换,当然知道了UTF-8的格式后,就可以进行逆运算,就是按照格式把它在二进制中的相应位置上取出,然后在转换就是所得到的Unicode字符了(这个运算可以通过“位移”来完成)。
网魂小兵 http://xdotnet.cnblogs.com
如上述的“你”的转换,由于其值大于0×800小于0×10000,因此可以判断为三字节存储,则最高位需要向右移“12”位再根据三字节格式的最高位为 11100000(0xE0)求或(|)就可以得到最高位的值了。同理第二位则是右移“6”位,则还剩下最高位和第二位的二进制值,可以通过与 111111(0x3F)求按位于(&)操作,再和11000000(0×80)求或(|)。第三位就不用移位了,只要直接取最后六位(与 111111(ox3F)取&),在与11000000(0×80)求或(|)。OK了,转换成功!在VC++中的代码如下所示(Unicode到UTF-8的转换)。

1 const wchar_t pUnicode = L”你”;
2 char utf8[3+1];
3 memset(utf8,0,4);
4 utf8[0] = 0xE0|(pUnicode>>12);
5 utf8[1] = 0×80|((pUnicode>>6)&0x3F);
6 utf8[2] = 0×80|(pUnicode&0x3F);
7 utf8[3] = ”\0″;
8 //char[4]就是UTF-8的字符“你”了。

当然在UTF-8到Unicode的转换也是通过移位等来完成的,就是把UTF-8那些格式相应的位置的二进制数给揪出来。在上述例子中“你”为三个字节,因此要每个字节进行处理,有高位到低位进行处理。在UTF-8中“你”为11100100,10111101,10100000。从高位起即第一个字节11100100就是把其中的”0100″给取出来,这个很简单只要和11111(0x1F)取与(&),由三字节可以得知最到位肯定位于12位之前,因为每次取六位。所以还要将得到的结果左移12位,最高位也就这样完成了0100,000000,000000。而第二位则是要把“111101”给取出来,则只需将第二字节10111101 和111111(0x3F)取与(&)。在将所得到的结果左移6位与最高字节所得的结果取或(|),第二位就这样完成了,得到的结果为 0100,111101,000000。以此类推最后一位直接与111111(0x3F)取与(&),再与前面所得的结果取或(|)即可得到结果 0100,111101,100000。OK,转换成功!在VC++中的代码如下所示(UTF-8到Unicode的转换)。

1 const wchar_t pUnicode = L”你”;
2 char utf8[3+1];
3 memset(utf8,0,4);
4 utf8[0] = 0xE0|(pUnicode>>12);
5 utf8[1] = 0×80|((pUnicode>>6)&0x3F);
6 utf8[2] = 0×80|(pUnicode&0x3F);
7 utf8[3] = ”\0″;
8 //char[4]就是UTF-8的字符“你”了。

当然在UTF-8到Unicode的转换也是通过移位等来完成的,就是把UTF-8那些格式相应的位置的二进制数给揪出来。在上述例子中“你”为三个字节,因此要每个字节进行处理,有高位到低位进行处理。在UTF-8中“你”为11100100,10111101,10100000。从高位起即第一个字节11100100就是把其中的”0100″给取出来,这个很简单只要和11111(0x1F)取与(&),由三字节可以得知最到位肯定位于12位之前,因为每次取六位。所以还要将得到的结果左移12位,最高位也就这样完成了0100,000000,000000。而第二位则是要把“111101”给取出来,则只需将第二字节10111101 和111111(0x3F)取与(&)。在将所得到的结果左移6位与最高字节所得的结果取或(|),第二位就这样完成了,得到的结果为 0100,111101,000000。以此类推最后一位直接与111111(0x3F)取与(&),再与前面所得的结果取或(|)即可得到结果 0100,111101,100000。OK,转换成功!在VC++中的代码如下所示(UTF-8到Unicode的转换)。

1 //UTF-8格式的字符串
2 const char* utf8 = ”你”;
3 wchar_t unicode;
4 unicode = (utf8[0] & 0x1F) << 12;
5 unicode |= (utf8[1] & 0x3F) << 6;
6 unicode |= (utf8[2] & 0x3F);
7 //unicode is ok!

网魂小兵 http://xdotnet.cnblogs.com
当然在编程过程中不可能只转换一个字符,这里需要注意的是字符的长度一定要算清楚,不然会带来…以上就是我这几天研究的结果,至于Unicode的转换为GB2312在MFC中Windows有自带的API(WideCharToMultiByte)可以转换。这样也就能够将UTF-8格式转换为GB2312了,这里就不再赘述,如果大家有更好的方法希望指教。

 

posted by kingmaxyang in Tech and have No Comments

MySQL 数据库同步

本文为转载,转以备忘。

MySQL 的数据同步,在 MySQL 官方网站文档上,叫 Replication 字面是重作的意思,意译就是同步了。其实,MySQL 的同步,并不是使用同步 sync 这个单词而是用重作 replication,很准确表明了 MySQL 数据库操作的实质,是作同样的操作,或叫重作同样的操作,以保持主数据库服务器 master 与 从属服务器 slave 之样的数据保持一致。replication 就是有重复,重作的意思。

MySQL 为了实现 replication 必须打开 bin-log 项,也是打开二进制的 MySQL 日志记录选项。

MySQL 的 bin log 二进制日志,可以记录所有影响到数据库表中存储记录内容的 sql 操作,如 insert / update / delete 操作,而不记录 select 这样的操作。因此,我们可以通过二进制日志把某一时间段内丢失的数据可以恢复到数据库中(如果二进制日志中记录的日志项,包涵数据库表中所有数据,那么,就可以恢复本地数据库的全部数据了)。 而这个二进制日志,如果用作远程数据库恢复,那就是 replication 了。这就是使用 replication 而不用 sync 的原因。这也是为什么要设置 bin-log = 这个选项的原因。

在同步过程中,最重要的同步参照物,就是同步使用那一个二进制日志文件,从那一条记录开始同步。

下面,我们来讲解最核心的过程:

  1. 首先,你应该有两个或两个以上的 MySQL 数据库服务器,版本最好是在 3.3 以上 (当然,两个服务器不一定是两台机器,一台机器上安装两个 MySQL 服务是可以的,同时,如果你对 MySQL replication 原理十分精通的话,你甚至可以在一个 MySQL 服务的两个不同数据库 database 之间作同步,看有没有需要了)说明: 这两个服务器一般设置一个为主服务器,或叫源服务器, master mysql server, 另一台或其他多台就是 replication slave 同步从服务器了。一台 slave 与多台 slave 设置方法是一样的,这样你就可以作类似数据库集群了。
  2. 设置可访问 MySQL 帐号,操作以英文为准。
    • MySQL 帐号一般设置为限定 IP 访问,以保障安全性
    • MySQL 帐号一般在 master 与 slave 设置为相同帐号,同时是远程可访问
    • 特别注意,如果你用 Linux / Unix 操作系统,那一定要注意一下防火墙 firewall 有没有限制 MySQL 远程访问,如果是,最好是打开远程访问端口,并作好访问 IP 限制
    • 由于 my.cnf 中要明文存储 MySQL 帐号密码,请注意保护 my.cnf 不让其他用户访问到(看来要向 MySQL 说明下以后用密码存 passwd)。
  3. 第三步,当然是设置两个服务器要同步的数据库为同样的数据库了。
    • 方法之一,就是英文说明中说的,先锁定数据库读写功能 ( 其实最好是停止 mysqld 服务,再作备份) 然后用 tar 备份数据库目录,转到 slave 服务器相同数据目录中。
    • 方法之二,使用 mysql studio 这样的实用工具,直接使用 mysql studio 的 backup database 工具把数据库同步
    • 以上两种方法都是 master 数据库中有不少数据记录,按上两 种方法得到 master 与 slave 有相同数据库与数据记录。 而第三种方法,则是适合于新建数据库的情况,特别适合于 master 与 slave 在 my.cnf 已经设置好 replication 关系 (但 未指定 database 同步数据库 ) 的情况: 这就是使用 mysql 的 sql 语句 load table from master 与 load data from master;
      load table from master 可以从 master 数据库把表结构复制到 slave 数据库中,这样可以建立同步的表。
      load data from master 是从 master 数据库把数据导入到 slave 数据表中,条件是 master 从一开始安装运行就使用了 bin-log 参数而保存有二进制日志
  4. 这里有一些技巧,包括 mysql 的 sql 指令说明下。

  5. 接下来就是配置 master 与 slave 的 my.cnf 文件,使得 replcation 能有合适的启动参数以支持数据同步
  6. 技巧: 如果你使用 win2k 的 mysql 那么,你可以下载 mysql.com 出的官方 mysql administrator 实用程序,直接在 mysql administrator 中即可配置 master 与 slave ,同时也可以配置 query-cache 。

    在 master 的 my.cnf(如果是 win32 那就是 my.ini)增加

    [mysqld]
    log-bin =
    server-id=1

    注意,上面的 log-bin = 中的 等号 = 是不可少的。

    在 slave 的 my.cnf 修改

    [mysqld]
    server-id=2 # 如果有多个 slave 就改为不重复的 id 就好,在mysql 4.1 中,这个已经取消了
    master-host=10.10.10.22
    master-user=backup #同步用户帐号
    master-password=1234
    master-port=3306
    master-connect-retry=60 #预设重试间隔60秒
    replicate-do-db=test # 告诉slave只做 test 数据库的更新
    bin-log =

     

     

     

  7. 检查 master 与 slave 配置状态,使用 show master status; 与 show slave status; 这两个 SQL 指令即可在 master 与 slave 查看配置状态。这里有两个状态变量十分重要
    • master 与 slave 有相同的数据库表结构,最好 database name 也一样(可以设置为不一样的 database name)
    • master 与 slave 有相同的初始数据记录,保证同步操作开始后两者数据一致
    • master 必须使用 bin-log 二进制日志记录(推荐 slave 也使用 bin-log)
    • slave 是从 master 的 bin-log 是读取 sql 记录来同步,所以,从哪一条 log 开始读取很重要(下面的第 7 条操作,就是保证 slave 能与 master 保持相同的记录读取,并读取正确的 bin-log 日志文件)
  8. mysql > SHOW MASTER STATUS;
    +---------------+----------+--------------+------------------+
    | File   | Position | Binlog_Do_DB | Binlog_Ignore_DB |
    +---------------+----------+--------------+------------------+
    | mysql-bin.003 | 73  | test   | manual,mysql  |
    +---------------+----------+--------------+------------------+

    注意 File 是 mysql-bin.003 而 position 是 73

    这个文件是对 test 这个 数据库的二进制日志记录,记录数据变化的当前记录条数是 73

    前面我们说过,二进制日志记录着某个数据库所有数据记录变化的 sql 操作语句,如 insert / update / delete 等,正是因为如此,在 slave 同步 mysql 数据库操作时,其实是读取master 中这个 mysql-bin.003 二进制日志中的 sql 操作,同在 slave 中执行这些 sql 操作,所以,同步成功有以下几个条件:

  9. 在 slave 执行下面 sql 操作
  10. mysql> CHANGE MASTER TO
    ->  MASTER_HOST='master_host_name',
    ->  MASTER_USER='replication_user_name',
    ->  MASTER_PASSWORD='replication_password',
    ->  MASTER_LOG_FILE='recorded_log_file_name',
    ->  MASTER_LOG_POS=recorded_log_position;

    这里,把 上面的 redcorded_log_file_name 改为 mysql-bin.003 而 recorded_log_position 改为 73 (特别注意,这是关系关键)。

linux 下的 mysql 与 win2k 下的 MySQL 作 replication 会有什么技巧:

  1. 注意 Linux 下有大小写区分,而 win2k 下没有。所以最好使用 mysqldump 方法来让两个数据库初始化同步,而不能使用 tar 方式直接 copy 数据库表文件。使用 mysql studio 来作 database backup 也不错
  2. 注意 win2k 下的 mysql 配置文件是 c:\my.ini。你可以使用 mysql administrator 0.9 这个图型界面的实用工具来设置。
  3. 如果 win2k 下的 mysql 为 master , 一定要注意 show master status 中显示出来的结果。
  4. win2k 下的 mysql 为 slave 时,注意不要把同步时间周期设置太长。

实战

环境配置

操作系统:linux
MySQL:5.14
主服务器A IP:192.168.1.2(假设)
从服务器B IP:192.168.1.3(假设)
同步数据库: test(用于测试,两台服务器初始数据一致)

主服务器(master)设置

新建一个用于备份的用户(直接用root用户也可以):
GRANT FILE ON *.* TO backup@192.168.1.3 IDENTIFIED BY ‘123456’;

编辑“/etc/my.cnf”(不同服务器可能路径不同)文件,在该文件添加以下内容:
server-id=1
#设置服务器id,主从服务器要不同
log-bin=mysqllog
#启用二进制变更日志(即把所有对数据进行操作的SQL命令以二进制格式记入日志)
#其中mysqllog是日志文件的名称,日志的文件名是mysqllog.n,其中n是一个6位数字的整数。
binlog-do-db=test
#指定需要启用二进制变更日志的数据库"test"
binlog-ignore-db = mysql
#指定不需要启用二进制变更日志的数据库"mysql"

重启mysqld服务,可以用mysql命令:SHOW MASTER STATUS;查看“启用二进制变更日志”情况

从服务器(slave)设置

编辑“/etc/my.cnf”(不同服务器可能路径不同)文件,在该文件添加以下内容:

server-id=2
#设置服务器id,主从服务器要不同
replicate-do-db=test
#指定需要从master同步过来的数据库"test"
replicate-ignore-db = mysql
#指定不需要从master同步过来的数据库"mysql"

#设置master服务器的IP地址、登陆用户、密码、端口
master-host=192.168.1.2
master-user=backup
master-password=123456
master-port=3306

master-connect-retry=60
#连接master服务器失败后重试的延迟时间
slave-skip-errors=all
#跳过所有错误继续执行同步工作
log-slave-updates
#启用从属服务器上的日志同步功能

注意:如果从服务器上存在master.info文件(如:/var/lib/mysql/master.info),要使以上配置选项生效,在重启mysqld服务前必须删除该文件。

重启mysqld服务,可以用mysql命令:SHOW SLAVE STATUS;查看同步情况

从数据库的相关命令:

slave st; slave start ; 开始停止从数据库。
show slave statusG; 显示从库正读取哪一个主数据库二进制日志

成功完成以上配置后,在主服务器A的test库里添加数据或删除数据,在从服务器B的test库里马上也能看到相应的变更。两台服务器的同步操作可以说是瞬间完成的。

 

posted by kingmaxyang in Tech and have No Comments

我靠,写软件近十年,今天才开始研究SVN的分支功能

最近在写大型软件,不用branches实在搞不店了,记录到博客以备忘。

SVN分支和合并

panweizeng.com 2009年03月08日 09:42 查看7386次 作者: Pan  【
文章分类:项目管理
尽管svn没有作强制要求,但是一般svn版本库目录建议创建trunk、branches和tags三个目录。在实际操作时,trunk主干版本要时刻保持干净,即随时可以基于这个版本进行修改并将应用部署上线。branches是分支目录,存放并行开发的项目代码,因为分支是主干的廉价拷贝(相当只是提交了一次主干版本,增加了一个版本号, 并没有取出版本库作镜像拷贝),所以你可以放心建立很多分支版本。不过 Subversion不支持跨版本库的拷贝,当使用svn copy时你只能在同一个版本库内操作。tags目录存放trunk某个的快照,比如说release-1.0即trunk处于1.0版本时的快照。

使用svn来作团队的代码管理,那么分支和合并将是非常常用的操作。下面是一个简单的示例。

1. 创建分支。这里假设你要负责一个叫theme的项目,分支号1.7.2。

1. #这里的localhost是svn服务器地址
2. svn copy -m “1.7.2 – theme” svn://localhost/www/trunk svn://localhost/www/branches/branch1.7.2-theme
3. svn co svn://localhost/www/branches/branch1.7.2-theme

2. 从trunk中merge到分支。忙了一个星期终于开发完了,但是开发期间trunk版本有过改动,部署上线前你需要合并trunk的代码。

1. #branch1.7.2-theme是分支目录,注意不可以进到分支子目录
2. cd branch1.7.2-theme
3. #前面的12972是开分支之前trunk的版本号,后面的12991是merge时trunk的版本号
4. svn merge -r 12972:12991 svn://localhost/www/trunk

如果有冲突选择p(postpone),merge完了之后使用svn st|grep ^C查看冲突文件,然后比对修改冲突文件。解决冲突后再check in ,信息写上执行的merge操作。

1. svn ci -m ‘svn merge -r 12972:12991 svn://localhost/www/trunk’

3. 从分支merge到trunk。上线测试完毕,你很幸运,一切都如预期正常,这时就要将分支回归trunk,将trunk更新到最新。

1. #先从trunk checkout一份新鲜的代码,然后cd到该版本目录下
2. svn co svn://localhost/www/trunk
3. cd trunk
4. #12973是分支开始的版本号,13006是分支结束的版本号
5. svn merge -r 12973:13006 svn://localhost/www/branches/branch1.7.2-theme

如步骤2一样解决冲突,解决冲突后再check in,信息写上执行的merge操作。

1. svn ci -m “svn merge -r 12973:13006 svn://localhost/www/branches/branch1.7.2-theme”

相关的手册可以参阅svn文档,电子版点这里下载

 

posted by kingmaxyang in Tech and have No Comments

JQuery移动版发布

最近开始有机会写一些非基于电脑平台的软件,可能甚至需要跨所有软、硬件平台,这一特性唯有WEB是可以做得到。在移动终端的平台选择上,最优还是Android,iOS仅运行于iPhone硬件成本太高,不是一般客户承受得起,而Win这昨日黄花提都不想提了,Linux不错可惜移动市场支持不多,只有Android以价廉、机多的优势目前不失为最优选择。

当我还在为如何在Android上的浏览器跑Javascript有更好的兼容性,而增强用户体验和减小Web程序员的工作量时,我发现,原来近日JQuery已经推出移动版!

地址:http://jquerymobile.com/

对于有志于开始移动终端的WEB应用的同志来说,无异于一个天大的好消息。可惜,京东上卖699的一款MID(掌上电脑)已经无货,无法买来做测试。

posted by kingmaxyang in Tech and have No Comments

字符集gbk与gb2312还是有微少区别

刚刚才发现,在使用iconv时,gb2312字符集还是有个别汉字不支持,比如“滘”字,在gb2312时认不出来,改成用gbk就OK了。

现在我的程序及数据库设计基本上都是utf-8的了,但在Windows还是gbk一套。在转换编码时,建议使用iconv(“gbk”,”utf-8″)注意utf-8不要漏了一横,在个别操作系统只认utf-8不认utf8的,不要使用iconv(“gb2312″,”utf-8″)。

posted by kingmaxyang in Tech and have No Comments