<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>PageTalks &#187; Programming</title>
	<atom:link href="http://pagetalks.com/category/site-development/programming/feed" rel="self" type="application/rss+xml" />
	<link>http://pagetalks.com</link>
	<description>Pure Web Development &#38; Design Ideas</description>
	<lastBuildDate>Thu, 19 Jan 2012 12:06:33 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Wrangling with Deflate, Base64 and GZip</title>
		<link>http://pagetalks.com/2012/01/19/wrangling-with-deflate-base64-and-gzip.html</link>
		<comments>http://pagetalks.com/2012/01/19/wrangling-with-deflate-base64-and-gzip.html#comments</comments>
		<pubDate>Thu, 19 Jan 2012 11:35:56 +0000</pubDate>
		<dc:creator>Robin</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[NodeJS]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[base64]]></category>
		<category><![CDATA[deflate]]></category>
		<category><![CDATA[gzip]]></category>
		<category><![CDATA[inflate]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[zlib]]></category>

		<guid isPermaLink="false">http://pagetalks.com/?p=549</guid>
		<description><![CDATA[最近不小心被一些编码相关的东西困扰了。这些从Web诞生便产生的一些编码问题，在2012年的今天仍然可以让一个程序员抓狂。项目的大致需求是这样的，客户端需要将一个字符串进行如下处理... ]]></description>
			<content:encoded><![CDATA[<p>最近不小心被一些编码相关的东西困扰了。这些从Web诞生便产生的一些编码问题，在2012年的今天仍然可以让一个程序员抓狂。项目的大致需求是这样的，客户端需要将一个字符串进行如下处理：</p>
<ol>
<li>将字符串进行Deflate压缩</li>
<li>将压缩后的结果再进行Base64编码</li>
</ol>
<p>那么服务器端，需要进行上述流程的反过程。问题是，由于这是个开放接口，客户端可以使用各种不同的平台进行开发，如JS、Java、Ruby、PHP等。好在，大多数语言都是基于<a href="http://zlib.net/">zlib</a>包装了自己的相关API，那么也算是实现标准了。窘迫的事情时，NodeJS里面zlib的实现是在0.6以后加入的，我们使用的技术仍然是0.4版本的。</p>
<p>迫于时间有限，切换到0.6或者实现zlib的binding都是不靠谱的，于是我打开了万能的Github。果然功夫不负有心人，找到了Deflate的纯JS实现——<a href="https://github.com/dankogai/js-deflate">RawDeflate</a>。顿时对作者的崇拜之心油然而生。殊不知，悲剧就是从这里开始的。<span id="more-549"></span><br />
<h3>Base64算法</h3>
<p>为了测试有效性，我用JS做了客户端编码工作，然后用Ruby实现了服务器端解码工作。代码如下:</p>
<ul>
<li>被我修改过的<a href="https://gist.github.com/1638963#file_deflate.js">deflate.js</a></li>
<li>JS编码脚本,<a href="https://gist.github.com/1638963#file_encode_v1.js">v1</a></li>
<li>Ruby解码脚本,<a href="https://gist.github.com/1638963#file_decode_v1.rb">v1</a></li>
</ul>
<p>这里只把编码脚本和解码脚本贴出来，其他的已经在上面给出了Gist链接。</p>
<h4>编码脚本, v1</h4>
<pre><code>var RawDeflate = require("./deflate"),
    Buffer = require("buffer").Buffer,
    fs = require("fs");

function encode(str) {
  return new Buffer(RawDeflate.deflate(str)).toString("base64");
}

console.log(encode("hello, world!"));
fs.writeFileSync("data.txt", encode("hello, world!"));</code></pre>
<h4>解码脚本，v1</h4>
<pre><code>require 'base64'
require 'zlib'

def decode(str)
  Zlib::Inflate.new(-Zlib::MAX_WBITS).inflate(Base64.decode64(str))
end

str = File.open("data.txt", "r") do |data|
  data.readlines().join()
end

p decode(str)</code></pre>
<p>运行的结果是空串哦，亲！也就是说Ruby竟然不能解出来。Ruby是直接在Zlib上进行包装的，那么其他的语言PHP、Python什么的也应该是同样的结果。</p>
<p>好吧，难道我JS的算法有误差？那么和Ruby的算法进行对比以下吧⋯⋯</p>
<p><a href="https://gist.github.com/1638963#file_compare_test.rb">Ruby的测试脚本</a>，算出的每个步骤都进行md5：</p>
<pre><code>require 'base64'
require 'zlib'
require 'digest/md5'

def deflate(str)
  Zlib::Deflate.new(nil, -Zlib::MAX_WBITS).deflate(str, Zlib::FINISH)
end

def base64(str)
  Base64.encode64(str)
end

def md5(str)
  s = Digest::MD5.hexdigest(str)
end

def encode(str)
  base64(deflate(str))
end

def decode(str)
  Zlib::Inflate.new(-Zlib::MAX_WBITS).inflate(Base64.decode64(str))
end

str = 'hello, world'

p "Test Base64"
p base64(str)
p md5(base64(str))

p "Test Deflate"
p deflate(str)
p md5(deflate(str))

p "Test Encode Defalte and Base64"
p encode(str)
p md5(encode(str))

p "Test Decode Deflate and Base64"
p decode(encode(str))</code></pre>
<p>运行发现，Ruby自己处理自己压缩出来的东西毫无问题。那么JS呢？</p>
<pre><code>var Base64 = require("./b64"),
    RawDeflate = require("./deflate"),
    Buffer = require("buffer").Buffer,
    crypto = require("crypto");

function decode (str) {
  return RawDeflate.inflate(new Buffer(str, "base64").toString());
}

function md5 (str) {
  return crypto.createHash("md5").update(str).digest("hex");
}

function base64 (str) {
  return new Buffer(str).toString("base64");
}

function deflate (str) {
  return RawDeflate.deflate(str);
}

function encode (str) {
  return base64(deflate(str));
}

var str = "hello, world";
console.log("Testing string: " + str);

console.log("Base64 Test");
console.log(base64(str));
console.log(md5(base64(str)));

console.log("Defalte Test");
console.log(deflate(str));
console.log(md5(deflate(str)));

console.log("Test Encode");
console.log(encode(str));
console.log(md5(encode(str)));

console.log("Test Decode");
console.log(decode(encode(str)));</code></pre>
<p>好吧，JS的算法自己处理自己的结果也是正确的。那么比较以下两边各个步骤的md5，可以发现几个现象：</p>
<p><a href="http://www.flickr.com/photos/28352704@N06/6724942605" title="View 'Screen Shot 2012-01-19 at 下午6.43.35' on Flickr.com"><img border="0" style="display:block; margin-left:auto; margin-right:auto;" height="396" src="http://farm8.staticflickr.com/7012/6724942605_db603df767_o.png" alt="Screen Shot 2012-01-19 at 下午6.43.35" width="560" title="Screen Shot 2012-01-19 at 下午6.43.35"/></a></p>
<ul>
<li>仅仅Base64后MD5便不一致</li>
<li>仅仅Deflate后MD5一致</li>
<li>Deflate后再Base64,结果MD5不一致</li>
</ul>
<p>那么就是NodeJS的Base64这么算可能不对了，这时我已经凌乱了，算了，干脆找个JS的Base64实现吧。我的大神啊，原来RawDeflate的作者自己也写了个<a href="https://github.com/dankogai/js-base64">Base64的实现</a>，我觉得这里面有阴谋⋯⋯</p>
<p>用上这位<a href="https://gist.github.com/1638963#file_base64.js">大神的Base64</a>，同时我也发现了RawDeflate里面有一个使用实例。例子里面在Deflate之前，把字符串进行了Base64.<a href="http://h30097.www3.hp.com/docs/base_doc/DOCUMENTATION/V40F_HTML/MAN/MAN1/0398____.HTM">utob</a>操作。但是我们用的测试字符是“hello,world&#8221;貌似没有非ACSII字符。</p>
<p>那么我们<a href="https://gist.github.com/1638963#file_encode_v2.js">新的编码脚本</a>如下：</p>
<pre><code>var RawDeflate = require("./deflate"),
    Buffer = require("buffer").Buffer,
    fs = require("fs"),
    Base64 = require("./base64");

function encode(str) {
  return Base64.toBase64(RawDeflate.deflate(Base64.utob(str)));
}

console.log(encode("hello, world!"));
fs.writeFileSync("data.txt", encode("hello, world!"));</code></pre>
<p>我们仍然使用之前的<a href="https://gist.github.com/1638963#file_decode_v1.rb">解码脚本</a>，结果竟然通过了！ruby得到了“hello,world“！</p>
<p>其中原理不解，有待高人解答，但是灾难还没有结束哦。</p>
<h3>RFC1951、RFC1950和RFC1951</h3>
<p>因为对方服务器目前使用的是JAVA，那么我必须用JAVA测试才能OK。</p>
<p>JAVA的代码如下，只贴出核心代码吧：</p>
<pre><code>InputStream in = new InflaterInputStream(new Base64InputStream(new FileInputStream(compressed)));</code></pre>
<p>第一次试验的结果是，无法解压的，想哭啊，得到“unknown compression method”的错误。</p>
<p>我开始质疑JAVA的实现了。虽然也是zlib的前缀，但是InflaterInputStream<a href="http://docs.oracle.com/javase/1.4.2/docs/api/java/util/zip/InflaterInputStream.html">这个类的JavaDoc</a>里却没有写清楚它对应的算法。</p>
<p>我们知道，HTTP传输里面经常会用到gzip、deflate来压缩内容，只用在header里面写明“Content-encoding&#8221;。Web服务器和浏览器其实都是相当默契的。好吧，我必须承认，浏览器不愧是Web里面最复杂的软件。因为它handle了太多的东西。</p>
<p><a href="http://www.ietf.org/rfc/rfc1950.txt">RFC1950</a>是zlib算法，<a href="http://www.google.com/url?sa=t&#038;rct=j&#038;q=rfc%201951&#038;source=web&#038;cd=1&#038;sqi=2&#038;ved=0CCMQFjAA&#038;url=http%3A%2F%2Fwww.ietf.org%2Frfc%2Frfc1951.txt&#038;ei=E_sXT9OPNsWpiAfVtdybCw&#038;usg=AFQjCNFifaDqn62RJhQ3ODDJ12pO1LsQAA">RFC1951</a>是deflate算法，<a href="http://www.google.com/url?sa=t&#038;rct=j&#038;q=rfc%201952&#038;source=web&#038;cd=1&#038;ved=0CCAQFjAA&#038;url=http%3A%2F%2Fwww.ietf.org%2Frfc%2Frfc1952.txt&#038;ei=I_sXT-ykEpCWiQe0wdmgCw&#038;usg=AFQjCNFA13Eq1NXCeQAGsDxtXuMSMI7bog">RFC1952</a>是Gzip算法。那么他们是三个独立的算法么？</p>
<p>我以为是，其实不是！</p>
<p>在HTTP 1.1的定义里面，也就是<a href="http://www.w3.org/Protocols/rfc2616/rfc2616.html">RFC2616</a>是这么定义delfate传输压缩的：</p>
<p><quote>deflate &#8211; The &#8220;zlib&#8221; format defined in RFC 1950 [31] in combination with the &#8220;deflate&#8221; compression mechanism described in RFC 1951 [29].</quote></p>
<p>原来zlib和deflate是同时使用的！zlib仅仅作为一种容器格式，来承载通过deflate算法压缩的内容。就像AVI其实是个视频容器格式，里面的压缩算法可以是XVID也可以H.262！</p>
<p>回来想想RawDeflate的主页上也仅仅说明是RFC1951的实现，而且人家是”Raw“Deflate，Raw！看来是我自己不懂啊⋯⋯</p>
<p>跟我一样苦逼的人还是不少的，看这个<a href="http://stackoverflow.com/questions/3932117/handling-http-contentencoding-deflate">帖子</a>，有一个回复已经给出了JAVA里面的解决方案。</p>
<p>如果要解决单纯使用Deflate压缩的文件，必须传入一个自定义Inflater。</p>
<pre><code>InputStream in = new InflaterInputStream(conn.getInputStream()), new Inflater(true));</code></pre>
<p>更新了JAVA脚本之后，的确问题解决了。顺手把其他语言解码方案也试验出来了。基本上，除了JAVA需要，其他实现都不需要进行额外的判断，所以JAVA实在不是一个敏捷语言啊⋯⋯</p>
<h4>Ruby解码实现</h4>
<pre><code>require 'base64'
require 'zlib'

def decode(str)
  Zlib::Inflate.new(-Zlib::MAX_WBITS).inflate(Base64.decode64(str))
end

File.open("data.txt", "r") do |data|
  str = data.readlines
  p decode str.join
end</code></pre>
<h4>Python解码实现</h4>
<p>Python在压缩的时候，想得到纯粹的Deflate流也是需要额外的加工的，详见此处：<a href="http://stackoverflow.com/questions/1089662/python-inflate-and-deflate-implementations">http://stackoverflow.com/questions/1089662/python-inflate-and-deflate-implementations</a>。</p>
<p><a href="https://gist.github.com/1638963#file_inflate.py">Python的解码</a>的实现也很直白：</p>
<pre><code>import zlib
import base64

str = ""
with open("data.txt") as data:
    for line in data:
        print line
        str += line

def decode_base64_and_inflate(str):
    decoded_data = base64.b64decode( str )
    return zlib.decompress( decoded_data , -zlib.MAX_WBITS)

print decode_base64_and_inflate(str)</code></pre>
<h4>PHP解码实现</h4>
<p>PHP一定要使用gzinflate才能解压纯Deflate流，gzuncompress是用来解压HTTP采用“deflate”方式压缩的数据的！</p>
<pre><code>$data = file_get_contents("data.txt");

echo $data;
echo gzinflate(base64_decode($data));

// this command will throw an exception: data error
// echo gzuncompress(base64_decode($data));
</code></pre>
<h4>JAVA实现</h4>
<p><a href="https://gist.github.com/1638963#file_inflate.java">JAVA实现</a>好累啊，这么罗嗦。还需要一个额外的一个JAR进行Base64操作。这里用的是Apache的<a href="http://commons.apache.org/codec/download_codec.cgi">Common Codec</a>。</p>
<pre><code>//http://stackoverflow.com/questions/3932117/handling-http-contentencoding-deflate

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.zip.DataFormatException;
import java.util.zip.Inflater;
import java.util.zip.InflaterInputStream;
import java.util.zip.ZipException;

import org.apache.commons.codec.binary.Base64InputStream;

public class Inflate {

    public static void inflate(File compressed, OutputStream out) throws IOException {
        InputStream in = new InflaterInputStream(new Base64InputStream(new FileInputStream(compressed)), new Inflater(true));
        shovelInToOut(in, out);
        in.close();
        out.close();
    }

    /**
     * Shovels all data from an input stream to an output stream.
     */
    private static void shovelInToOut(InputStream in, OutputStream out) throws IOException {
//    The following code should be working but it produces strange suffix like "[B@13fcf0ce" now and then
//        byte[] buffer = new byte[1000];
//        int len;
//        while((len = in.read(buffer)) > 0) {
//            out.write(buffer, 0, len);
//            System.out.println(buffer);
//        }

        String line;
        InputStreamReader isr = new InputStreamReader(in);
        BufferedReader br = new BufferedReader(isr);
        while((line = br.readLine()) != null) {
            out.write(line.getBytes());
        }
    }

    /**
     * Main method to test it all.
     */
    public static void main(String[] args) throws IOException, DataFormatException {
        File compressed = new File("data.txt");
        try {
            inflate(compressed, System.out);
        } catch(ZipException e) {
            System.out.println(e.getMessage());
            throw e;
        }
    }

}</code></pre>
<h3>总结</h3>
<p>编码问题总是一个挥之不去的阴影！</p>
]]></content:encoded>
			<wfw:commentRss>http://pagetalks.com/2012/01/19/wrangling-with-deflate-base64-and-gzip.html/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>10 Simple and Light Weight CMS Solutions</title>
		<link>http://pagetalks.com/2010/03/23/10-simple-and-light-weight-cms-solutions.html</link>
		<comments>http://pagetalks.com/2010/03/23/10-simple-and-light-weight-cms-solutions.html#comments</comments>
		<pubDate>Tue, 23 Mar 2010 13:40:58 +0000</pubDate>
		<dc:creator>Robin</dc:creator>
				<category><![CDATA[Digest]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[cms]]></category>
		<category><![CDATA[light weight]]></category>

		<guid isPermaLink="false">http://pagetalks.com/?p=363</guid>
		<description><![CDATA[Choosing the right content management system can be an overwhelming task for a web designer or developer. There are so many available, all with different features, it can be difficult to decide which is the best solution for a particular web project. For... ]]></description>
			<content:encoded><![CDATA[<div class="text-en" lang="en">
Choosing the right content management system can be an overwhelming task for a web designer or developer. There are so many available, all with different features, it can be difficult to decide which is the best solution for a particular web project. For complex websites, a fully featured CMS is probably the best way to go. However, for simple sites, lots of bells and whistles can be overkill and actually be a bit confusing for the person maintaining the website.</p>
<p>In this article, I’ve rounded up 10 simple and light weight cms solutions. All of these systems were built with simplicity and ease-of-use in mind.
</p></div>
<div class="text-cn" lang="zh">
Wordpress已经是PHP领域的CMS王者，其余的Movable Type、ExpressionEngine、Drupal之类也是十分强悍。但是根据8：2理论，他们80％的功能我们是用不着的！我们有足够的理由换用一个更加轻量级的程序。文章便做了这样一个介绍。
</div>
<p><a href="http://webdesignledger.com/tools/10-simple-and-light-weight-cms-solutions" class="external digest-continue more-link">Read More</a></p>
]]></content:encoded>
			<wfw:commentRss>http://pagetalks.com/2010/03/23/10-simple-and-light-weight-cms-solutions.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>5 Pet Peeves Developers Have With Designers (and How to Avoid Them)</title>
		<link>http://pagetalks.com/2010/03/22/5-pet-peeves-developers-have-with-designers-and-how-to-avoid-them.html</link>
		<comments>http://pagetalks.com/2010/03/22/5-pet-peeves-developers-have-with-designers-and-how-to-avoid-them.html#comments</comments>
		<pubDate>Mon, 22 Mar 2010 06:50:27 +0000</pubDate>
		<dc:creator>Robin</dc:creator>
				<category><![CDATA[Digest]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[developer]]></category>
		<category><![CDATA[PowerDesigner]]></category>
		<category><![CDATA[programmer]]></category>

		<guid isPermaLink="false">http://pagetalks.com/?p=348</guid>
		<description><![CDATA[&#8221; 就像猫和狗、该隐和亚伯一样，程序员和美工也是对死对头。 程序员和美工就像来自不同星球的两种完全不同的人，他们脑袋所关心的事情也完全不同。程序员希望网站运行起来完美，... ]]></description>
			<content:encoded><![CDATA[<div class="text-cn" lang="zh">
&#8221; 就像猫和狗、该隐和亚伯一样，程序员和美工也是对死对头。 程序员和美工就像来自不同星球的两种完全不同的人，他们脑袋所关心的事情也完全不同。程序员希望网站运行起来完美，而美工希望网站看起来漂亮。 这次，我们将站在程序员的角度看看：程序员对美工的5个经典牢骚。
</div>
<div class="text-en" lang="en">
Cats and dogs. Cain and Abel. Designers and developers. These are just a few of the great historical face-offs.</p>
<p>Designers and developers often seem to come from different planets and have completely different brains.</p>
<p>Developers want a website to work right, designers want it to look right.</p>
<p>A few weeks ago, we explored the main pet peeves that web designers have with web developers, and suggested some solutions for them.</p>
<p>Today, we will discuss the other side of the coin: the five most common gripes that developers have with designers.</p></div>
<p><a href="http://www.webdesignerdepot.com/2009/07/5-pet-peeves-developers-have-with-designers-and-how-to-avoid-them/" class="external digest-continue more-link">Read More</a></p>
]]></content:encoded>
			<wfw:commentRss>http://pagetalks.com/2010/03/22/5-pet-peeves-developers-have-with-designers-and-how-to-avoid-them.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Choosing a CASE Tool</title>
		<link>http://pagetalks.com/2010/01/04/choosing-a-case-tool.html</link>
		<comments>http://pagetalks.com/2010/01/04/choosing-a-case-tool.html#comments</comments>
		<pubDate>Mon, 04 Jan 2010 06:59:01 +0000</pubDate>
		<dc:creator>Robin</dc:creator>
				<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://pagetalks.com/?p=298</guid>
		<description><![CDATA[现在的建模工具在MDA的概念之下发展的非常强劲，我们这次的一个Web项目准备尝试用UML建模并辅助生成代码和数据库。不可避免的，我们需要考虑所使用的CASE工具。经过一番试用，总结出如下... ]]></description>
			<content:encoded><![CDATA[<p>现在的建模工具在MDA的概念之下发展的非常强劲，我们这次的一个Web项目准备尝试用UML建模并辅助生成代码和数据库。不可避免的，我们需要考虑所使用的CASE工具。经过一番试用，总结出如下内容：</p>
<h3>各领风骚</h3>
<p>目前流行的CASE工具还是很多的。UML的创始人Booch为首的Rational Rose，Sybase的PowerDesigner，NoMagic的MagicDraw。另外有一些工具和IDE集成紧密，NetBeans的UML工具，Eclipse的UML2Tools、EclipseUML、AmatuerUML、Together等。这其中有开源的，有商业的，让人眼花缭乱。除了基本的画图功能外，一些成熟的CASE工具是支持MDA特性的，即可以生成代码的。<br />
<span id="more-298"></span></p>
<h3>Rational Rose or RSA</h3>
<p>这个是老牌OOM的工具了，网上对他的介绍如下：</p>
<blockquote><p>Rose是当时全球最大的CASE工具提供商Rational的拳头产品，UML建模语言就是由Rational公司的三位巨头Booch、Rumbaugh和Jacobson发明的，后来Rational被IBM收购，所以Rose可谓出身名门，嫁入豪族。</p></blockquote>
<p>Rose的最新版本是Rose 2003，再之后的版本IBM开发了另一款Rational Software Architect，那是一款基于Eclipse的建模环境。意在替代已经大红大紫的Rose。可惜广大的工程师并不领情，依然习惯于老旧的Rose。<br />
Rose 2003里面，对UML2支持性很差，运行速度较慢。作为一款软件，他的界面显得有些老旧，界面使用不太方便。<br />
Rose的优点是它的教程、文档遍地都是，基本是OOM领域的一个基准点。另外，对于J2EE开发、GoF设计模式支持的非常深入。<br />
由于Rose更注重于项目的逻辑部分，这款软件的使用者，可能是经验丰富的设计师，或是已经相当习惯Rose的一些程序员。对于他们，也许这样一款异常“专业”的工具才是最亲切的。</p>
<p>新版的RSA我没有用过，大家可以到IBM的官网上下着玩下。RSA是基于Eclipse的一套IED，也有针对WebSphere的插件。这个更多的应该是完善IBM的整个Rational体系，因为你选择了WebSphere，那么就必须选择IBM的一系列产品，MDA这块，IBM肯定不会放过。看过Eclipse的UML插件你会发现，他们都大同小异。</p>
<p>Rational Rose： http://www.ibm.com/developerworks/cn/rational/products/rose/<br />
RSA： http://www.ibm.com/developerworks/cn/rational/products/rsa/</p>
<h3>PowerDesigner</h3>
<p>关于PD（PowerDesigner，以下同样如此简称），我们很自豪他的创始人是个中国人。网上对PD鄂介绍如下：</p>
<blockquote><p>PowerDesigner有一段好玩的历史，作者王晓昀是一位中国人，在法国SDP软件公司工作时，由于苦觅一个好用的CASE工具未果，干脆自由开搞，整了个AMC Designor出来，居然一炮打响，在法国卖得个“巴黎纸贵”，后来SDP被Powersoft公司收购，同年Sybase这只大黄雀又吃下了 Powersoft这只螳螂，所以PowerDesigner也是惊艳出场，星光四射。</p></blockquote>
<p>人们对PD的印象是再DBM领域是绝对的王者，毕竟东家是Sybase。这种说法再PD9的时候还尚且说得过去，但是从PD12往后，PD就是一个从需求到部署的一条龙的建模利器。可以说，PD才是真正意义上的RUP流程。<br />
在PD9之后的版本里，Requirements Data Model、Bussiness Process Model、Concept Data Model、Physics Data Model、Object Oriented Model等概念出来以后，就已经树立了PD的未来一站式建模的发展方向。<br />
从本质上讲，PD的数据库建模以及对象建模才是核心力量，其它的功能固然好，但是毕竟有很多选择（例如，用Word＋绘图工具直接做需求描述）。<br />
在PD15里面，跟UML2的关联度越来越大，各种各样的模型基本涵盖了RUP流程的每一个角落。</p>
<p>PD的数据库建模方面，在建立了CPM（类似于领域模型）可以自动生成针对某个DBMS的PDM（也就是数据库表）。这一过程就已经够爽了，想想CPM是数据库无关的，更新数据库这方面是非常潇洒的。<br />
PDM可以导出为SQL，最大限度的节省部署的难度。<br />
如果你决定用PD来做需求、分析、设计，那么你甚至可以从RDM到BPM，再到OOM、再到CPM，到这里实际上你的程序架构和数据库都出来了……<br />
PD的缺点是，它已经细致到了非常深的程度。上手虽然简单，但是真的想要从BPM到CPM一路上都用PD完成，需要一定研究。</p>
<p>PD可以在官网上下载试用版，在试用期内你就可以很容易上手。想想Sybase的PB吧……</p>
<p>PD ：http://www.sybase.com/products/modelingdevelopment/powerdesigner</p>
<h3>Magic Draw</h3>
<p>认识这个软件的理由很尴尬。号称对设计和开发领域非常友好的Mac上，其实这些程序建模软件少的可怜。除了基于Java的平台的一些本身就是跨平台的建模软件，就没有一个是真正为Mac开发的。<br />
MagicDraw是一个基于Java的独立开发环境，也有Eclipse插件，看你喜欢怎么用了。<br />
使用起来很方便，鼠标的操作占主要部分。目前还没有用这个做出过东西，也不能妄加评论。可能是被PD的易用性惯坏了，感觉比较难以上手，主要表现为一打开那超多按钮的界面就头晕……<br />
最新的16.6，我自己安装的16.5 SP4。这个是支持UML2.x的，图片风格和PD一样非常漂亮。如果使用Eclipse的插件，你可以直接在Eclipse里新建一个MagicDraw文件，然后在Eclipse里面作图，和插件无异。这一点让我比较喜欢。<br />
MagicDraw跟随的是Rose的脚步，强调逻辑建模，对需求建模支持的不是很强大。<br />
另外，MagicDraw的很多功能都是由插件提供的，当然插件大多是付费的……</p>
<p>MagicDraw不失为一个标准的UML解决方案，易用性赶不上PD，但是功能足够强大，感觉替代Rose是足够了的。</p>
<p>MagicDraw：http://www.magicdraw.com/</p>
<h3>EclipseUML</h3>
<p>这个是地道的Eclipse插件，支持UML2.x的所有图，标准的UML建模工具。我试用的时候感觉很吃内存。<br />
界面交互方式和MagicDraw之类的没有很大区别……<br />
它的主要优势是不断更新，且功能支持比较完整。但没有什么其它亮点。</p>
<h3>其它种种</h3>
<p>AmaterasUml是个非常简单的UML插件，仅仅支持有限的几种UML图。优势是简便、开源。http://amateras.sourceforge.jp/cgi-bin/fswiki_en/wiki.cgi?page=AmaterasUML<br />
Visual Paradigm，传说中速度最快的UML工具，下载过还没用过。http://www.visual-paradigm.com/product/vpuml/<br />
Eclipse UML2Tools是一个Eclipse的官方插件，是MDT的一个组件。支持的图比较有限，类似AmaterasUML。http://www.eclipse.org/modeling/mdt/downloads/?project=uml2tools</p>
]]></content:encoded>
			<wfw:commentRss>http://pagetalks.com/2010/01/04/choosing-a-case-tool.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Moving UC/SupeSite/Discuz/XSpace</title>
		<link>http://pagetalks.com/2009/12/02/moving-ucsupesitediscuzxspace.html</link>
		<comments>http://pagetalks.com/2009/12/02/moving-ucsupesitediscuzxspace.html#comments</comments>
		<pubDate>Wed, 02 Dec 2009 13:57:43 +0000</pubDate>
		<dc:creator>Robin</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[disscuz]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[supesite]]></category>

		<guid isPermaLink="false">http://pagetalks.com/?p=290</guid>
		<description><![CDATA[08年的一个客户想要把站点迁移到我们的服务器上，由于是一个大客户，我准备把站点迁移到linode上。以下是整个过程和经历： 站点的原来规模是一个SupeSite＋DZ＋XSpace＋UC的组合，虽然采用了... ]]></description>
			<content:encoded><![CDATA[<p>08年的一个客户想要把站点迁移到我们的服务器上，由于是一个大客户，我准备把站点迁移到linode上。以下是整个过程和经历：</p>
<p>站点的原来规模是一个SupeSite＋DZ＋XSpace＋UC的组合，虽然采用了开源代码，但在程序上进行了包括模板定制在内的大规模改动。对方没有IT支持，所以我们的沟通成本也很大。整体来说，是一个不大不小的事情。</p>
<p>这个事情的开端是比较痛苦的，他们站点的所有备份文件我都没有，等要到了FTP、DB的备份，时间也过了一天。可想而知，如果这些资料一开始就准备得当，转换是可以在30分钟内完成的平滑过度。对于一个具有一定规模的站点来说，这节省下来的时间是相当宝贵的。这样证明，企业专有的ADMIN还是很重要的。</p>
<p>排除非人为因素，关于系统的过度，Comsenz有很详细的介绍：</p>
<p>http://faq.comsenz.com/viewnews-539</p>
<p>http://faq.comsenz.com/viewnews-504</p>
<p>对于租用虚拟主机的用户，这些内容已经够了，但是Linode是VPS，我们可以用更简单的方法……</p>
<p>该任务有两种思路可以完成它：<br />
1、架设全新的系统，然后恢复数据库以及相关文件（头像、附件等等）<br />
2、拷贝以前的系统文件，恢复数据库，修改相关参数</p>
<p>由于我手上没有以前系统的版本信息，我无法下载相应的程序，而且我也不知道我们之前到底更改了哪些系统代码；所以采取了第二种思路。<br />
<span id="more-290"></span></p>
<h3>更改域名指向</h3>
<p>我们首先应该把域名转向给更改了，因为这个是需要时间刷新的，所以最好放在一开始完成。A记录和泛解都应该指向新的IP。</p>
<p>某些服务商是可以提供WEB在线打包的，那么你的站点可以很迅速的把自己打包为压缩文件，之后通过远程服务器对传文件。登陆到VPS之后，用wget命令取得了原来FTP上的压缩包。<br />
wget可以实现很复杂的下载操作，而利用远程服务器获取FTP上的文件只是杀鸡用牛刀。<br />
详细内容可以通过man查询，或是看看这里：http://airwave.blog.hexun.com/4162966_d.html</p>
<p>如果你无法快速拿到原站点的打包，你可以尝试FTP对传，也就是利用FlashFXP打开两个远程FTP，左右对传。总之，尽量避免传送到你的工作站再上传到新服务器，对于动辄上G的FTP备份，这个办法太脑残了。</p>
<p>至于数据库，得到SQL文件之后，可以上传到VPS，登陆mysql的命令行，用source命令导入。当然还有一些适合生产环境的方法，可是对于大多数使用此类开源系统的企业，短短几秒钟的数据库备份时间应该不会产生太大影响。</p>
<p>至此，还算比较顺利。</p>
<h3>确保Zend正常</h3>
<p>待DNS已经更新了我的域名解析之后，我打开浏览器进行调试，结果发现它提示我没有ZEND：</p>
<blockquote><p>Attention:Zend Optimizer not Installed</p>
<p>In order to run this software,please install the latest version of freely available Zend Optimizer<br />
您的服务器尚未正确安装运行本软件所需的 Zend Optimizer 软件，请与空间提供商联系。</p></blockquote>
<p>自己服务器上应该配置了Zend才对，可是为会这样呢？</p>
<p>在Google上找不到什么有用的内容，我直接进入Comsenz的论坛进行搜索了，果真我不是第一个吃螃蟹的人：</p>
<p>http://www.discuz.net/search.php?searchid=2561&#038;orderby=lastpost&#038;ascdesc=desc&#038;searchsubmit=yes</p>
<p>总结一下关于Zend的安装问题：<br />
1、phpinfo出现zend的图表不代表zend被正确配置，需要后面出现详细的zend参数才行<br />
<a href="http://pagetalks.com/wp-content/uploads/2009/12/zend_icon.png"><img src="http://pagetalks.com/wp-content/uploads/2009/12/zend_icon.png" alt="phpinfo的zend图标" title="phpinfo的zend图标" width="601" height="80" class="aligncenter size-full wp-image-292" /></a></p>
<p><a href="http://pagetalks.com/wp-content/uploads/2009/12/zend_spec.png"><img src="http://pagetalks.com/wp-content/uploads/2009/12/zend_spec.png" alt="只有有这些参数列表才代表你的zend配置正确" title="只有有这些参数列表才代表你的zend配置正确" width="621" height="205" class="aligncenter size-full wp-image-294" /></a></p>
<p>2、注意php和zend的版本对应，zend的安装包里有很多种版本<br />
<a href="http://pagetalks.com/wp-content/uploads/2009/12/zend_pack.gif"><img src="http://pagetalks.com/wp-content/uploads/2009/12/zend_pack.gif" alt="官方提供的压缩包的内容" title="官方提供的压缩包的内容" width="577" height="401" class="aligncenter size-full wp-image-296" /></a></p>
<p>3、php.ini需要配置正确<br />
参考http://bbs.zendchina.net/viewthread.php?tid=41，该文档是zend的官方文档。</p>
<p>http://www.xinlei.org/article/jishu/415.htm有相关参数的解释</p>
<p>主要设置如下两个参数：<br />
zend_optimizer.optimization_level=15<br />
zend_extension=&#8221;/usr/local/Zend/lib/ZendOptimizer.so&#8221;</p>
<p>切忌将zend_Optimizer.encoder_loader设置为0，此选项默认为1，这意味着会开启zend的加密解密功能。SupeSite的程序都是经过加密的，所以需要开启zend的解密。（这也是配置zend的主要目的）</p>
<p>4、保证zend的文件夹具有可执行权限<br />
我用root登陆进行的配置，所以没有遇到问题；如果是非root，应该要chmod设置一下。</p>
<h3>调整Gzip</h3>
<p>接下来打开浏览器，首页是显示到一半浏览器突然自己刷新然后提示：无法显示您尝试查看的页面，因为它使用了无效或者不支持的压缩格式。</p>
<p><a href="http://pagetalks.com/wp-content/uploads/2009/12/gzip_file.gif"><img src="http://pagetalks.com/wp-content/uploads/2009/12/gzip_file.gif" alt="包含GZIP选项的可能文件" title="包含GZIP选项的可能文件" width="485" height="566" class="aligncenter size-full wp-image-295" /></a></p>
<p>这个就比较郁闷了，这个应该是gzip的问题，我的服务器在PHP上已经设置了zlib的压缩。是否是需要禁用supesite的gzip？</p>
<p>在文件里面搜索gzip的选项：</p>
<p>目录下有这么多文件包含gzip，但是很显然只会在一些config文件里面才会有用。<br />
你需要检查这些文件：bbs_settings.cache.php、cache_settings.php、config.cache.php。确保里面的gzipcompress均为0。</p>
<h3>再看看系统的配置文件</h3>
<p>再测试一下，已经能够正常显示了。就在我以为已经大功告成了的时候，我竟然发现登陆的时候会提示无法链接到数据库！</p>
<p>这就让我郁闷了，因为config.php的数据库信息已经被我更改过了，怎么会无法链接了。再次求助Comsenz的官方论坛，果然我还不是第一个吃螃蟹的人：</p>
<p>http://www.discuz.net/viewthread.php?tid=1370988&#038;highlight=%CA%FD%BE%DD%BF%E2%2B%C7%A8%D2%C6</p>
<p>原因很简单，就是由于是几个组件的整合，你需要更改每个组件的配置文件。<br />
动手搜索文件名包含“config”的文件，需要修改的有三个：<br />
一个是uc的config.ins.php，一个是dz的config.inc.php、最后是ss的config.php。</p>
<p>这些配置文件里面，数据库用户名、数据库密码、数据库名称都是必填的。你还要确保后面的一些域名和IP地址的设置都是正确的，否则整套系统无法整合起来。</p>
<p>修改完后，刷新一下页面，已经可以正常登陆了。其他功能也正常了。</p>
<h3>修复死链</h3>
<p>这个问题在更换域名之后就会出现。参考了一些网友的意见：http://www.xlbbs.cn/bbs/redirect.php?tid=2685&#038;goto=lastpost。<br />
我发现官方提供了相应的工具来修复：</p>
<p>http://www.discuz.net/thread-618077-1-1.html</p>
<p>注意执行需要事先登陆为管理员，使用完毕候请删除该脚本。<br />
最后一点问题也清除了～呵呵</p>
<h3>总结</h3>
<ul>
<li>珍惜生命，善用搜索</li>
<li>确保你考虑到了所有可能性，尤其是在配置文件的问题上</li>
<li>不能忽视日常备份</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://pagetalks.com/2009/12/02/moving-ucsupesitediscuzxspace.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>On JSP Language in China</title>
		<link>http://pagetalks.com/2008/12/19/on-jsp-language-in-china.html</link>
		<comments>http://pagetalks.com/2008/12/19/on-jsp-language-in-china.html#comments</comments>
		<pubDate>Sat, 20 Dec 2008 02:02:21 +0000</pubDate>
		<dc:creator>Robin</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[china]]></category>
		<category><![CDATA[jsp]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://pagetalks.com/?p=196</guid>
		<description><![CDATA[随着互联网的繁荣，网络应用层次不穷。而构建网络应用的第一步，往往是选择一套合理的、富有弹性的、高效的应用平台。这一点无需置疑，也是大多数接触过网络编程的人士都接受的事实... ]]></description>
			<content:encoded><![CDATA[<p>随着互联网的繁荣，网络应用层次不穷。而构建网络应用的第一步，往往是选择一套合理的、富有弹性的、高效的应用平台。这一点无需置疑，也是大多数接触过网络编程的人士都接受的事实。除了纯粹的技术因数，平台的选择往往也与企业的商业决策（企业现有固定资产、人员结构等）；对个人用户来说，这种选择更大的程度上是决定于个人偏好和个人技术水平。</p>
<p>近几年来，开源社区的兴起，为网络技术的发展做出了不朽的贡献。这些社区将诸多以往被认为只有在少数前线大企业才能完成的开发分散到全球的各个程序员手中。这些自由程序员，在开源社区的带领下组成了巨大而高效的开发机器。在这种开发模式下，我们可以看到的成果是惊人的，从Linux操作系统到无数免费的桌面程序应用。而在这其中，存在着另一股巨大的涌动，那就是基于JSP的应用开发。</p>
<blockquote><p>
JSP(Java Server Pages)是由Sun Microsystems公司倡导、许多公司参与一起建立的一种动态网页技术标准。 JSP技术是用JAVA语言作为脚本语言的，JSP网页为整个服务器端的JAVA库单元提供了一个接口来服务于HTTP的应用程序。由于Sun公司从事服务器领域已有多年历史，其企业形象所蕴含的高效、稳定也继承在了JSP上。JSP的出现可以说是给本已混乱的网络编程语言扔下了一个重磅炸弹。</p></blockquote>
<p><span id="more-196"></span><br />
经过几年的厮杀，人们目睹了无数的小语言的兴起、衰落，无数企业在网络应用上的无休止的投资，以及每种语言背后的社区和研发公司的性酸苦辣。最终，网络语言市场，可谓依旧呈现三足鼎立之势：ASP、PHP、JSP三者共同占有着90%以上的市场。12月份最新的TIOBE排名显示了到目前为止的众多语言的占有率问题。</p>
<p><img src="http://www.tiobe.com/content/paperinfo/tpci/images/tpci_trends.png" alt="TIOBE Dec 2008" /></p>
<p>排开C++、VB、JS、C、C#等不能专注于网络应用或只能局限于前台程序，JAVA以绝对优势超越其他语言。（由于ASP.net严格来说不能算作一种语言，所以它没有被单独统计在其中）。似乎JAVA程序员可以做梦都偷着笑了，可事实并非如此——JAVA就像移动通讯的3G技术，尽管是这样那样的美好，可是当运营商真的想要用它的时候，就会遇到这样和那样的困难。这种局面，包括163在内的诸多国内门户是由PHP开发的，而微软的诸多网络服务自然而然是有ASP实现的，目前采用JSP的大多数是政府部门的官方站点和一些处于“时代前沿”的学生或开发人员承接的中、小型项目。JSP的窘境可想一般，一种网络编程语言的无冕之王竟然沦落到了“爷爷不要姥姥不爱”的地步……根据国内情况和本人实际经验我们可以进行如下的讨论。</p>
<h3>老板至上</h3>
<p>在这个市场经济时代，虽说技术驱动着市场，可给程序员发钱的还是老板。一个非常尴尬的局面是，公司的老总以自己那点技术知识在自己部门网站还未进入策划阶段之时就放出了诸如“就用PHP吧……”、“ASP的网站挺流行！”的话语，技术经理如果不是所谓的“理想主义者”或”JSP的狂热支持者“都不会加以阻止，更多的他们直接会在策划书的网络平台上写上”PHP+MySql“、”ASP+Access“之类的字样……更让人讽刺的是，往往老板的一句话会让程序员不得不自学本来被认为”没有竞争力“的PHP或ASP，毕竟家里妻子孩子还在等着吃饭呢。</p>
<h3>成本至上</h3>
<p>假设你有足够胆量或者你运气足够的好，顽固的高层决策的障碍被你消除，我们终于能够进行基于JSP的开发了。那么，开发全程的各项成本必然是技术经理在写报告的时候必须提到的事情，这个将是他们面临的第二大挑战。开发JSP用到的IDE，十个有九个是要收费的，还有一个是“残废“的，例如鼎鼎大名的MyEclipse。免费的 IDE让我们大学生做做“实验报告”还是可以的，如果真的干起了正家伙，我还不如直接跟老板写辞职书。好吧，我必须承认我们是在中国啊！一个版权保护极其薄弱的国家，你不仅能找到各式各样的商业软件下载，还能找到他们的注册机、破解器。开发软件的成本就这么解除了，代价是某天某软件公司会给你递上一封法律信函，往往一些实力雄厚的公司也不会选择这样做。<br />
另外，网络应用所依赖的服务器也是一个非常现实的问题。你可以找到一个一年只需要300RMB的双线全能空间（支持ASP、CGI、PHP、ACESS、MySQL），而你没法用同样的价格找到一个支持JSP、Servlet的空间。你能够找到的也许一台VPS，或者合租的服务器。假如你是小型企业，便会直接把你的策划书撕掉，然后把所有“JSP”换成“PHP”或“JSP”；假如你是中型企业，也许你会考虑合租服务器或使用专用的VPS服务，代价是一年平均2000RMB的固定成本呢；如果你是大企业，你可以作出够买服务器并放到电信托管的举动，代价是服务器（一次性，平均8000RMB）、托管（平均4000一年）、聘请专业的管理员（一年4万以上）、应用平台软件（WebLogic、 Oracle等，通常在5位数RMB以上，这些软件通常由于证书的原因不能使用盗版）的费用。企业的隐成本不算作其中。</p>
<h3>效率至上</h3>
<p>有一点必须要承认，面对高强度的应用，无论是PHP还是ASP，都跟JSP无法相比。JSP本身虽然也是脚本语言，但是却和PHP、ASP有着本质的区别。 PHP和ASP都是由语言引擎解释执行程序代码，而JSP代码却被编译成Servlet并由Java虚拟机执行，这种编译操作仅在对JSP页面的第一次请求时发生。在纯技术领域，对于这些语言的性能比较已经有很多详细的文章，在这里不加以赘述。<br />
可是单从技术的角度来开率问题是不明智的。效率这个词不等于“性能”，它应该还包括“开发时间”和&#8221;支持与维护”。在开发时间上，PHP便是“敏捷”开发的代名词，JSP没法比，甚至后起之秀Ruby On Rails都比JSP强。有人会说现在都是用框架在做J2EE开发。事实是，PHP也有诸如ThinkPHP、CakePHP的框架，Ruby On Rails的框架则更是数不胜数。凭什么一定让我用JSP的框架？<br />
关于支持与维护，JSP倒是可以扬眉吐气了。由于有SUN、IBM等公司在后面撑腰，JSP的确可以长期保证高效的技术支持；可你别忘了，ASP的支持提供商是Microsoft，它好歹还是世界第一大软件商；最可怜的则是 PHP，它是通过开源社区的形式提供支持。但开源社区也许并不意味着技术支持，因为在开源社区解答问题的可能就是IBM、Sun这些公司的工程师，他们更热衷于充当网络上的活雷锋。而且开源社区对于新技术的应用也更为大胆，这是那些受限于法律和投资风险的常规企业无法比拟的。还有一点大家必须清楚，够买 IBM和SUN的服务是需要通常5位数以上的RMB，否则你只能使用他们的“社区支持”。</p>
<h3>停止“攀比”</h3>
<p>有时候关于谁比谁强的争论都是技术人员饭后的谈资，慢慢的被炒作，便成了“问题”。技术人员在对另一种语言作出消极评价的时候，往往是想创造出自己的优越感，以及使自己相信自己不会被这场IT游戏立马淘汰。<br />
事实上，没有最好的，只有最合适的。雅虎中国的CTO曾经在一次讲话上完整的阐述了雅虎的技术体系。雅虎选择的即是LAMP体系，即 Linux+Apache+MySQL+PHP。这些软件全部是免费并且开源的，而且我们也从没听说雅虎有什么安全事故、或者程序效率低下的传言。他们选择BSD发行的Linux、并且对Apache进行定制开发，对于开发中遇到PHP的局限，则选择用C、C++进行PHP的扩展编写。这似乎在告诉我们，只要你有实力，选择何种语言都并不是最重要的。有足够的资金，你可以选择使用IBM的全套WebLogic+DB2，你也可以像Yahoo一样做定制开发，哪个在你那里行得通就用哪个。</p>
<p>综上所述，JSP的困境也许并不能叫做困境，它的确在技术上领先于其他语言，并且在国外已经是绝对的主流。只是在国内，面临着“精明”的中国人，他还需要更优秀一些才行。</p>
]]></content:encoded>
			<wfw:commentRss>http://pagetalks.com/2008/12/19/on-jsp-language-in-china.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Irritating Charset</title>
		<link>http://pagetalks.com/2008/10/22/irritating-charset.html</link>
		<comments>http://pagetalks.com/2008/10/22/irritating-charset.html#comments</comments>
		<pubDate>Wed, 22 Oct 2008 14:24:59 +0000</pubDate>
		<dc:creator>Robin</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[asp]]></category>
		<category><![CDATA[charset]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jsp]]></category>
		<category><![CDATA[php]]></category>

		<guid isPermaLink="false">http://pagetalks.com/?p=192</guid>
		<description><![CDATA[页面编码是有头部的META标签指定的。浏览器会根据设置的内容来选择编码集以显示内容。甚至，在你从一个UTF8的页面向一个GB2312的页面POST数据的时候，可能里面的东西就成为乱码了。除了统... ]]></description>
			<content:encoded><![CDATA[<p>页面编码是有头部的META标签指定的。浏览器会根据设置的内容来选择编码集以显示内容。甚至，在你从一个UTF8的页面向一个GB2312的页面POST数据的时候，可能里面的东西就成为乱码了。除了统一编码之外，显然还有一些其他方法。鉴于我之前被这个搞得很郁闷，我在这里特别地汇总一下，也好让大家验证一下这些的代码。目前已知JSP、PHP、ASP的方法总结如下：<br />
<span id="more-192"></span></p>
<h3>伟大（而麻烦）的JSP</h3>
<p>第一种方法大概就是写一个过滤器：</p>
<pre>package com.filter;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;

public class PageEncodingFilter extends HttpServlet implements Filter {

public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
request.setCharacterEncoding("UTF-8");
chain.doFilter(request, response);
}

public void init(FilterConfig arg0) throws ServletException {

}

public PageEncodingFilter() {
super();
}

public void destroy() {
super.destroy();
}

public void init() throws ServletException {
}
} </pre>
<p>并设置web.xml文档：</p>
<pre>&lt;filter&gt;
&lt;filter-name&gt;PageEncodingFilter&lt;/filter-name&gt;
&lt;filter-class&gt;com.filter.PageEncodingFilter&lt;/filter-class&gt;
&lt;/filter&gt;

&lt;filter-mapping&gt;
&lt;filter-name&gt;PageEncodingFilter&lt;/filter-name&gt;
&lt;url-pattern&gt;/*&lt;/url-pattern&gt;
&lt;/filter-mapping&gt;
</pre>
<p>还有一个escape()编码转换的方法：<br />
在前台传输之前，用JS进行转换:</p>
<pre>function enCode(chineseStr) {
        return escape(chineseStr,'utf-8');
}</pre>
<p>后台将数据作为普通字符串再进行解码为正常中文：</p>
<pre>String XXX= getUrlParameter(unescape(request.getQueryString()),"XXX");

//如此获得的XXX即为解码后的正确的中文

public String getUrlParameter(String str,String targetstr){

          String[] stringarray = str.split("&#038;") ;

            for(int i=0;i<stringarray.length;i++){
               if(stringarray[i].startsWith(targetstr)){
                   stringarray=stringarray[i].split("=");
                   break;
               }
            }
            return stringarray[1];
      }

//解码方法
//以下是对js的escape进行解码
      private final static byte[] val = { 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
          0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
          0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
          0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
          0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x00, 0x01,
          0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x3F, 0x3F, 0x3F,
          0x3F, 0x3F, 0x3F, 0x3F, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x3F,
          0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
          0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
          0x3F, 0x3F, 0x3F, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x3F, 0x3F,
          0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
          0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
          0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
          0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
          0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
          0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
          0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
          0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
          0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
          0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
          0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
          0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
          0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
          0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F };

      /**
       * 解码 说明：本方法保证 不论参数s是否经过escape()编码，均能得到正确的“解码”结果
       *
       * @param s
       * @return
       */
      public static String unescape(String s) {
      StringBuffer sbuf = new StringBuffer();
      int i = 0;
      int len = s.length();
      while (i < len) {
      int ch = s.charAt(i);
      if ('A' <= ch &#038;&#038; ch <= 'Z') { // 'A'..'Z' : as it was
      sbuf.append((char) ch);
      } else if ('a' <= ch &#038;&#038; ch <= 'z') { // 'a'..'z' : as it was
      sbuf.append((char) ch);
      } else if ('0' <= ch &#038;&#038; ch <= '9') { // '0'..'9' : as it was
      sbuf.append((char) ch);
      } else if (ch == '-' || ch == '_' // unreserved : as it was
      || ch == '.' || ch == '!' || ch == '~' || ch == '*'
      || ch == '\'' || ch == '(' || ch == ')') {
      sbuf.append((char) ch);
      } else if (ch == '%') {
      int cint = 0;
      if ('u' != s.charAt(i + 1)) { // %XX : map to ascii(XX)
      cint = (cint << 4) | val[s.charAt(i + 1)];
      cint = (cint << 4) | val[s.charAt(i + 2)];
      i += 2;
      } else { // %uXXXX : map to unicode(XXXX)
      cint = (cint << 4) | val[s.charAt(i + 2)];
      cint = (cint << 4) | val[s.charAt(i + 3)];
      cint = (cint << 4) | val[s.charAt(i + 4)];
      cint = (cint << 4) | val[s.charAt(i + 5)];
      i += 5;
      }
      sbuf.append((char) cint);
      } else { // 对应的字符未经过编码
      sbuf.append((char) ch);
      }
      i++;
      }
      return sbuf.toString();
      }</pre>
<h3>平民PHP</h3>
<p>PHP的方法是Blueidea里面的版主指点的，在这里共享一下。其思想主要是在传送之前转换编码：</p>
<pre>$send = iconv("UTF-8","GB2312//IGNORE",$data)</pre>
<p>就是这样把UTF8转换为了GB2312，PHP我爱你！<br />
这里的“//IGNORE"是为了让PHP忽略该函数转换“—”的错误。<br />
不过这里必须指出该函数需要libiconv的库。类似的还有mbstring库的mb_convert_encoding();<br />
如果你倒霉到环境里什么库都没有，那么手写JSP部分的那个函数吧……</p>
<h3>M$的ASP</h3>
<p>Gb2312编码页面中加入</p>
<pre> <%@LANGUAGE="VBSCRIPT" CODEPAGE="936"%><%Session.CodePage=936%>
<%Response.charset = "BG2312"%></pre>
<p>utf-8编码页面中加入</p>
<pre><%@LANGUAGE="VBSCRIPT" CODEPAGE="65001"%>
<%Session.CodePage=65001%>
<%Response.charset = "utf-8"%></pre>
<p>另附一些常用的codepage：</p>
<ul>
<li><%@ codepage=65001%> UTF-8</li>
<li><%@ codepage=936%> 简体中文</li>
<li><%@ codepage=950%> 繁体中文</li>
<li><%@ codepage=437 %> 美国/加拿大英语</li>
<li><%@ codepage=932 %> 日文</li>
<li><%@ codepage=949 %> 韩文</li>
<li><%@ codepage=866 %> 俄文</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://pagetalks.com/2008/10/22/irritating-charset.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
<!-- WP Super Cache is installed but broken. The path to wp-cache-phase1.php in wp-content/advanced-cache.php must be fixed! -->
