??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲精品无码久久久久秋霞,亚洲欧洲尹人香蕉综合,亚洲国产日韩精品http://www.tkk7.com/happytian/My really life......zh-cnSat, 10 May 2025 20:06:36 GMTSat, 10 May 2025 20:06:36 GMT60java 关键?/title><link>http://www.tkk7.com/happytian/archive/2008/05/14/200476.html</link><dc:creator>happytian</dc:creator><author>happytian</author><pubDate>Wed, 14 May 2008 12:50:00 GMT</pubDate><guid>http://www.tkk7.com/happytian/archive/2008/05/14/200476.html</guid><wfw:comment>http://www.tkk7.com/happytian/comments/200476.html</wfw:comment><comments>http://www.tkk7.com/happytian/archive/2008/05/14/200476.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/happytian/comments/commentRss/200476.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/happytian/services/trackbacks/200476.html</trackback:ping><description><![CDATA[关键字列?<br /> <br /> abstract boolean break byte case <br /> catch char class continue default <br /> do double else extends false <br /> final finally float for if <br /> implements import instanceof int interface <br /> long native new null package <br /> private protected public return short <br /> static super switch synchronized this <br /> throw throws transient true try <br /> void volatile while  <br /> <br /> 保留?<br /> &n bsp;constQgoto <br /> <br /> 注意?<br /> <br /> 识别java语言的关键字Q不要和其他语言如c/c++的关键字h?<br /> ?nbsp; <br /> const和goto是java的保留字?<br /> 所有的关键字都是小?<br /> friendlyQsizeof不是java的关键字</font>   <br /> <br /> <br /> 1. 标识W变?cMҎ都需要一定的名称,我们这U名U叫做标识符.java中对标识W有一定的限制.首先:所有的标识W的首字W必L字母Q大写Q?下划U_或美元符K?其次标示W是由数字(0--9Q?所有从a--z的大写字?a--z的小写字母与下划U_.元WE与所有在十六q制0xc0前的 ascii码等构成;W三注意表示W不能用系l保留的关键字做标示W? <img src ="http://www.tkk7.com/happytian/aggbug/200476.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/happytian/" target="_blank">happytian</a> 2008-05-14 20:50 <a href="http://www.tkk7.com/happytian/archive/2008/05/14/200476.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java 调用存储q程http://www.tkk7.com/happytian/archive/2008/05/14/200472.htmlhappytianhappytianWed, 14 May 2008 12:19:00 GMThttp://www.tkk7.com/happytian/archive/2008/05/14/200472.htmlhttp://www.tkk7.com/happytian/comments/200472.htmlhttp://www.tkk7.com/happytian/archive/2008/05/14/200472.html#Feedback0http://www.tkk7.com/happytian/comments/commentRss/200472.htmlhttp://www.tkk7.com/happytian/services/trackbacks/200472.html 存储q程是指保存在数据库q在数据库端执行的程序。你可以使用Ҏ的语法在JavacM调用存储q程。在调用Ӟ存储q程的名U及指定的参数通过JDBCq接发送给DBMSQ执行存储过Eƈ通过q接Q如果有Q返回结果?
使用存储q程拥有和用基于EJB或CORBAq样的应用服务器一L好处。区别是存储q程可以从很多流行的DBMS中免费用,而应用服务器大都非常昂贵。这q不只是许可证费用的问题。用应用服务器所需要花费的理、编写代码的费用Q以及客L序所增加的复杂性,都可以通过DBMS中的存储q程所整个地替代?
你可以用JavaQPythonQPerl或C~写存储q程Q但是通常使用你的DBMS所指定的特定语a。Oracle使用PL/SQLQPostgreSQL使用pl/pgsqlQDB2使用Procedural SQL。这些语a都非常相伹{在它们之间UL存储q程q不比在Sun的EJB规范不同实现版本之间ULSession Bean困难。ƈ且,存储q程是ؓ嵌入SQL所设计Q这使得它们比Java或C{语a更加友好地方式表达数据库的机制?
因ؓ存储q程q行在DBMS自nQ这可以帮助减少应用E序中的{待旉。不是在Java代码中执?个或5个SQL语句Q而只需要在服务器端执行1个存储过E。网l上的数据往q次数的减少可以戏剧性地优化性能?

使用存储q程

单的老的JDBC通过CallableStatementcL持存储过E的调用。该cd际上是PreparedStatement的一个子cR假设我们有一个poets数据库。数据库中有一个设|诗人逝世q龄的存储过E。下面是对老酒鬼Dylan ThomasQold soak Dylan ThomasQ不指定是否有关典故、文化,h评指正。译注)q行调用的详l代码:

try{

int age = 39;

String poetName = "dylan thomas";

CallableStatement proc = connection.prepareCall("{ call set_death_age(?, ?) }");

proc.setString(1, poetName);

proc.setInt(2, age);

cs.execute();

}catch (SQLException e){ // ....}

传给prepareCallҎ的字串是存储q程调用的书写规范。它指定了存储过E的名称Q?代表了你需要指定的参数?
和JDBC集成是存储过E的一个很大的便利Qؓ了从应用中调用存储过E,不需要存根(stubQ类或者配|文Ӟ除了你的DBMS的JDBC驱动E序外什么也不需要?
当这D代码执行时Q数据库的存储过E就被调用。我们没有去获取l果Q因存储q程q不q回l果。执行成功或p|通过例外得知。失败可能意味着调用存储q程时的p|Q比如提供的一个参数的cd不正)Q或者一个应用程序的p|Q比如抛Z个例外指C在poets数据库中q不存在“Dylan Thomas”Q?

l合SQL操作与存储过E?

映射Java对象到SQL表中的行相当单,但是通常需要执行几个SQL语句Q可能是一个SELECT查找IDQ然后一个INSERT插入指定ID的数据。在高度规格化(W合更高的范式,译注Q的数据库模式中Q可能需要多个表的更斎ͼ因此需要更多的语句。Java代码会很快地膨胀Q每一个语句的|络开销也迅速增加?
这些SQL语句转移C个存储过E中大大简化代码,仅涉及一ơ网l调用。所有关联的SQL操作都可以在数据库内部发生。ƈ且,存储q程语言Q例如PL/SQLQ允怋用SQL语法Q这比Java代码更加自然。下面是我们早期的存储过E,使用Oracle的PL/SQL语言~写Q?

create procedure set_death_age(poet VARCHAR2, poet_age NUMBER)

poet_id NUMBER;

begin SELECT id INTO poet_id FROM poets WHERE name = poet;

INSERT INTO deaths (mort_id, age) VALUES (poet_id, poet_age);

end set_death_age;

很独特?不。我打赌你一定期待看C个poets表上的UPDATE。这也暗CZ使用存储q程实现是多么容易的一件事情。set_death_age几乎可以肯定是一个很烂的实现。我们应该在poets表中d一列来存储逝世q龄。Java代码中ƈ不关心数据库模式是怎么实现的,因ؓ它仅调用存储q程。我们以后可以改变数据库模式以提高性能Q但是我们不必修Ҏ们代码?
下面是调用上面存储过E的Java代码Q?

public static void setDeathAge(Poet dyingBard, int age) throws SQLException{

Connection con = null;

CallableStatement proc = null;

try {

con = connectionPool.getConnection();

proc = con.prepareCall("{ call set_death_age(?, ?) }");

proc.setString(1, dyingBard.getName());

proc.setInt(2, age);

proc.execute();

}

finally {

try { proc.close(); }

catch (SQLException e) {}

con.close();

}

}

Z保可维护性,使用像这儿这LstaticҎ。这也得调用存储过E的代码集中在一个简单的模版代码中。如果你用到许多存储q程Q就会发C需要拷贝、粘贴就可以创徏新的Ҏ。因Z码的模版化,甚至也可以通过脚本自动生调用存储q程的代码?

Functions

存储q程可以有返回|所以CallableStatementcLcMgetResultSetq样的方法来获取q回倹{当存储q程q回一个值时Q你必须使用registerOutParameterҎ告诉JDBC驱动器该值的SQLcd是什么。你也必调整存储过E调用来指示该过E返回一个倹{?
下面接着上面的例子。这ơ我们查询Dylan Thomas逝世时的q龄。这ơ的存储q程使用PostgreSQL的pl/pgsqlQ?

create function snuffed_it_when (VARCHAR) returns integer ´declare

poet_id NUMBER;

poet_age NUMBER;

begin

--first get the id associated with the poet.

SELECT id INTO poet_id FROM poets WHERE name = $1;

--get and return the age.

SELECT age INTO poet_age FROM deaths WHERE mort_id = poet_id;

return age;

end;´ language ´pl/pgsql´;

另外Q注意pl/pgsql参数名通过Unix和DOS脚本?n语法引用。同Ӟ也注意嵌入的注释Q这是和Java代码相比的另一个优性。在Java中写q样的注释当然是可以的,但是看v来很凌ؕQƈ且和SQL语句pQ必d入到Java String中?
下面是调用这个存储过E的Java代码Q?

connection.setAutoCommit(false);

CallableStatement proc = connection.prepareCall("{ ? = call snuffed_it_when(?) }");

proc.registerOutParameter(1, Types.INTEGER);

proc.setString(2, poetName);

cs.execute();

int age = proc.getInt(2);

如果指定了错误的q回值类型会怎样Q那么,当调用存储过E时抛Z个RuntimeExceptionQ正如你在ResultSet操作中用了一个错误的cd所到的一栗?

复杂的返回?

关于存储q程的知识,很多人好像就熟悉我们所讨论的这些。如果这是存储过E的全部功能Q那么存储过E就不是其它q程执行机制的替换方案了。存储过E的功能比这强大得多?
当你执行一个SQL查询ӞDBMS创徏一个叫做cursorQ游标)的数据库对象Q用于在q回l果中P代每一行。ResultSet是当前时间点的游标的一个表C。这是Z么没有缓存或者特定数据库的支持,你只能在ResultSet中向前移动?
某些DBMS允许从存储过E中q回游标的一个引用。JDBCq不支持q个功能Q但是Oracle、PostgreSQL和DB2的JDBC驱动器都支持在ResultSet上打开到游标的指针QpointerQ?
设想列出所有没有活到退休年龄的诗hQ下面是完成q个功能的存储过E,q回一个打开的游标,同样也用PostgreSQL的pl/pgsql语言Q?

create procedure list_early_deaths () return refcursor as ´declare

toesup refcursor;

begin

open toesup for SELECT poets.name, deaths.age FROM poets, deaths -- all entries in deaths are for poets. -- but the table might become generic.

WHERE poets.id = deaths.mort_id AND deaths.age < 60;

return toesup;

end;´ language ´plpgsql´;

下面是调用该存储q程的JavaҎQ将l果输出到PrintWriterQ?
PrintWriter:

static void sendEarlyDeaths(PrintWriter out){

Connection con = null;

CallableStatement toesUp = null;

try {

con = ConnectionPool.getConnection();

// PostgreSQL needs a transaction to do this... con.

setAutoCommit(false); // Setup the call.

CallableStatement toesUp = connection.prepareCall("{ ? = call list_early_deaths () }");

toesUp.registerOutParameter(1, Types.OTHER);

toesUp.execute();

ResultSet rs = (ResultSet) toesUp.getObject(1);

while (rs.next()) {

String name = rs.getString(1);

int age = rs.getInt(2);

out.println(name + " was " + age + " years old.");

}

rs.close();

}

catch (SQLException e) { // We should protect these calls. toesUp.close(); con.close();

}

}

因ؓJDBCq不直接支持从存储过E中q回游标Q我们用Types.OTHER来指C存储过E的q回cdQ然后调用getObject()Ҏq对q回D行强制类型{换?
q个调用存储q程的JavaҎ是mapping的一个好例子。Mapping是对一个集上的操作q行抽象的方法。不是在q个q程上返回一个集Q我们可以把操作传送进L行。本例中Q操作就是把ResultSet打印C个输出流。这是一个值得举例的很常用的例子,下面是调用同一个存储过E的另外一个方法实玎ͼ

public class ProcessPoetDeaths{

public abstract void sendDeath(String name, int age);

}

static void mapEarlyDeaths(ProcessPoetDeaths mapper){

Connection con = null;

CallableStatement toesUp = null;

try {

con = ConnectionPool.getConnection();

con.setAutoCommit(false);

CallableStatement toesUp = connection.prepareCall("{ ? = call list_early_deaths () }");

toesUp.registerOutParameter(1, Types.OTHER);

toesUp.execute();

ResultSet rs = (ResultSet) toesUp.getObject(1);

while (rs.next()) {

String name = rs.getString(1);

int age = rs.getInt(2);

mapper.sendDeath(name, age);

}

rs.close();

} catch (SQLException e) { // We should protect these calls. toesUp.close();

con.close();

}

}

q允许在ResultSet数据上执行Q意的处理Q而不需要改变或者复制获取ResultSet的方法:

static void sendEarlyDeaths(final PrintWriter out){

ProcessPoetDeaths myMapper = new ProcessPoetDeaths() {

public void sendDeath(String name, int age) {

out.println(name + " was " + age + " years old.");

}

};

mapEarlyDeaths(myMapper);

}

q个Ҏ使用ProcessPoetDeaths的一个匿名实例调用mapEarlyDeaths。该实例拥有sendDeathҎ的一个实玎ͼ和我们上面的例子一L方式把结果写入到输出。当Ӟq个技巧ƈ不是存储q程Ҏ的,但是和存储过E中q回的ResultSetl合使用Q是一个非常强大的工具?

l论

存储q程可以帮助你在代码中分逻辑Q这基本上L有益的。这个分ȝ好处有:
• 快速创建应用,使用和应用一h变和改善的数据库模式?
• 数据库模式可以在以后改变而不影响Java对象Q当我们完成应用后,可以重新设计更好的模式?
• 存储q程通过更好的SQL嵌入使得复杂的SQL更容易理解?
• ~写存储q程比在Java中编写嵌入的SQL拥有更好的工PQ大部分~辑器都提供语法高亮Q?
• 存储q程可以在Q何SQL命o行中试Q这使得调试更加Ҏ?

q不是所有的数据库都支持存储q程Q但是存在许多很的实现Q包括免?开源的和非免费的,所以移植ƈ不是一个问题。Oracle、PostgreSQL和DB2都有cM的存储过E语aQƈ且有在线的社区很好地支持?
存储q程工具很多Q有像TOAD或TORAq样的编辑器、调试器和IDEQ提供了~写、维护PL/SQL或pl/pgsql的强大的环境?
存储q程实增加了你的代码的开销Q但是它们和大多数的应用服务器相比,开销得多。如果你的代码复杂到需要用DBMSQ我整个采用存储q程的方式?

资源

• JDBC specification
• PostgreSQL
• Oracle Corporation´s Oracle database server
• IBM´s DB2 database server

作者简介:Nic Ferrier 是Web应用斚w的独立Y仉问。顾问?


happytian 2008-05-14 20:19 发表评论
]]>
字符Q字节和~码http://www.tkk7.com/happytian/archive/2007/10/24/155453.htmlhappytianhappytianWed, 24 Oct 2007 01:33:00 GMThttp://www.tkk7.com/happytian/archive/2007/10/24/155453.htmlhttp://www.tkk7.com/happytian/comments/155453.htmlhttp://www.tkk7.com/happytian/archive/2007/10/24/155453.html#Feedback2http://www.tkk7.com/happytian/comments/commentRss/155453.htmlhttp://www.tkk7.com/happytian/services/trackbacks/155453.html字符Q字节和~码

[原创文章Q{载请保留或注明出处:http://www.regexlab.com/zh/encoding.htm]

U别Q中U?/p>

摘要Q本文介l了字符与编码的发展q程Q相x늚正确理解。D例说明了一些实际应用中Q编码的实现Ҏ。然后,本文讲述了通常对字W与~码的几U误解,׃q些误解而导致ؕ码生的原因Q以及消除ؕ码的办法。本文的内容늛?#8220;中文问题”Q?#8220;q问题”?/p>

掌握~码问题的关键是正确地理解相x念,~码所涉及的技术其实是很简单的。因此,阅读本文旉要慢d惻I多思考?/p>

引言

“字符与编?#8221;是一个被l常讨论的话题。即使这P时常出现的ؕ码仍然困扰着大家。虽然我们有很多的办法可以用来消除ؕ码,但我们ƈ不一定理解这些办法的内在原理。而有的ؕ码生的原因Q实际上׃底层代码本n有问题所D的。因此,不仅是初学者会对字W编码感到模p,有的底层开发h员同样对字符~码~Z准确的理解?/p>
 

1. ~码问题的由来,相关概念的理?/h4>

1.1 字符与编码的发展

从计机对多国语a的支持角度看Q大致可以分Z个阶D:

  pȝ内码 说明
阶段一 ASCII 计算机刚开始只支持pQ其它语a不能够在计算Z存储和显C?/td> 英文 DOS
阶段?/td> ANSI~码
Q本地化Q?/td>
Z计算机支持更多语aQ通常使用 0x80~0xFF 范围?2 个字节来表示 1 个字W。比如:汉字 '? 在中文操作系l中Q?[0xD6,0xD0] q两个字节存储?br />
不同的国家和地区制定了不同的标准Q由此生了 GB2312, BIG5, JIS {各自的~码标准。这些?2 个字节来代表一个字W的各种汉字延׾~码方式Q称?strong> ANSI ~码。在体中文系l下QANSI ~码代表 GB2312 ~码Q在日文操作pȝ下,ANSI ~码代表 JIS ~码?br />
不同 ANSI ~码之间互不兼容Q当信息在国际间交流Ӟ无法属于两U语a的文字,存储在同一D?strong> ANSI ~码的文本中?/td>
中文 DOSQ中?Windows 95/98Q日?Windows 95/98
阶段?/td> UNICODE
Q国际化Q?/td>
Z使国际间信息交流更加方便Q国际组l制定了 UNICODE 字符?/strong>Qؓ各种语言中的每一个字W设定了l一q且唯一的数字编P以满语言、跨q_q行文本转换、处理的要求?/td> Windows NT/2000/XPQLinuxQJava

字符串在内存中的存放ҎQ?/p>

?ASCII 阶段Q?strong>单字节字W串使用一个字节存放一个字W(SBCSQ。比如,"Bob123" 在内存中为:

42 6F 62 31 32 33 00
B o b 1 2 3 \0

在?ANSI ~码支持多种语言阶段Q每个字W用一个字节或多个字节来表C(MBCSQ,因此Q这U方式存攄字符也被UC多字节字W?/strong>。比如,"中文123" 在中?Windows 95 内存中ؓ7个字节,每个汉字?个字节,每个英文和数字字W占1个字节:

D6 D0 CE C4 31 32 33 00
?/td> ?/td> 1 2 3 \0

?UNICODE 被采用之后,计算机存攑֭W串Ӟ改ؓ存放每个字符?UNICODE 字符集中的序受目前计机一般?2 个字节(16 位)来存放一个序PDBCSQ,因此Q这U方式存攄字符也被UC宽字节字W?/strong>。比如,字符?"中文123" ?Windows 2000 下,内存中实际存攄?5 个序P

2D 4E 87 65 31 00 32 00 33 00 00 00      ← ?x86 CPU 中,低字节在?/font>
?/td> ?/td> 1 2 3 \0  

一共占 10 个字节?/p>
 

1.2 字符Q字节,字符?/h5>

理解~码的关键,是要把字W的概念和字节的概念理解准确。这两个概念ҎhQ我们在此做一下区分:

  概念描述 举例
字符 Z使用的记P抽象意义上的一个符受?/td> '1', '?, 'a', '$', 'K?, ……
字节 计算Z存储数据的单元,一?位的二进制数Q是一个很具体的存储空间?/td> 0x01, 0x45, 0xFA, ……
ANSI
字符?/td>
在内存中Q如?#8220;字符”是以 ANSI ~码形式存在的,一个字W可能用一个字节或多个字节来表C,那么我们U这U字W串?ANSI 字符?/strong>或?strong>多字节字W串?/td> "中文123"
Q占7字节Q?/font>
UNICODE
字符?/td>
在内存中Q如?#8220;字符”是以?UNICODE 中的序号存在的,那么我们U这U字W串?UNICODE 字符?/strong>或?strong>宽字节字W串?/td> L"中文123"
Q占10字节Q?/font>

׃不同 ANSI ~码所规定的标准是不相同的Q因此,对于一个给定的多字节字W串Q我们必ȝ道它采用的是哪一U编码规则,才能够知道它包含了哪?#8220;字符”。而对?UNICODE 字符?/strong>来说Q不在什么环境下Q它所代表?#8220;字符”内容L不变的?/p>
 

1.3 字符集与~码

各个国家和地区所制定的不?ANSI ~码标准中,都只规定了各自语a所需?#8220;字符”。比如:汉字标准QGB2312Q中没有规定韩国语字W怎样存储。这?ANSI ~码标准所规定的内容包含两层含义:

  1. 使用哪些字符。也是说哪些汉字,字母和符号会被收入标准中。所包含“字符”的集合就叫做“字符?/strong>”?
  2. 规定每个“字符”分别用一个字节还是多个字节存储,用哪些字节来存储Q这个规定就叫做“~码”?

各个国家和地区在制定~码标准的时候,“字符的集?#8221;?#8220;~码”一般都是同时制定的。因此,q_我们所说的“字符?#8221;Q比如:GB2312, GBK, JIS {,除了?#8220;字符的集?#8221;q层含义外,同时也包含了“~码”的含义?/p>

UNICODE 字符?/strong>”包含了各U语a中用到的所?#8220;字符”。用来给 UNICODE 字符集编码的标准有很多种Q比如:UTF-8, UTF-7, UTF-16, UnicodeLittle, UnicodeBig {?/p>
 

1.4 常用的编码简?/h5>

单介l一下常用的~码规则Qؓ后边的章节做一个准备。在q里Q我们根据编码规则的特点Q把所有的~码分成三类Q?/p>
分类 ~码标准 说明
单字节字W编?/td> ISO-8859-1 最单的~码规则Q每一个字节直接作Z?UNICODE 字符。比如,[0xD6, 0xD0] q两个字节,通过 iso-8859-1 转化为字W串Ӟ直接得?[0x00D6, 0x00D0] 两个 UNICODE 字符Q即 "ÖÐ"?br />
反之Q将 UNICODE 字符串通过 iso-8859-1 转化为字节串Ӟ只能正常转化 0~255 范围的字W?/td>
ANSI ~码 GB2312,
BIG5,
Shift_JIS,
ISO-8859-2 ……
?UNICODE 字符串通过 ANSI ~码转化?#8220;字节?#8221;ӞҎ各自~码的规定,一?UNICODE 字符可能转化成一个字节或多个字节?br />
反之Q将字节串{化成字符串时Q也可能多个字节转化成一个字W。比如,[0xD6, 0xD0] q两个字节,通过 GB2312 转化为字W串Ӟ得?[0x4E2D] 一个字W,?'? 字?br />
“ANSI ~码”的特点:
1. q些“ANSI ~码标准”都只能处理各自语a范围之内?UNICODE 字符?br /> 2. “UNICODE 字符”?#8220;转换出来的字?#8221;之间的关pLZؓ规定的?/td>
UNICODE ~码 UTF-8,
UTF-16, UnicodeBig ……
?#8220;ANSI ~码”cM的,把字W串通过 UNICODE ~码转化?#8220;字节?#8221;Ӟ一?UNICODE 字符可能转化成一个字节或多个字节?br />
?#8220;ANSI ~码”不同的是Q?br /> 1. q些“UNICODE ~码”能够处理所有的 UNICODE 字符?br /> 2. “UNICODE 字符”?#8220;转换出来的字?#8221;之间是可以通过计算得到的?/td>

我们实际上没有必要去q每一U编码具体把某一个字W编码成了哪几个字节Q我们只需要知?#8220;~码”的概念就是把“字符”转化?#8220;字节”可以了。对?#8220;UNICODE ~码”Q由于它们是可以通过计算得到的,因此Q在Ҏ的场合,我们可以M解某一U?#8220;UNICODE ~码”是怎样的规则?/p>
 

2. 字符与编码在E序中的实现

2.1 E序中的字符与字?/h5>

?C++ ?Java 中,用来代表“字符”?#8220;字节”的数据类型,以及q行~码的方法:

cd或操?/strong> C++ Java
字符 wchar_t char
字节 char byte
ANSI 字符?/td> char[] byte[]
UNICODE 字符?/td> wchar_t[] String
字节?#8594;字符?/td> mbstowcs(), MultiByteToWideChar() string = new String(bytes, "encoding")
字符?#8594;字节?/td> wcstombs(), WideCharToMultiByte() bytes = string.getBytes("encoding")

以上需要注意几点:

  1. Java 中的 char 代表一?#8220;UNICODE 字符Q宽字节字符Q?#8221;Q?C++ 中的 char 代表一个字节?
  2. MultiByteToWideChar() ?WideCharToMultiByte() ?Windows API 函数?
 
2.2 C++ 中相兛_现方?/h5>

声明一D字W串帔RQ?/p>
// ANSI 字符Ԍ内容长度 7 字节
char
     sz[20] = "中文123";

// UNICODE 字符Ԍ内容长度 5 ?wchar_tQ?0 字节Q?/span>
wchar_t wsz[20] = L"\x4E2D\x6587\x0031\x0032\x0033";

UNICODE 字符串的 I/O 操作Q字W与字节的{换操作:

// q行时设定当?ANSI ~码QVC 格式
setlocale(LC_ALL, ".936");

// GCC 中格?/span>
setlocale(LC_ALL, "zh_CN.GBK");

// Visual C++ 中用小?%sQ按?setlocale 指定~码输出到文?br /> // GCC 中用大?%S
fwprintf(fp, L"%s\n", wsz);

// ?UNICODE 字符串按?setlocale 指定的编码{换成字节
wcstombs(sz, wsz, 20);
// 把字节串按照 setlocale 指定的编码{换成 UNICODE 字符?br />
mbstowcs(wsz, sz, 20);

?Visual C++ 中,UNICODE 字符串常量有更简单的表示Ҏ。如果源E序的编码与当前默认 ANSI ~码不符Q则需要?#pragma setlocaleQ告诉编译器源程序用的~码Q?/p>
// 如果源程序的~码与当前默?ANSI ~码不一_
// 则需要此行,~译时用来指明当前源E序使用的编?/font>

#pragma setlocale
(".936")

// UNICODE 字符串常量,内容长度 10 字节
wchar_t wsz[20] = L"中文123";

以上需要注?#pragma setlocale ?setlocale(LC_ALL, "") 的作用是不同的,#pragma setlocale 在编译时起作用,setlocale() 在运行时起作用?/p>
 

2.3 Java 中相兛_现方?/h5>

字符串类 String 中的内容?UNICODE 字符Ԍ

// Java 代码Q直接写中文
String
string = "中文123";

// 得到长度?5Q因为是 5 个字W?/span>
System.out.println(string.length());

字符?I/O 操作Q字W与字节转换操作。在 Java ?java.io.* 中,?#8220;Stream”l尾的类一般是用来操作“字节?#8221;的类Q以“Reader”Q?#8220;Writer”l尾的类一般是用来操作“字符?#8221;的类?/p>
// 字符串与字节串间怺转化

// 按照 GB2312 得到字节Q得到多字节字符Ԍ

byte
[] bytes = string.getBytes("GB2312");

// 从字节按?GB2312 得到 UNICODE 字符?/span>
string = new String(bytes, "GB2312");

// 要将 String 按照某种~码写入文本文gQ有两种ҎQ?br />
// W一U办法:?Stream cd入已l按照指定编码{化好的字节串

OutputStream os = new FileOutputStream("1.txt");
os.write(bytes);
os.close();

// W二U办法:构造指定编码的 Writer 来写入字W串
Writer ow = new OutputStreamWriter(new FileOutputStream("2.txt"), "GB2312");
ow.write(string);
ow.close();

/* 最后得到的 1.txt ?2.txt 都是 7 个字?*/

如果 java 的源E序~码与当前默?ANSI ~码不符Q则在编译的时候,需要指明一下源E序的编码。比如:

E:\>javac -encoding BIG5 Hello.java

以上需要注意区分源E序的编码与 I/O 操作的编码,前者是在编译时起作用,后者是在运行时起作用?/p>
 

3. 几种误解Q以及ؕ码生的原因和解军_?/h4>

3.1 Ҏ产生的误?/h5>
  对编码的误解
误解一 在将“字节?#8221;转化?#8220;UNICODE 字符?#8221;Ӟ比如在读取文本文件时Q或者通过|络传输文本ӞҎ?#8220;字节?#8221;单地作ؓ单字节字W串Q采用每“一个字?#8221;是“一个字W?#8221;的方法进行{化?br />
而实际上Q在非英文的环境中,应该?#8220;字节?#8221;作ؓ ANSI 字符Ԍ采用适当的编码来得到 UNICODE 字符Ԍ有可?#8220;多个字节”才能得到“一个字W?#8221;?br />
通常Q一直在英文环境下做开发的E序员们Q容易有q种误解?/td>
误解?/td> ?DOSQWindows 98 {非 UNICODE 环境下,字符串都是以 ANSI ~码的字节Ş式存在的。这U以字节形式存在的字W串Q必ȝ道是哪种~码才能被正地使用。这使我们Ş成了一个惯性思维Q?#8220;字符串的~码”?br />
?UNICODE 被支持后QJava 中的 String 是以字符?#8220;序号”来存储的Q不是以“某种~码的字?#8221;来存储的Q因此已l不存在“字符串的~码”q个概念了。只有在“字符?#8221;?#8220;字节?#8221;转化Ӟ或者,一?#8220;字节?#8221;当成一?ANSI 字符串时Q才有编码的概念?br />
不少的h都有q个误解?/td>

W一U误解,往往是导致ؕ码生的原因。第二种误解Q往往D本来ҎU正的ؕ码问题变得更复杂?/p>

在这里,我们可以看到Q其中所讲的“误解一”Q即采用?#8220;一个字?#8221;是“一个字W?#8221;的{化方法,实际上也q同于采用 iso-8859-1 q行转化。因此,我们常常使用 bytes = string.getBytes("iso-8859-1") 来进行逆向操作Q得到原始的“字节?#8221;。然后再使用正确?ANSI ~码Q比?string = new String(bytes, "GB2312")Q来得到正确?#8220;UNICODE 字符?#8221;?/p>
 

3.2 ?UNICODE E序在不同语a环境间移植时的ؕ?/h5>

?UNICODE E序中的字符Ԍ都是以某U?ANSI ~码形式存在的。如果程序运行时的语a环境与开发时的语a环境不同Q将会导?ANSI 字符串的昄p|?/p>

比如Q在日文环境下开发的?UNICODE 的日文程序界面,拿到中文环境下运行时Q界面上显CZؕ码。如果这个日文程序界面改为采?UNICODE 来记录字W串Q那么当在中文环境下q行Ӟ界面上将可以昄正常的日文?/p>

׃客观原因Q有时候我们必d中文操作pȝ下运行非 UNICODE 的日文YӞq时我们可以采用一些工P比如Q南极星QAppLocale {,暂时的模拟不同的语言环境?/p>
 

3.3 |页提交字符?/h5>

当页面中的表单提交字W串Ӟ首先把字W串按照当前面的编码,转化成字节串。然后再每个字节{化成 "%XX" 的格式提交到 Web 服务器。比如,一个编码ؓ GB2312 的页面,提交 "? q个字符串时Q提交给服务器的内容?"%D6%D0"?/p>

在服务器端,Web 服务器把收到?"%D6%D0" 转化?[0xD6, 0xD0] 两个字节Q然后再Ҏ GB2312 ~码规则得到 "? 字?/p>

?Tomcat 服务器中Qrequest.getParameter() 得到qӞ常常是因为前面提到的“误解一”造成的。默认情况下Q当提交 "%D6%D0" l?Tomcat 服务器时Qrequest.getParameter() 返?[0x00D6, 0x00D0] 两个 UNICODE 字符Q而不是返回一?"? 字符。因此,我们需要?bytes = string.getBytes("iso-8859-1") 得到原始的字节串Q再?string = new String(bytes, "GB2312") 重新得到正确的字W串 "??/p>
 

3.4 从数据库d字符?/h5>

通过数据库客LQ比?ODBC ?JDBCQ从数据库服务器中读取字W串Ӟ客户端需要从服务器获知所使用?ANSI ~码。当数据库服务器发送字节流l客LӞ客户端负责将字节按照正的~码转化?UNICODE 字符丌Ӏ?/p>

如果从数据库d字符串时得到qQ而数据库中存攄数据又是正确的,那么往往q是因ؓ前面提到?#8220;误解一”造成的。解决的办法q是通过 string = new String( string.getBytes("iso-8859-1"), "GB2312") 的方法,重新得到原始的字节串Q再重新使用正确的编码{化成字符丌Ӏ?/p>
 

3.5 电子邮g中的字符?/h5>

当一D?Text 或?HTML 通过电子邮g传送时Q发送的内容首先通过一U指定的字符~码转化?#8220;字节?#8221;Q然后再?#8220;字节?#8221;通过一U指定的传输~码QContent-Transfer-EncodingQ进行{化得到另一?#8220;字节?#8221;。比如,打开一电子邮件源代码Q可以看到类似的内容Q?/p>
Content-Type: text/plain;
        charset="gb2312"
Content-Transfer-Encoding: base64

sbG+qcrQuqO17cf4yee74bGjz9W7+b3wudzA7dbQ0MQNCg0KvPKzxqO6uqO17cnnsaPW0NDEDQoNCg==

最常用?Content-Transfer-Encoding ?Base64 ?Quoted-Printable 两种。在对二q制文g或者中文文本进行{化时QBase64 得到?#8220;字节?#8221;?Quoted-Printable 更短。在对英文文本进行{化时QQuoted-Printable 得到?#8220;字节?#8221;?Base64 更短?/p>

邮g的标题,用了一U更短的格式来标?#8220;字符~码”?#8220;传输~码”。比如,标题内容?"?Q则在邮件源代码中表CZؓQ?/p>
// 正确的标题格?/span>
Subject: =?GB2312?B?1tA=?=

其中Q?/p>

  • W一?#8220;=?”?#8220;?”中间的部分指定了字符~码Q在q个例子中指定的?GB2312?
  • “?”?#8220;?”中间?#8220;B”代表 Base64。如果是“Q”则代?Quoted-Printable?
  • 最?#8220;?”?#8220;?=”之间的部分,是l过 GB2312 转化成字节串Q再l过 Base64 转化后的标题内容?

如果“传输~码”改ؓ Quoted-PrintableQ同P如果标题内容?"?Q?/p>
// 正确的标题格?/span>
Subject: =?GB2312?Q?=D6=D0?=

如果阅读邮g时出Cؕ码,一般是因ؓ“字符~码”?#8220;传输~码”指定有误Q或者是没有指定。比如,有的发邮件组件在发送邮件时Q标?"?Q?/p>
// 错误的标题格?/span>
Subject: =?ISO-8859-1?Q?=D6=D0?=

q样的表C,实际上是明确指明了标题ؓ [0x00D6, 0x00D0]Q即 "ÖÐ"Q而不?"??/p>
 

4. 几种错误理解的纠?/h4>

误解Q?#8220;ISO-8859-1 是国际编码?”

非也。iso-8859-1 只是单字节字W集中最单的一U,也就?#8220;字节~号”?#8220;UNICODE 字符~号”一致的那种~码规则。当我们要把一?#8220;字节?#8221;转化?#8220;字符?#8221;Q而又不知道它是哪一U?ANSI ~码Ӟ先暂时地?#8220;每一个字?#8221;作ؓ“一个字W?#8221;q行转化Q不会造成信息丢失。然后再使用 bytes = string.getBytes("iso-8859-1") 的方法可恢复到原始的字节丌Ӏ?/p>

误解Q?#8220;Java 中,怎样知道某个字符串的内码Q?#8221;

Java 中,字符串类 java.lang.String 处理的是 UNICODE 字符Ԍ不是 ANSI 字符丌Ӏ我们只需要把字符串作?#8220;抽象的符L?#8221;来看待。因此不存在字符串的内码的问题?/p>

 



happytian 2007-10-24 09:33 发表评论
]]>消除jsp中getҎ传递中文参数的q问题http://www.tkk7.com/happytian/archive/2007/08/27/139739.htmlhappytianhappytianMon, 27 Aug 2007 01:43:00 GMThttp://www.tkk7.com/happytian/archive/2007/08/27/139739.htmlhttp://www.tkk7.com/happytian/comments/139739.htmlhttp://www.tkk7.com/happytian/archive/2007/08/27/139739.html#Feedback2http://www.tkk7.com/happytian/comments/commentRss/139739.htmlhttp://www.tkk7.com/happytian/services/trackbacks/139739.htmlsudo vim server.xml
在如下添加红色部?br> <!-- Define a non-SSL Coyote HTTP/1.1 Connector on port 8080 -->
    <Connector port="8080"
               maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
               enableLookups="false" redirectPort="8443" acceptCount="100"
               debug="0" connectionTimeout="20000"
               disableUploadTimeout="true" URIEncoding="UTF-8或GBK"/>
    <!-- Note : To disable connection timeouts, set connectionTimeout value
     to 0 -->
保存Q重启tomcat卛_
注意
l一资源标识W?(Uniform Resource Identifier, URI)
l一资源定位W?(Uniform Resource Locator, URL)

happytian 2007-08-27 09:43 发表评论
]]>
dLDAP http://www.tkk7.com/happytian/archive/2007/08/22/138565.htmlhappytianhappytianWed, 22 Aug 2007 03:58:00 GMThttp://www.tkk7.com/happytian/archive/2007/08/22/138565.htmlhttp://www.tkk7.com/happytian/comments/138565.htmlhttp://www.tkk7.com/happytian/archive/2007/08/22/138565.html#Feedback0http://www.tkk7.com/happytian/comments/commentRss/138565.htmlhttp://www.tkk7.com/happytian/services/trackbacks/138565.htmlHashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL,"ldap://192.***.***.***:portNumber(389 is defualt)"Q?
env.put(Context.SECURITY_PRINCIPAL,userID+"yourDomain(@***.com)");//
env.put(Context.SECURITY_CREDENTIALS, pass);
userID ?nbsp;pass是d域的账号。不要用全称。因Z在上面用C域名?br>2Q开始验证。通过try..catch来判断用L合法性?br>try{
LdapContext ctx = new InitialLdapContext(env, null);
System.out.println("Succeess");
} catch QException e) {
if (e.getMessage().indexOf("775") > = 0) {
System.out.println("你的账号被锁了?);
}else {
System.out.println("Invalid User");
}
}

happytian 2007-08-22 11:58 发表评论
]]>
վ֩ģ壺 ѹۿƵ㶮| ޹Ƶվ| ƵƷ| ߹ۿƵ| һһƬƵ| ޾Ʒþþþϼ| Ƶ| AVһϵ| AVһ | þþƷ˵| زѿ| 91ƷѹƬ| պѸƬ| Ʒվ| Ʒav벻| Ʒ˿| ŷ޹˾Ʒ| ƵƷ| vavavaĻ| þñѵӰˬˬˬ| Ļһþ| ޵һ߹ۿ| ֻˬһëƬѹۿ| ձһһѿ | 쾫Ʒ߹ۿ| ŷղվ| һػƴƬëƬ| ޵һƬȫ| ޹Ʒһþ| Ůǿ߳վ | ߹ۿ| ëƬƵ| va߹ۿ| ɫһ| ޺Сvideos| 91͵߹ۿ| ++ۺ+ר| պƷAV| ˳վ߹ۿ| ˳Ƶ߹ۿ| Ƶѹۿ|