??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲午夜爱爱香蕉片,国产亚洲美女精品久久久2020,亚洲国产夜色在线观看http://www.tkk7.com/fundei/江苏520zh-cnSun, 11 May 2025 11:15:33 GMTSun, 11 May 2025 11:15:33 GMT60字符Q字节和~码三者的关系http://www.tkk7.com/fundei/archive/2009/06/03/279886.html江苏520江苏520Wed, 03 Jun 2009 12:19:00 GMThttp://www.tkk7.com/fundei/archive/2009/06/03/279886.html1. ~码问题的由来,相关概念的理?br /> 1.1 字符与编码的发展
从计机对多国语a的支持角度看Q大致可以分Z个阶D:

  pȝ内码 说明 pȝ
阶段一 ASCII 计算机刚开始只支持pQ其它语a不能够在计算Z存储和显C?英文 DOS
阶段?ANSI~码
Q本地化Q?Z计算机支持更多语aQ通常使用 0x80~0xFF 范围?2 个字节来表示 1 个字W。比如:汉字 '? 在中文操作系l中Q?[0xD6,0xD0] q两个字节存储?/p>

不同的国家和地区制定了不同的标准Q由此生了 GB2312, BIG5, JIS {各自的~码标准。这些?2 个字节来代表一个字W的各种汉字延׾~码方式Q称?ANSI ~码。在体中文系l下QANSI ~码代表 GB2312 ~码Q在日文操作pȝ下,ANSI ~码代表 JIS ~码?/p>

不同 ANSI ~码之间互不兼容Q当信息在国际间交流Ӟ无法属于两U语a的文字,存储在同一D?ANSI ~码的文本中?中文 DOSQ中?Windows 95/98Q日?Windows 95/98
阶段?UNICODE
Q国际化Q?Z使国际间信息交流更加方便Q国际组l制定了 UNICODE 字符集,为各U语a中的每一个字W设定了l一q且唯一的数字编P以满语言、跨q_q行文本转换、处理的要求?Windows NT/2000/XPQLinuxQJava

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

?ASCII 阶段Q单字节字符串用一个字节存放一个字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。比如,"中文123" 在中?Windows 95 内存中ؓ7个字节,每个汉字?个字节,每个英文和数字字W占1个字节:

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

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

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

一共占 10 个字节?/p>

 
 回页?br />  
 
 

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

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

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

 
 回页?br />  
 
 

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

使用哪些字符。也是说哪些汉字,字母和符号会被收入标准中。所包含“字符”的集合就叫做“字符?#8221;?
规定每个“字符”分别用一个字节还是多个字节存储,用哪些字节来存储Q这个规定就叫做“~码”?
各个国家和地区在制定~码标准的时候,“字符的集?#8221;?#8220;~码”一般都是同时制定的。因此,q_我们所说的“字符?#8221;Q比如:GB2312, GBK, JIS {,除了?#8220;字符的集?#8221;q层含义外,同时也包含了“~码”的含义?/p>

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

  

1.4 常用的编码简?br /> 单介l一下常用的~码规则Qؓ后边的章节做一个准备。在q里Q我们根据编码规则的特点Q把所有的~码分成三类Q?/p>

分类 ~码标准 说明
单字节字W编?ISO-8859-1 最单的~码规则Q每一个字节直接作Z?UNICODE 字符。比如,[0xD6, 0xD0] q两个字节,通过 iso-8859-1 转化为字W串Ӟ直接得?[0x00D6, 0x00D0] 两个 UNICODE 字符Q即 "ÖÐ"?/p>

反之Q将 UNICODE 字符串通过 iso-8859-1 转化为字节串Ӟ只能正常转化 0~255 范围的字W?
ANSI ~码 GB2312,
BIG5,
Shift_JIS,
ISO-8859-2 …… ?UNICODE 字符串通过 ANSI ~码转化?#8220;字节?#8221;ӞҎ各自~码的规定,一?UNICODE 字符可能转化成一个字节或多个字节?/p>

反之Q将字节串{化成字符串时Q也可能多个字节转化成一个字W。比如,[0xD6, 0xD0] q两个字节,通过 GB2312 转化为字W串Ӟ得?[0x4E2D] 一个字W,?'? 字?/p>

“ANSI ~码”的特点:
1. q些“ANSI ~码标准”都只能处理各自语a范围之内?UNICODE 字符?br /> 2. “UNICODE 字符”?#8220;转换出来的字?#8221;之间的关pLZؓ规定的?
UNICODE ~码 UTF-8,
UTF-16, UnicodeBig …… ?#8220;ANSI ~码”cM的,把字W串通过 UNICODE ~码转化?#8220;字节?#8221;Ӟ一?UNICODE 字符可能转化成一个字节或多个字节?/p>

?#8220;ANSI ~码”不同的是Q?br /> 1. q些“UNICODE ~码”能够处理所有的 UNICODE 字符?br /> 2. “UNICODE 字符”?#8220;转换出来的字?#8221;之间是可以通过计算得到的?

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

 

2. 字符与编码在E序中的实现
2.1 E序中的字符与字?br /> ?C++ ?Java 中,用来代表“字符”?#8220;字节”的数据类型,以及q行~码的方法:

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

以上需要注意几点:

Java 中的 char 代表一?#8220;UNICODE 字符Q宽字节字符Q?#8221;Q?C++ 中的 char 代表一个字节?
MultiByteToWideChar() ?WideCharToMultiByte() ?Windows API 函数?nbsp;

  

2.2 C++ 中相兛_现方?br /> 声明一D字W串帔RQ?/p>

// ANSI 字符Ԍ内容长度 7 字节
char     sz[20] = "中文123";

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

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

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

// GCC 中格?br /> 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序使用的编?br /> #pragma setlocale(".936")

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

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

 
  

2.3 Java 中相兛_现方?br /> 字符串类 String 中的内容?UNICODE 字符Ԍ

// Java 代码Q直接写中文
String string = "中文123";//come from http://www.bt285.cn  http://www.5a520.cn

// 得到长度?5Q因为是 5 个字W?br /> 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 字符?br /> string = new String(bytes, "GB2312");

// 要将 String 按照某种~码写入文本文gQ有两种ҎQ?/p>

// 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以及ؕ码生的原因和解军_?br /> 3.1 Ҏ产生的误?br />   对编码的误解
误解一 在将“字节?#8221;转化?#8220;UNICODE 字符?#8221;Ӟ比如在读取文本文件时Q或者通过|络传输文本ӞҎ?#8220;字节?#8221;单地作ؓ单字节字W串Q采用每“一个字?#8221;是“一个字W?#8221;的方法进行{化?/p>

而实际上Q在非英文的环境中,应该?#8220;字节?#8221;作ؓ ANSI 字符Ԍ采用适当的编码来得到 UNICODE 字符Ԍ有可?#8220;多个字节”才能得到“一个字W?#8221;?/p>

通常Q一直在英文环境下做开发的E序员们Q容易有q种误解?
误解??DOSQWindows 98 {非 UNICODE 环境下,字符串都是以 ANSI ~码的字节Ş式存在的。这U以字节形式存在的字W串Q必ȝ道是哪种~码才能被正地使用。这使我们Ş成了一个惯性思维Q?#8220;字符串的~码”?/p>

?UNICODE 被支持后QJava 中的 String 是以字符?#8220;序号”来存储的Q不是以“某种~码的字?#8221;来存储的Q因此已l不存在“字符串的~码”q个概念了。只有在“字符?#8221;?#8220;字节?#8221;转化Ӟ或者,一?#8220;字节?#8221;当成一?ANSI 字符串时Q才有编码的概念?/p>

不少的h都有q个误解?

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环境间移植时的ؕ?br /> ?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 |页提交字符?br /> 当页面中的表单提交字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字符?br /> 通过数据库客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中的字符?br /> 当一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>

// 正确的标题格?br /> 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>

// 正确的标题格?br /> Subject: =?GB2312?Q?=D6=D0?=

如果阅读邮g时出Cؕ码,一般是因ؓ“字符~码”?#8220;传输~码”指定有误Q或者是没有指定。比如,有的发邮件组件在发送邮件时Q标?"?Q?/p>

// 错误的标题格?br /> Subject: =?ISO-8859-1?Q?=D6=D0?=

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


 
 

4. 几种错误理解的纠?br /> 误解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>

 

 



江苏520 2009-06-03 20:19 发表评论
]]>
java异常处理W记http://www.tkk7.com/fundei/archive/2009/06/02/279698.html江苏520江苏520Tue, 02 Jun 2009 13:39:00 GMThttp://www.tkk7.com/fundei/archive/2009/06/02/279698.html阅读全文

江苏520 2009-06-02 21:39 发表评论
]]>
java多线E问题及处理(W记)http://www.tkk7.com/fundei/archive/2009/05/31/279280.html江苏520江苏520Sun, 31 May 2009 12:53:00 GMThttp://www.tkk7.com/fundei/archive/2009/05/31/279280.html1.死锁
         多线E编E在实际的网l程序开发中Q在客户端程序实C使用的比较简单,但是在服务器端程序实C却不仅是大量使用Q而且会出现比客户端更多的问题?/p>

         另外一个容易在服务器端出现的多U程问题是——死锁。死锁指两个或两个以上的U程Z使用某个临界资源而无限制的等待下厅R还是以前面卫生间的例子来说明死锁,例如两个人都同时到达卫生_而且两个人都比较CDQ第一个h和第二个Q你先吧Q第二个人和W一个h_你先吧。这两个人就q样一直在互相CDQ谁也不q入Q这U现象就是死锁。这里的两个人就好比是线E,而卫生间在这里就是界资源,而由于这两个U程在一直谦让,谁也不用界资源?/p>

         死锁不仅使程序无法达到预期实现的功能Q而且费pȝ的资源,所以在服务器端E序中危x较大Q在实际的服务器端程序开发中Q需要注意避免死锁?/p>

         而死锁的比较麻烦,而且不一定每ơ都出现Q这需要在试服务器端E序Ӟ有够的耐心Q仔l观察程序执行时的性能,如果发现执行的性能显著降低Q则很可能是发生了死锁,然后再具体的查找死锁出现的原因,q解x锁的问题?/p>

         死锁出现的最本质原因q是逻辑处理不够严}Q在考虑时不是很周全Q所以一般需要修改程序逻辑才能够很好的解决死锁?/p>

2. U程优先U?br />          在日常生zMQ例如火车售窗口等l常可以看到“XXX优先”Q那么多U程~程中每个线E是否也可以讄优先U呢Q?/p>

         在多U程~程中,支持为每个线E设|优先。优先高的U程在排队执行时会获得更多的CPU执行旉Q得到更快的响应。在实际E序中,可以Ҏ逻辑的需要,需要得到及时处理的U程讄成较高的优先U,而把Ҏ间要求不高的U程讄成比较低的优先?/p>

         在ThreadcMQ总计规定了三个优先Q分别ؓQ?/p>

l  MAX_PRIORITY——最高优先

l  NORM_PRIORITY——普通优先Q也是默认优先

l  MIN_PRIORITY——最低优先

在前面创建的U程对象中,׃没有讄U程的优先Q则U程默认的优先是NORM_PRIORITYQ在实际使用Ӟ也可以根据需要用ThreadcM的setPriorityҎ讄U程的优先Q该Ҏ的声明ؓQ?/p>

         public final void setPriority(int newPriority)

假设t是一个初始化q的U程对象Q需要设|t的优先为最高,则实现的代码为:

         t. setPriority(Thread. MAX_PRIORITY);

q样Q在该线E执行时获得更多的执行ZQ也是优先执行。如果由于安全等原因Q不允许讄U程的优先Q则会抛出SecurityException异常?/p>

下面使用一个简单的输出数字的线E演C线E优先的用,实现的示例代码如下:

         package priority;

/**

 * 试U程优先U?br />

* author by http://www.bt285.cn http://www.5a520.cn

 */

public class TestPriority {

         public static void main(String[] args) {

                   PrintNumberThread p1 = new PrintNumberThread("高优先");

                   PrintNumberThread p2 = new PrintNumberThread("普通优先");

                   PrintNumberThread p3 = new PrintNumberThread("低优先");

                   p1.setPriority(Thread.MAX_PRIORITY);

                   p2.setPriority(Thread.NORM_PRIORITY);

                   p3.setPriority(Thread.MIN_PRIORITY);

                   p1.start();

                   p2.start();

                   p3.start();

         }

}

package priority;

/**

 * 输出数字的线E?/p>

 */

public class PrintNumberThread extends Thread {

         String name;

         public PrintNumberThread(String name){

                   this.name = name;

         }

         public void run(){

                   try{

                            for(int i = 0;i < 10;i++){

                                     System.out.println(name + ":" + i);

                            }

                   }catch(Exception e){}

         }

}

E序的一U执行结果ؓQ?/p>

高优先:0

高优先:1

高优先:2

普通优先:0

高优先:3

普通优先:1

高优先:4

普通优先:2

高优先:5

高优先:6

高优先:7

高优先:8

高优先:9

普通优先:3

普通优先:4

普通优先:5

普通优先:6

普通优先:7

普通优先:8

普通优先:9

低优先:0

低优先:1

低优先:2

低优先:3

低优先:4

低优先:5

低优先:6

低优先:7

低优先:8

低优先:9

         在该CZE序QPrintNumberThreadU程实现的功能是输出数字Q每ơ数字输Z间没有设|时间gq,在测试类TestPriority中创Z个PrintNumberThreadcd的线E对象,然后分别讄U程优先U是最高、普通和最低,接着启动U程执行E序。从执行l果可以看出高优先的线E获得了更多的执行时_首先执行完成Q而低优先U的U程׃优先U较低,所以最后一个执行结束?/p>

         其实Q对于线E优先的管理主要由pȝ的线E调度实玎ͼ较高优先U的U程优先执行Q所以可以通过讄U程的优先影响U程的执行?/p>

5 ȝ
         关于多线E的基础知识׃l这么多Q在本章中介l了U程的概c线E的实现方式以及使用多线E时会遇到的问题以及解决办法Q而需要徏立多U程的概念,也就是ƈ发编E的概念q需要进行比较多的练习,理解多线E的概念q熟悉多U程的编E?/p>

         而关于多U程~程的高U知识,如线E组{则可以在熟悉了U程的基本概念以后再q行更加深入的学习?/p>

 

 



江苏520 2009-05-31 20:53 发表评论
]]>
从JAR与zip档案文g中提取Java 资源http://www.tkk7.com/fundei/archive/2009/05/29/277883.html江苏520江苏520Fri, 29 May 2009 11:56:00 GMThttp://www.tkk7.com/fundei/archive/2009/05/29/277883.html多数 java E序员都非常清楚使用 jar 文g组?/span> java 解决Ҏ的各U资源(?/span> .class 文g、声韛_囑փQ打包的优点。刚开始?/span> jar 文g的h帔R的一个问题是Q?#8220;如何?/span> jar 文g中提取图像呢Q?#8221;本文回{这个问题,q会提供一个类Q这个类使从 jar 文g中提取Q何资源变得非常简单!
加蝲 gif 囑փ
   
假定我们有一?/span> jar 文gQ其中包含我们的应用E序要用的一l?/span> .gif 囑փ。下面就是?/span> JarResources 讉K jar 文g中的囑փ文g的方法:
    JarResources JR=new JarResources(" http://www.bt285.cn /GifBundle.jar");


    Image logo=Toolkit.getDefaultToolkit().createImage(JR.getResources("logo.gif"));

    
q段代码说明我们可以创徏一?/span>JarResources对象Qƈ其初始化ؓ包含我们要用的资源?/span> jar 文g -- images.jar。随后我们?/span>JarResources?/span>getResource()Ҏ来?/span> logo.gif 文g的原始数据提供给 awt Toolkit ?/span>createImage()Ҏ?/span>
命名说明
JarResource
是一个非常简单的CZQ它说明了如何?/span> java 所提供的各U功能来处理 jar ?/span> zip 档案文g?/span>

 
工作方式

JarReourcescȝ重要数据域用来跟t和存储指定 jar 文g的内容:
public final class JarResources {

   public boolean debugon=false;

   private Hashtable htsizes=new Hashtable();
   private Hashtable htjarcontents=new Hashtable();

   private String jarfilename;

q样Q该cȝ实例化设|?/span> jar 文g的名Uͼ然后转到init()Ҏ完成全部实际工作?/span>
   public JarResources(String jarfilename) {
      this.jarfilename=jarfilename;
      init();
   }

现在Q?/span>init()Ҏ只将指定 jar 文g的整个内容加载到一?/span> hashtableQ通过资源名访问)中?/span>

     
q是一个相当有用的ҎQ下面我们对它作q一步的分析?/span>ZipFilecMؓ我们提供了对 jar/zip 档案头信息的基本讉KҎ。这cM于文件系l中的目录信息。下面我们列?/span>ZipFile中的所有条目,q用档案中每个资源的大小d htsizes hashtableQ?/span>
 private void init() {
      try {
          // extracts just sizes only. 
          ZipFile zf=new ZipFile(jarFileName);
          Enumeration e=zf.entries();
          while (e.hasMoreElements()) {
              ZipEntry ze=(ZipEntry)e.nextElement();
              if (debugOn) {
                 System.out.println(dumpZipEntry(ze));
              }
              htSizes.put(ze.getName(),new Integer((int)ze.getSize()));
          }
          zf.close();
接下来,我们使用ZipInputStreamc访问档案?/span>ZipInputStreamcd成了全部术Q允许我们单独读取档案中的每个资源。我们从档案中读取组成每个资源的_字节敎ͼq将其存储在 htjarcontents hashtable 中,您可以通过资源名访问这些数据:     
          // extract resources and put them into the hashtable.
          FileInputStream fis=new FileInputStream(jarFileName);
          BufferedInputStream bis=new BufferedInputStream(fis);
          ZipInputStream zis=new ZipInputStream(bis);
          ZipEntry ze=null;
          while ((ze=zis.getNextEntry())!=null) {
             if (ze.isDirectory()) {
                continue;////啊哟!没有处理子目录中的资源啊 http://www.5a520.cn  说520|?/span>
             }
             if (debugOn) {
                System.out.println(
                   "ze.getName()="+ze.getName()+","+"getSize()="+ze.getSize()
                   );
             }
             int size=(int)ze.getSize();
             // -1 means unknown size. 
             if (size==-1) {
                size=((Integer)htSizes.get(ze.getName())).intValue();
             }
             byte[] b=new byte[(int)size];
             int rb=0;
             int chunk=0;
            while (((int)size - rb) > 0) {
                 chunk=zis.read(b,rb,(int)size - rb);
                 if (chunk==-1) {
                    break;
                 }
                 rb+=chunk;
             }
             // add to internal resource hashtable
             htJarContents.put(ze.getName(),b);
             if (debugOn) {
                System.out.println(
                   ze.getName()+" rb="+rb+
                   ",size="+size+
                   ",csize="+ze.getCompressedSize()
                   );
             }
          }
       } catch (NullPointerException e) {
          System.out.println("done.");
       } catch (FileNotFoundException e) {
          e.printStackTrace();
       } catch (IOException e) {
          e.printStackTrace();
       }
   }
h意,用来标识每个资源的名U是档案中资源的限定路径名,例如Q?em>不是包中的类?/span> -- ?/span> java.util.zip 包中?/span>ZipEntrycd被命名ؓ "java/util/zip/ZipEntry"Q而不?/span> "java.util.zip.ZipEntry"?/span>

其它Ҏ:
    /**
    * Dumps a zip entry into a string.
    * @param ze a ZipEntry
    */
   private String dumpZipEntry(ZipEntry ze) {
       StringBuffer sb=new StringBuffer();
       if (ze.isDirectory()) {
          sb.append("d "); 
       } else {
          sb.append("f "); 
       }
       if (ze.getMethod()==ZipEntry.STORED) {
          sb.append("stored   "); 
       } else {
          sb.append("defalted ");
       }
       sb.append(ze.getName());
       sb.append("\t");
       sb.append(""+ze.getSize());
       if (ze.getMethod()==ZipEntry.DEFLATED) {
          sb.append("/"+ze.getCompressedSize());
       }
       return (sb.toString());
   }

    /**
    * Extracts a jar resource as a blob.
    * @param name a resource name.
    */
   public byte[] getResource(String name) {
      return (byte[])htJarContents.get(name);
   }
      
代码的最后一个重要部分是单的试驱动E序。该试驱动E序是一个简单的应用E序Q它接收 jar/zip 档案名和资源名。它试图发现档案中的资源文gQ然后将成功或失败的消息报告出来Q?/span>
public static void main(String[] args) throws IOException {
       if (args.length!=2) {
          System.err.println(
             "usage: java JarResources < jar file name> < resource name>"
             );
          System.exit(1);
       }
       JarResources jr=new JarResources(args[0]);
       byte[] buff=jr.getResource(args[1]);
       if (buff==null) {
          System.out.println("Could not find "+args[1]+".");
       } else {
          System.out.println("Found "+args[1]+ " (length="+buff.length+").");
       }
   }
}              // End of JarResources class.
您已了解了这个类。一个易于用的c,它隐藏了使用打包?/span> jar 文g中的资源的全部棘手问题?/span>

如果您曾l望知道如何从 jar 文g中提取图像,那么您现在已学到了一U方法。有了本技巧提供的q个新类Q您׃仅可以用 jar 文g处理囑փQ而且可以提取魔术用?/span> jar 文g中的M资源?/span> 


江苏520 2009-05-29 19:56 发表评论
]]>
JSP面查询昄常用模式http://www.tkk7.com/fundei/archive/2009/05/27/277882.html江苏520江苏520Wed, 27 May 2009 13:36:00 GMThttp://www.tkk7.com/fundei/archive/2009/05/27/277882.html背景Q?br /> 1Q?nbsp;   需要将数据库查询结果在JSP中以列表方式昄
2Q?nbsp;   在一个良好的J2EE模式中数据库查询一般用DAO实现QData Access ObjectQ, JSP仅用于显C数?br />
问题Q?br />     通过JDBC ResultSet可获取查询结果(存在于数据库~冲区内Q,但在Statement、Connection关闭后ResultSet即不可用。因此需要一U方式取出所有查询结果ƈ传递至JSP面?br />
解决Ҏ一Q?br />     使用Value Object。将每条记录均封装成JavaBean对象Q如Q?a >http://www.bt285.cn 把这些对象装入Collection传送给JSP昄。这U方法的~点是每一U查询都需要定义一个java classQƈ且将记录数据装成java对象时也需要很多额外的代码?br /> CZ代码Q?br />
  1. //查询数据代码
  2.   Connection conn = DBUtil.getConnection();
  3.   PreparedStatement pst = null;
  4.   ResultSet rs = null;
  5.   try{
  6.     String sql=“select emp_code, real_name from t_employee where organ_id=?”;
  7.     pst = conn.preparedStatement(sql);
  8.     pst.setString(1, “101”);
  9.     ResultSet rs = pst.executeQuery();
  10.     List list = new ArrayList();
  11.     Employee emp;
  12.     while (rs.next()){
  13.       emp = new Employee();
  14.       emp.setReakName(rs.getString(“real_name”));
  15.       emp.setEmpCode(rs.getString(“emp_code”));
  16.       …
  17.       list.add(emp);
  18.     }
  19.     return list;
  20.   }finally{
  21.     DBUtil.close(rs, pst ,conn);
  22.   }
  23. //jsp昄部分代码
  24. <%
  25.   List empList = (List)request.getAttribute(“empList”);
  26.   if (empList == null) empList = Collections.EMPTY_LIST;
  27. %>
  28. <table  cellspacing="0" width=”90%”>
  29.     <tr>  <td> http://www.5a520.cn   说520|?代码</td> <td>姓名</td>  </tr>
  30. <%
  31.   Employee emp;
  32.   for (int i=0; i< empList.size(); i++){
  33.     emp = (Employee) empList.get(i);
  34. %>
  35.     <tr>  
  36.       <td><%= emp.getEmpCode()%></td> 
  37.       <td><%= emp.getRealName()%></td>  
  38.     </tr>
  39. <%
  40.   }// end for
  41. %>
  42. </table>


解决Ҏ?/strong>Q?br />     遍历ResultSet取出所有数据封装进Collection?br /> 具体做法Q?br /> 1Q?nbsp;   生成一个List对象(List list = new ArrayList() )?br /> 2Q?nbsp;   生成一个Map对象(Map map = new HashMap() )。用Map装一行数据,key为各字段名,value为对应的倹{?map.put(“USER_NAME”), rs.getString(“USER_NAME”))
3Q?nbsp;   第2 步生成的Map对象装入W?步的list对象?list.add(map) )?br /> 4Q?nbsp;   重复2?步直到ResultSet遍历完毕
在DBUtil. resultSetToList(ResultSet rs)Ҏ中实C上述q程Q所有列名均使用大写Q,可参考用?br />
CZ代码Q?br />
  1. //查询数据部分代码Q?/em>
  2.   …
  3.   Connection conn = DBUtil.getConnection();
  4.   PreparedStatement pst = null;
  5.   ResultSet rs = null;
  6.   try{
  7.     String sql=“select emp_code, real_name from t_employee where organ_id=?”;
  8.     pst = conn.preparedStatement(sql);
  9.     pst.setString(1, “101”);
  10.     rs = pst.executeQuery();
  11.     List list = DBUtil. resultSetToList(ResultSet rs);
  12.     return list;
  13.   }finally{
  14.     DBUtil.close(rs, pst ,conn);
  15.   }
  16. //JSP昄部分代码
  17. <%
  18.   List empList = (List)request.getAttribute(“empList”);
  19.   if (empList == null) empList = Collections.EMPTY_LIST;
  20. %>
  21. <table  cellspacing="0" width=”90%”>
  22.     <tr>  <td> http://www.feng123.com 蜂蜜 代码</td> <td>姓名</td>  </tr>
  23. <%
  24.   Map colMap;
  25.   for (int i=0; i< empList.size(); i++){
  26.     colMap = (Map) empList.get(i);
  27. %>
  28.   <tr>  
  29.     <td><%=colMap.get(“EMP_CODE”)%></td> 
  30.     <td><%=colMap.get(“REAL_NAME”)%></td>  
  31.   </tr>
  32. <%
  33.   }// end for
  34. %>
  35. </table>


解决Ҏ?/strong>Q?br />     使用RowSet?br /> RowSet是JDBC2.0中提供的接口,Oracle对该接口有相应实玎ͼ其中很有用的是oracle.jdbc.rowset.OracleCachedRowSet?nbsp;OracleCachedRowSet实现了ResultSet中的所有方法,但与ResultSet不同的是QOracleCachedRowSet中的数据在Connection关闭后仍然有效?br />
oracle的rowset实现?/font>http://otn.oracle.com/software/content.html的jdbc下蝲里有Q名U是ocrs12.zip

CZ代码Q?br />
  1. //查询数据部分代码Q?/em>
  2.   import javax.sql.RowSet;
  3.   import oracle.jdbc.rowset.OracleCachedRowSet;
  4.   …
  5.   Connection conn = DBUtil.getConnection();
  6.   PreparedStatement pst = null;
  7.   ResultSet rs = null;
  8.   try{……
  9.     String sql=“select emp_code, real_name from t_employee where organ_id=?”;
  10.     pst = conn.preparedStatement(sql);
  11.     pst.setString(1, “101”);
  12.     rs = pst.executeQuery();
  13.     OracleCachedRowSet ors = newOracleCachedRowSet();
  14.     //ResultSet中的数据装到RowSet?/em>
  15.     ors.populate(rs);
  16.     return ors;
  17.   }finally{
  18.     DBUtil.close(rs, pst, conn);
  19.   }
  20. //JSP昄部分代码
  21. <%
  22.   javax.sql.RowSet empRS = (javax.sql.RowSet) request.getAttribute(“empRS”);
  23. %>
  24. <table  cellspacing="0" width=”90%”>
  25.     <tr>  <td>代码</td> <td>姓名</td>  </tr>
  26. <%
  27.   if (empRS != nullwhile (empRS.next() ) {
  28. %>
  29.   <tr>  
  30.     <td><%= empRS.get(“EMP_CODE”)%></td> 
  31.     <td><%= empRS.get(“REAL_NAME”)%></td>  
  32.   </tr>
  33. <%
  34.   }// end while
  35. %>
  36. </table>


适用场合Q?br />   Ҏ一使用于定制的查询操作
  Ҏ二适用于多条查询语句或需要对查询l果q行处理的情c?br />   Ҏ三适合于单条查询语句,适用于快速开发?/font>

江苏520 2009-05-27 21:36 发表评论
]]>
java字符集笔?/title><link>http://www.tkk7.com/fundei/archive/2009/05/25/277873.html</link><dc:creator>江苏520</dc:creator><author>江苏520</author><pubDate>Mon, 25 May 2009 11:03:00 GMT</pubDate><guid>http://www.tkk7.com/fundei/archive/2009/05/25/277873.html</guid><description><![CDATA[概述 <br /> <br /> 本文主要包括以下几个斚wQ编码基本知识,javaQ系lYӞurlQ工兯Y件等?nbsp;<br /> <br /> 在下面的描述中,以"中文"两个字ؓ例,l查表可以知道其GB2312~码?d6d0 cec4"QUnicode~码?4e2d 6587"QUTF~码是"e4b8ad e69687"。注意,q两个字没有iso8859-1~码Q但可以用iso8859-1~码?表示"?nbsp;<br /> <br /> 2. ~码基本知识 <br /> <br /> 最早的~码是iso8859-1Q和ascii~码怼。但Z方便表示各种各样的语aQ逐渐出现了很多标准编码,重要的有如下几个?nbsp;<br /> <br /> 2.1. iso8859-1 <br /> <br /> 属于单字节编码,最多能表示的字W范围是0-255Q应用于英文pd。比如,字母'a'的编码ؓ0x61=97?nbsp;<br /> <br /> 很明显,iso8859-1~码表示的字W范围很H,无法表示中文字符。但是,׃是单字节~码Q和计算机最基础的表C单位一_所以很多时候,仍旧使用iso8859-1~码来表C。而且在很多协议上Q默认用该~码。比如,虽然"中文"两个字不存在iso8859-1~码Q以gb2312~码ZQ应该是"d6d0 cec4"两个字符Q用iso8859-1~码的时候则它拆开?个字节来表示Q?d6 d0 ce c4"Q事实上Q在q行存储的时候,也是以字节ؓ单位处理的)。而如果是UTF~码Q则?个字?e4 b8 ad e6 96 87"。很明显Q这U表C方法还需要以另一U编码ؓ基础?nbsp;<br /> <br /> 2.2. GB2312/GBK <br /> <br /> q就是汉子的国标码,专门用来表示汉字Q是双字节编码,而英文字母和iso8859-1一_兼容iso8859-1~码Q。其中gbk~码能够用来同时表示J体字和体字Q而gb2312只能表示体字Qgbk是兼容gb2312~码的?nbsp;<br /> <br /> 2.3. unicode <br /> <br /> q是最l一的编码,可以用来表示所有语a的字W,而且是定长双字节Q也有四字节的)~码Q包括英文字母在内。所以可以说它是不兼容iso8859-1~码的,也不兼容M~码。不q,相对于iso8859-1~码来说Quniocode~码只是在前面增加了一?字节Q比如字?a'?00 61"?nbsp;<br /> <br /> 需要说明的是,定长~码便于计算机处理(注意GB2312/GBK不是定长~码Q,而unicode又可以用来表C所有字W,所以在很多软g内部是用unicode~码来处理的Q比如java?nbsp;<br /> <br /> 2.4. UTF <br /> <br /> 考虑到unicode~码不兼容iso8859-1~码Q而且Ҏ占用更多的空_因ؓ对于英文字母Qunicode也需要两个字节来表示。所以unicode不便于传输和存储。因此而生了utf~码Qutf~码兼容iso8859-1~码Q同时也可以用来表示所有语a的字W,不过Qutf~码是不定长~码Q每一个字W的长度?-6个字节不{。另外,utf~码自带单的校验功能。一般来Ԍ英文字母都是用一个字节表C,而汉字用三个字节?nbsp;<br /> <br /> 注意Q虽然说utf是ؓ了用更的I间而用的Q但那只是相对于unicode~码来说Q如果已l知道是汉字Q则使用GB2312/GBK无疑是最节省的。不q另一斚wQ值得说明的是Q虽然utf~码Ҏ字?个字节,但即使对于汉字网,utf~码也会比unicode~码节省Q因为网中包含了很多的英文字符?nbsp;<br /> <br /> 3. java对字W的处理 <br /> <br /> 在java应用软g中,会有多处涉及到字W集~码Q有些地斚w要进行正的讄Q有些地斚w要进行一定程度的处理?nbsp;<br /> <br /> 3.1. getBytes(charset) <br /> <br /> q是java字符串处理的一个标准函敎ͼ其作用是字W串所表示的字W按照charset~码Qƈ以字节方式表C。注意字W串在java内存中L按unicode~码存储的。比?中文"Q正常情况下Q即没有错误的时候)存储?4e2d 6587"Q如果charset?gbk"Q则被编码ؓ"d6d0 cec4"Q然后返回字?d6 d0 ce c4"。如果charset?utf8"则最后是"e4 b8 ad e6 96 87"。如果是"iso8859-1"Q则׃无法~码Q最后返?nbsp;"3f 3f"Q两个问P?nbsp;<br /> <br /> 3.2. new String(charset) <br /> <br /> q是java字符串处理的另一个标准函敎ͼ和上一个函数的作用相反Q将字节数组按照charset~码q行l合识别Q最后{换ؓunicode存储。参考上qgetBytes的例子,"gbk" ?utf8"都可以得出正的l果"4e2d 6587"Q但iso8859-1最后变成了"003f 003f"Q两个问P?nbsp;<br /> <br /> 因ؓutf8可以用来表示/~码所有字W,所以new String( str.getBytes( "utf8" ), "utf8" ) === strQ即完全可逆?nbsp;<br /> <br /> 3.3. setCharacterEncoding() <br /> <br /> 该函数用来设|httph或者相应的~码?nbsp;<br /> <br /> 对于requestQ是指提交内容的~码Q指定后可以通过getParameter()则直接获得正的字符Ԍ如果不指定,则默认用iso8859-1~码Q需要进一步处理。参见下q?表单输入"。值得注意的是在执行setCharacterEncoding()之前Q不能执行Q何getParameter()。java doc上说明:This method must be called prior to reading request parameters or reading input using getReader()。而且Q该指定只对POSTҎ有效Q对GETҎ无效。分析原因,应该是在执行W一个getParameter()的时候,java会按照~码分析所有的提交内容Q而后l的getParameter()不再q行分析Q所以setCharacterEncoding()无效。而对于GETҎ提交表单是,提交的内容在URL中,一开始就已经按照~码分析所有的提交内容QsetCharacterEncoding()自然无效?nbsp;<br /> <br /> 对于responseQ则是指定输出内容的~码Q同Ӟ该设|会传递给览器,告诉览器输出内Ҏ采用的编码?nbsp;<br /> <br /> 3.4. 处理q程 <br /> <br /> 下面分析两个有代表性的例子Q说明java对编码有关问题的处理Ҏ?nbsp;<br /> <br /> 3.4.1. 表单输入 <br /> <br /> User input  *(gbk:d6d0 cec4)  browser  *(gbk:d6d0 cec4)  web server  iso8859-1(00d6 00d 000ce 00c4)  classQ需要在class中进行处理:getbytes("iso8859-1")为d6 d0 ce c4Qnew String("gbk")为d6d0 cec4Q内存中以unicode~码则ؓ4e2d 6587?nbsp;<br /> <br /> l 用户输入的编码方式和面指定的编码有养I也和用户的操作系l有养I所以是不确定的Q上例以gbkZ?nbsp;<br /> <br /> l 从browser到web serverQ可以在表单中指定提交内Ҏ使用的字W集Q否则会使用面指定的编码。而如果在url中直接用?的方式输入参敎ͼ则其~码往往是操作系l本w的~码Q因时和面无关。上qC旧以gbk~码Z?nbsp;<br /> <br /> l Web server接收到的是字节流Q默认时QgetParameterQ会以iso8859-1~码处理之,l果是不正确的,所以需要进行处理。如 <a >http://www.5a520.cn</a>  说520|?但如果预先设|了~码Q通过request. setCharacterEncoding ()Q,则能够直接获取到正确的结果?nbsp;<br /> <br /> l 在页面中指定~码是个好习惯,否则可能失去控制Q无法指定正的~码?nbsp;<br /> <br /> 3.4.2. 文g~译 <br /> <br /> 假设文g是gbk~码保存的,而编译有两种~码选择Qgbk或者iso8859-1Q前者是中文windows的默认编码,后者是linux的默认编码,当然也可以在~译时指定编码?nbsp;<br /> <br /> Jsp  *(gbk:d6d0 cec4)  java file  *(gbk:d6d0 cec4)  compiler read  uincode(gbk: 4e2d 6587; iso8859-1: 00d6 00d 000ce 00c4)  compiler write  utf(gbk: e4b8ad e69687; iso8859-1: *)  compiled file  unicode(gbk: 4e2d 6587; iso8859-1: 00d6 00d 000ce 00c4)  class。所以用gbk~码保存Q而用iso8859-1~译的结果是不正的?nbsp;<br /> <br /> class  unicode(4e2d 6587)  system.out / jsp.out  gbk(d6d0 cec4)  os console / browser?nbsp;<br /> <br /> l 文g可以以多U编码方式保存,中文windows下,默认为ansi/gbk?nbsp;<br /> <br /> l ~译器读取文件时Q需要得到文件的~码Q如果未指定Q则使用pȝ默认~码。一般class文gQ是以系l默认编码保存的Q所以编译不会出问题Q但对于jsp文gQ如果在中文windows下编辑保存,而部|在英文linux下运?~译Q则会出现问题。所以需要在jsp文g中用pageEncoding指定~码?nbsp;<br /> <br /> l Java~译的时候会转换成统一的unicode~码处理Q最后保存的时候再转换为utf~码?nbsp;<br /> <br /> l 当系l输出字W的时候,会按指定~码输出Q对于中文windows下,System.out用gbk~码Q而对于responseQ浏览器Q,则用jsp文g头指定的contentTypeQ或者可以直接ؓresponse指定~码。同Ӟ会告诉browser|页的编码。如果未指定Q则会用iso8859-1~码。对于中文,应该为browser指定输出字符串的~码?nbsp;<br /> <br /> l browser昄|页的时候,首先使用response中指定的~码Qjsp文g头指定的contentType最l也反映在response上)Q如果未指定Q则会用网中metaҎ定中的contentType?nbsp;<br /> <br /> 3.5. 几处讄 <br /> <br /> 对于web应用E序Q和~码有关的设|或者函数如下?nbsp;<br /> <br /> 3.5.1. jsp~译 <br /> <br /> 指定文g的存储编码,很明显,该设|应该置于文件的开头。例如:<%@page pageEncoding="GBK"%>。另外,对于一般class文gQ可以在~译的时候指定编码?nbsp;<br /> <br /> 3.5.2. jsp输出 <br /> <br /> 指定文g输出到browser是用的~码Q该讄也应该置于文件的开头。例如:<%@ page contentType="text/html; charset= GBK" %>。该讄和response.setCharacterEncoding("GBK"){效?nbsp;<br /> <br /> 3.5.3. meta讄 <br /> <br /> 指定|页使用的编码,该设|对静态网尤其有作用。因为静态网|法采用jsp的设|,而且也无法执行response.setCharacterEncoding()。例如:<META http-equiv="Content-Type" content="text/html; charset=GBK" /> <br /> <br /> 如果同时采用了jsp输出和meta讄两种~码指定方式Q则jsp指定的优先。因为jsp指定的直接体现在response中?nbsp;<br /> <br /> 需要注意的是,apache有一个设|可以给无编码指定的|页指定~码Q该指定{同于jsp的编码指定方式,所以会覆盖静态网中的meta指定。所以有人徏议关闭该讄?nbsp;<br /> <br /> 3.5.4. form讄 <br /> <br /> 当浏览器提交表单的时候,可以指定相应的编码。例如:<form accept-charset= "gb2312">。一般不必不使用该设|,览器会直接使用|页的编码?nbsp;<br /> <br /> 4. pȝ软g <br /> <br /> 下面讨论几个相关的系lY件?nbsp;<br /> <br /> 4.1. mysql数据?nbsp;<br /> <br /> 很明显,要支持多语言Q应该将数据库的~码讄成utf或者unicodeQ而utf更适合与存储。但是,如果中文数据中包含的英文字母很少Q其实unicode更ؓ适合?nbsp;<br /> <br /> 数据库的~码可以通过mysql的配|文件设|,例如default-character-set=utf8。还可以在数据库链接URL中设|,例如Q?nbsp;useUnicode=true&characterEncoding=UTF-8。注意这两者应该保持一_在新的sql版本里,在数据库链接URL里可以不q行讄Q但也不能是错误的设|?nbsp;<br /> <br /> 4.2. apache <br /> <br /> appache和编码有关的配置在httpd.conf中,例如AddDefaultCharset UTF-8。如前所qͼ该功能会所有静态页面的~码讄为UTF-8Q最好关闭该功能?nbsp;<br /> <br /> 另外Qapacheq有单独的模块来处理|页响应_其中也可能对~码q行讄?nbsp;<br /> <br /> 4.3. linux默认~码 <br /> <br /> q里所说的linux默认~码Q是指运行时的环境变量。两个重要的环境变量是LC_ALL和LANGQ默认编码会影响到java URLEncode的行为,下面有描q?nbsp;<br /> <br /> 都设|ؓ"zh_CN.UTF-8"?nbsp;<br /> <br /> 4.4. 其它 <br /> <br /> Z支持中文文g名,linux在加载磁盘时应该指定字符集,例如Qmount /dev/hda5 /mnt/hda5/ -t ntfs -o iocharset=gb2312?nbsp;<br /> <br /> 另外Q如前所qͼ使用GETҎ提交的信息不支持request.setCharacterEncoding()Q但可以通过tomcat的配|文件指定字W集Q在tomcat的server.xml文g中,形如Q?lt;Connector ... URIEncoding="GBK"/>。这U方法将l一讄所有请求,而不能针对具体页面进行设|,也不一定和browser使用的编码相同,所以有时候ƈ不是所期望的?nbsp;<br /> <br /> 5. URL地址 <br /> <br /> URL地址中含有中文字W是很麻烦的Q前面描q过使用GETҎ提交表单的情况,使用GETҎӞ参数是包含在URL中?nbsp;<br /> <br /> 5.1. URL~码 <br /> <br /> 对于URL中的一些特D字W,览器会自动q行~码。这些字W除?/?&"{外Q还包括unicode字符Q比如汉子。这时的~码比较Ҏ?nbsp;<br /> <br /> IE有一个选项"L使用UTF-8发送URL"Q当该选项有效ӞIE会对特D字W进行UTF-8~码Q同时进行URL~码。如果改选项无效Q则使用默认~码"GBK"Qƈ且不q行URL~码。但是,对于URL后面的参敎ͼ则L不进行编码,相当于UTF-8选项无效。比? <a >http://www.bt285.cn</a> 中文.html?a=中文"Q当UTF-8选项有效Ӟ发送链? <a >http://www.bt285.cn</a> %e4%b8%ad%e6%96%87.html?a=\x4e\x2d\x65\x87"Q而UTF-8选项无效Ӟ发送链?\x4e\x2d\x65\x87.html?a=\x4e\x2d\x65\x87"。注意后者前面的"中文"两个字只?个字节,而前者却?8个字节,q主要时URL~码的原因?nbsp;<br /> <br /> 当web serverQtomcatQ接收到该链接时Q将会进行URL解码Q即L"%"Q同时按照ISO8859-1~码Q上面已l描qͼ可以使用URLEncoding来设|成其它~码Q识别。上qC子的l果分别? <a >http://www.feng123.com</a> \ue4\ub8\uad\ue6\u96\u87.html?a=\u4e\u2d\u65\u87"? <a >http://www.feng123.com</a> \u4e\u2d\u65\u87.html?a=\u4e\u2d\u65\u87"Q注意前者前面的"中文"两个字恢复成?个字W。这里用"\u"Q表C是unicode?nbsp;<br /> <br /> 所以,׃客户端设|的不同Q相同的链接Q在服务器上得到了不同结果。这个问题不h都遇刎ͼ却没有很好的解决办法。所以有的网站会用户试关闭UTF-8选项。不q,下面会描qC个更好的处理办法?nbsp;<br /> <br /> 5.2. rewrite <br /> <br /> 熟悉的h都知道,apache有一个功能强大的rewrite模块Q这里不描述其功能。需要说明的是该模块会自动将URL解码Q去?Q,卛_成上qweb serverQtomcatQ的部分功能。有相关文档介绍说可以用[NE]参数来关闭该功能Q但我试验ƈ未成功,可能是因为版本(我用的是apache 2.0.54Q问题。另外,当参C含有"?& "{符L时候,该功能将Dpȝ得不到正常结果?nbsp;<br /> <br /> rewrite本ng完全是采用字节处理的方式Q而不考虑字符串的~码Q所以不会带来编码问题?nbsp;<br /> <br /> 5.3. URLEncode.encode() <br /> <br /> q是Java本n提供对的URL~码函数Q完成的工作和上qUTF-8选项有效时浏览器所做的工作怼。值得说明的是Qjava已经不赞成不指定~码来用该ҎQdeprecatedQ。应该在使用的时候增加编码指定?nbsp;<br /> <br /> 当不指定~码的时候,该方法用系l默认编码,q会D软gq行l果得不定。比如对?中文"Q当pȝ默认~码?gb2312"Ӟl果?%4e%2d%65%87"Q而默认编码ؓ"UTF-8"Q结果却?%e4%b8%ad%e6%96%87"Q后l程序将难以处理。另外,q儿说的pȝ默认~码是由q行tomcat时的环境变量LC_ALL和LANG{决定的Q曾l出现过tomcat重启后就出现q的问题,最后才郁闷的发现是因ؓ修改修改了这两个环境变量?nbsp;<br /> <br /> l一指定?UTF-8"~码Q可能需要修改相应的E序?nbsp;<br /> <br /> 5.4. 一个解x?nbsp;<br /> <br /> 上面说vq,因ؓ览器设|的不同Q对于同一个链接,web server收到的是不同内容Q而Y件系l有无法知道q中间的区别Q所以这一协议目前q存在缺陗?nbsp;<br /> <br /> 针对具体问题Q不应该侥幸认ؓ所有客LIE讄都是UTF-8有效的,也不应该_暴的徏议用户修改IE讄Q要知道Q用户不可能去记住每一个web server的设|。所以,接下来的解决办法只能是让自qE序多一Ҏ能:Ҏ内容来分析编码是否UTF-8?nbsp;<br /> <br /> 比较q运的是UTF-8~码相当有规律,所以可以通过分析传输q来的链接内容,来判断是否是正确的UTF-8字符Q如果是Q则以UTF-8处理之,如果不是Q则使用客户默认~码Q比?GBK"Q,下面是一个判断是否UTF-8的例子,如果你了解相应规律,容易理解?nbsp;<br /> <br /> public static boolean isValidUtf8(byte[] b,int aMaxCount){ <br /> <br />        int lLen=b.length,lCharCount=0; <br /> <br />        for(int i=0;i<lLen && lCharCount<aMaxCount;++lCharCount){ <br /> <br />               byte lByte=b[i++];//to fast operation, ++ now, ready for the following for(;;) <br /> <br />               if(lByte>=0) continue;//>=0 is normal ascii <br /> <br />               if(lByte<(byte)0xc0 || lByte>(byte)0xfd) return false; <br /> <br />               int lCount=lByte>(byte)0xfc?5:lByte>(byte)0xf8?4 <br /> <br />                      :lByte>(byte)0xf0?3:lByte>(byte)0xe0?2:1; <br /> <br />               if(i+lCount>lLen) return false; <br /> <br />               for(int j=0;j<lCount;++j,++i) if(b[i]>=(byte)0xc0) return false; <br /> <br />        } <br /> <br />        return true; <br /> <br /> } <br /> <br /> 相应圎ͼ一个用上q方法的例子如下Q?nbsp;<br /> <br /> public static String getUrlParam(String aStr,String aDefaultCharset) <br /> <br /> throws UnsupportedEncodingException{ <br /> <br />        if(aStr==null) return null; <br /> <br />        byte[] lBytes=aStr.getBytes("ISO-8859-1"); <br /> <br />        return new String(lBytes,StringUtil.isValidUtf8(lBytes)?"utf8":aDefaultCharset); <br /> <br /> } <br /> <br /> 不过Q该Ҏ也存在缺P如下两方面: <br /> <br /> l 没有包括对用户默认编码的识别Q这可以Ҏh信息的语a来判断,但不一定正,因ؓ我们有时候也会输入一些韩文,或者其他文字?nbsp;<br /> <br /> l 可能会错误判断UTF-8字符Q一个例子是"学习"两个字,其GBK~码? \xd1\xa7\xcf\xb0"Q如果用上qisValidUtf8Ҏ判断Q将q回true。可以考虑使用更严格的判断ҎQ不q估计效果不大?nbsp;<br /> <br /> 有一个例子可以证明google也遇C上述问题Q而且也采用了和上q相似的处理ҎQ比如,如果在地址栏中输入"http://www.google.com/search?hl=zh-CN&newwindow=1&q=学习"Qgoogle无法正识别,而其他汉字一般能够正常识别?nbsp;<br /> <br /> 最后,应该补充说明一下,如果不用rewrite规则Q或者通过表单提交数据Q其实ƈ不一定会遇到上述问题Q因时可以在提交数据时指定希望的~码。另外,中文文g名确实会带来问题Q应该}慎用?nbsp;<br /> <br /> 6. 其它 <br /> <br /> 下面描述一些和~码有关的其他问题?nbsp;<br /> <br /> 6.1. SecureCRT <br /> <br /> 除了览器和控制C~码有关外,一些客L也很有关pR比如在使用SecureCRTq接linuxӞ应该让SecureCRT的显C编码(不同的sessionQ可以有不同的编码设|)和linux的编码环境变量保持一致。否则看到的一些帮助信息,可能是q?nbsp;<br /> <br /> 另外Qmysql有自q~码讄Q也应该保持和SecureCRT的显C编码一致。否则通过SecureCRT执行sql语句的时候,可能无法处理中文字符Q查询结果也会出Cؕ码?nbsp;<br /> <br /> 对于Utf-8文gQ很多编辑器Q比如记事本Q会在文件开头增加三个不可见的标志字节,如果作ؓmysql的输入文Ӟ则必要Lq三个字W。(用linux的vi保存可以Lq三个字W)。一个有的现象是,在中文windows下,创徏一个新txt文gQ用C本打开Q输?q?两个字,保存Q再打开Q你会发C个字没了Q只留下一个小黑点?nbsp;<br /> <br /> 6.2. qo?nbsp;<br /> <br /> 如果需要统一讄~码Q则通过filterq行讄是个不错的选择。在filter class中,可以l一为需要的h或者回应设|编码。参加上qsetCharacterEncoding()。这个类apache已经l出了可以直接用的例子SetCharacterEncodingFilter?nbsp;<br /> <br /> 6.3. POST和GET <br /> <br /> 很明显,以POST提交信息ӞURL有更好的可读性,而且可以方便的用setCharacterEncoding()来处理字W集问题。但GETҎ形成的URL能够更容易表辄늚实际内容Q也能够用于收藏?nbsp;<br /> <br /> 从统一的角度考虑问题Q徏议采用GETҎQ这要求在程序中获得参数是进行特D处理,而无法用setCharacterEncoding()的便利,如果不考虑rewriteQ就不存在IE的UTF-8问题Q可以考虑通过讄URIEncoding来方便获取URL中的参数?nbsp;<br /> <br /> 6.4. J体~码转换 <br /> <br /> GBK同时包含体和J体~码Q也是说同一个字Q由于编码不同,在GBK~码下属于两个字。有时候,Z正确取得完整的结果,应该繁体和体进行统一。可以考虑UTF、GBK中的所有繁体字Q{换ؓ相应的简体字QBIG5~码的数据,也应该{化成相应的简体字。当Ӟ仍旧以UTF~码存储?nbsp;<br /> <br /> 例如Q对?语言 ?a"Q用UTF表示?\xE8\xAF\xAD\xE8\xA8\x80 \xE8\xAA\x9E\xE8\xA8\x80"Q进行简J体~码转换后应该是两个相同?nbsp;"\xE8\xAF\xAD\xE8\xA8\x80>"?nbsp;<br /> <img src ="http://www.tkk7.com/fundei/aggbug/277873.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/fundei/" target="_blank">江苏520</a> 2009-05-25 19:03 <a href="http://www.tkk7.com/fundei/archive/2009/05/25/277873.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA生成高品质羃略图的代码与下蝲http://www.tkk7.com/fundei/archive/2009/05/22/271148.html江苏520江苏520Fri, 22 May 2009 14:12:00 GMThttp://www.tkk7.com/fundei/archive/2009/05/22/271148.htmlimport java.awt.image.BufferedImage;

public class ImageScale {

private int width;
private int height;
private int scaleWidth;
double support = (double) 3.0;
double PI = (double) 3.14159265358978;
double[] contrib;
double[] normContrib;
double[] tmpContrib;
int startContrib, stopContrib;
int nDots;
int nHalfDots;

public BufferedImage imageZoomOut(BufferedImage srcBufferImage, int w, int h) {
width = srcBufferImage.getWidth();
height = srcBufferImage.getHeight();
scaleWidth = w;

if (DetermineResultSize(w, h) == 1) {
return srcBufferImage;
}
CalContrib();
BufferedImage pbOut = HorizontalFiltering(srcBufferImage, w);
BufferedImage pbFinalOut = VerticalFiltering(pbOut, h);
return pbFinalOut;
}

/**
 * 军_囑փ寸
 */
private int DetermineResultSize(int w, int h) {
double scaleH, scaleV;
scaleH = (double) w / (double) width;
scaleV = (double) h / (double) height;
// 需要判断一下scaleHQscaleVQ不做放大操?br /> if (scaleH >= 1.0 && scaleV >= 1.0) {
return 1;
}
return 0;

} // end of DetermineResultSize()

private double Lanczos(int i, int inWidth, int outWidth, double Support) {
double x;

x = (double) i * (double) outWidth / (double) inWidth;

return Math.sin(x * PI) / (x * PI) * Math.sin(x * PI / Support)
/ (x * PI / Support);

} // end of Lanczos()

//
// Assumption: same horizontal and vertical scaling factor
//
private void CalContrib() {
nHalfDots = (int) ((double) width * support / (double) scaleWidth);
nDots = nHalfDots * 2 + 1;
try {
contrib = new double[nDots];
normContrib = new double[nDots];
tmpContrib = new double[nDots];
} catch (Exception e) {
System.out.println("init contrib,normContrib,tmpContrib" + e);
}

int center = nHalfDots;
contrib[center] = 1.0;

double weight = 0.0;
int i = 0;
for (i = 1; i <= center; i++) {
contrib[center + i] = Lanczos(i, width, scaleWidth, support);
weight += contrib[center + i];
}

for (i = center - 1; i >= 0; i--) {
contrib[i] = contrib[center * 2 - i];
}

weight = weight * 2 + 1.0;

for (i = 0; i <= center; i++) {
normContrib[i] = contrib[i] / weight;
}

for (i = center + 1; i < nDots; i++) {
normContrib[i] = normContrib[center * 2 - i];
}
} // end of CalContrib()

// 处理边缘
private void CalTempContrib(int start, int stop) {
double weight = 0;

int i = 0;
for (i = start; i <= stop; i++) {
weight += contrib[i];
}

for (i = start; i <= stop; i++) {
tmpContrib[i] = contrib[i] / weight;
}

} // end of CalTempContrib()

private int GetRedValue(int rgbValue) {
int temp = rgbValue & 0x00ff0000;
return temp >> 16;
}

private int GetGreenValue(int rgbValue) {
int temp = rgbValue & 0x0000ff00;
return temp >> 8;
}

private int GetBlueValue(int rgbValue) {
return rgbValue & 0x000000ff;
}

private int ComRGB(int redValue, int greenValue, int blueValue) {

return (redValue << 16) + (greenValue << 8) + blueValue;
}

// 行水qxo?br /> private int HorizontalFilter(BufferedImage bufImg, int startX, int stopX,
int start, int stop, int y, double[] pContrib) {
double valueRed = 0.0;
double valueGreen = 0.0;
double valueBlue = 0.0;
int valueRGB = 0;
int i, j;

for (i = startX, j = start; i <= stopX; i++, j++) {
valueRGB = bufImg.getRGB(i, y);

valueRed += GetRedValue(valueRGB) * pContrib[j];
valueGreen += GetGreenValue(valueRGB) * pContrib[j];
valueBlue += GetBlueValue(valueRGB) * pContrib[j];
}

valueRGB = ComRGB(Clip((int) valueRed), Clip((int) valueGreen),
Clip((int) valueBlue));
return valueRGB;

} // end of HorizontalFilter()

// 囄水^滤L
private BufferedImage HorizontalFiltering(BufferedImage bufImage, int iOutW) {
int dwInW = bufImage.getWidth();
int dwInH = bufImage.getHeight();
int value = 0;
BufferedImage pbOut = new BufferedImage(iOutW, dwInH,
BufferedImage.TYPE_INT_RGB);

for (int x = 0; x < iOutW; x++) {

int startX;
int start;
int X = (int) (((double) x) * ((double) dwInW) / ((double) iOutW) + 0.5);
int y = 0;

startX = X - nHalfDots;
if (startX < 0) {
startX = 0;
start = nHalfDots - X;
} else {
start = 0;
}

int stop;
int stopX = X + nHalfDots;
if (stopX > (dwInW - 1)) {
stopX = dwInW - 1;
stop = nHalfDots + (dwInW - 1 - X);
} else {
stop = nHalfDots * 2;
}

if (start > 0 || stop < nDots - 1) {
CalTempContrib(start, stop);
for (y = 0; y < dwInH; y++) {
value = HorizontalFilter(bufImage, startX, stopX, start,
stop, y, tmpContrib);
pbOut.setRGB(x, y, value);
}
} else {
for (y = 0; y < dwInH; y++) {
value = HorizontalFilter(bufImage, startX, stopX, start,
stop, y, normContrib);
pbOut.setRGB(x, y, value);
}
}
}

return pbOut;

} // end of HorizontalFiltering()

private int VerticalFilter(BufferedImage pbInImage, int startY, int stopY,
int start, int stop, int x, double[] pContrib) {
double valueRed = 0.0;
double valueGreen = 0.0;
double valueBlue = 0.0;
int valueRGB = 0;
int i, j;

for (i = startY, j = start; i <= stopY; i++, j++) {
valueRGB = pbInImage.getRGB(x, i);

valueRed += GetRedValue(valueRGB) * pContrib[j];
valueGreen += GetGreenValue(valueRGB) * pContrib[j];
valueBlue += GetBlueValue(valueRGB) * pContrib[j];
// System.out.println(valueRed+"->"+Clip((int)valueRed)+"<-");
//
// System.out.println(valueGreen+"->"+Clip((int)valueGreen)+"<-");
// System.out.println(valueBlue+"->"+Clip((int)valueBlue)+"<-"+"-->");
}

valueRGB = ComRGB(Clip((int) valueRed), Clip((int) valueGreen),
Clip((int) valueBlue));
// System.out.println(valueRGB);
return valueRGB;

} // end of VerticalFilter()

private BufferedImage VerticalFiltering(BufferedImage pbImage, int iOutH) {
int iW = pbImage.getWidth();
int iH = pbImage.getHeight();
int value = 0;
BufferedImage pbOut = new BufferedImage(iW, iOutH,
BufferedImage.TYPE_INT_RGB);

for (int y = 0; y < iOutH; y++) {

int startY;
int start;
int Y = (int) (((double) y) * ((double) iH) / ((double) iOutH) + 0.5);

startY = Y - nHalfDots;
if (startY < 0) {
startY = 0;
start = nHalfDots - Y;
} else {
start = 0;
}

int stop;
int stopY = Y + nHalfDots;
if (stopY > (int) (iH - 1)) {
stopY = iH - 1;
stop = nHalfDots + (iH - 1 - Y);
} else {
stop = nHalfDots * 2;
}

if (start > 0 || stop < nDots - 1) {
CalTempContrib(start, stop);
for (int x = 0; x < iW; x++) {
value = VerticalFilter(pbImage, startY, stopY, start, stop,
x, tmpContrib);
pbOut.setRGB(x, y, value);
}
} else {
for (int x = 0; x < iW; x++) {
value = VerticalFilter(pbImage, startY, stopY, start, stop,
x, normContrib);
pbOut.setRGB(x, y, value);
}
}

}

return pbOut;

} // end of VerticalFiltering()

int Clip(int x) {
if (x < 0)
return 0;
if (x > 255)
return 255;
return x;
}

public static void main(String[] args) {
}
}
}


-----------------------------------------------------------------------
public BufferedImage imageZoomOut(BufferedImage srcBufferImage, int w, int h)
我将q个ҎҎ?br /> public BufferedImage imageZoomOut(BufferedImage srcBufferImage, float w, float h)
Z方便同比例羃放,w, h改ؓflaot型作为羃放比率,其他地方作相应的改动?/p>

如果是在|页上显C的话,需要徏一个ServletQ代码如下:
package servlet;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.ImageScale;

public class ImageServlet extends HttpServlet {

  private static final long serialVersionUID = 1L;

  public void doPost(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    doGet(request, response);
  }

  public void doGet(HttpServletRequest request, HttpServletResponse response)
      throws ServletException, IOException {
    response.setHeader("Cache-Control", "no-store");
    response.setHeader("Pragma", "no-cache");
    response.setDateHeader("Expires", 0);
    response.setContentType("image/jpeg");
    
    // 囄攑֜当前应用的images目录??a >http://www.feng123.com 下的文g目录?br />     String path = getServletContext().getRealPath("images/2.jpg");    
    BufferedImage image1 = ImageIO.read(new File(path));    
    
    if(request.getParameter("x") == null) {
      ImageIO.write(image1, "jpeg", response.getOutputStream());
    }else {
      float w = Float.parseFloat(request.getParameter("x"));
      float h;
      if(request.getParameter("y") == null) {
        h = w;
      }else{
        h = Float.parseFloat(request.getParameter("y"));
      }      
      ImageScale is = new ImageScale();
      BufferedImage image2 = is.imageZoomOut(image1, w, h);
      ImageIO.write(image2, "jpeg", response.getOutputStream());
    }
  }
}

在web.xml中增加相应的配置Q?br /> <servlet>
  <servlet-name>ImageServlet</servlet-name>
  <servlet-class>servlet.ImageServlet</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>ImageServlet</servlet-name>
  <url-pattern>/imageServlet</url-pattern>
</servlet-mapping>

试面 http://www.feng123.com 下的Q?br /> <html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=gbk" />
  </head>
  <body>
    囄~放试http://www.bt285.cn <br/>
    <img src="imageServlet" />
    <img src="imageServlet?x=0.9&y=0.9" />
    <img src="imageServlet?x=0.8&y=0.8" />
    <img src="imageServlet?x=0.7&y=0.7" />
    <img src="imageServlet?x=0.6&y=0.6" />
    <img src="imageServlet?x=0.5&y=0.5" />
    <img src="imageServlet?x=0.4&y=0.4" />
    <img src="imageServlet?x=0.3&y=0.3" />
    <img src="imageServlet?x=0.2&y=0.2" />
    <img src="imageServlet?x=0.1&y=0.1" />
    <img src="imageServlet?x=0.08" />
    <img src="imageServlet?x=0.5&y=0.7" />
  </body>
</html>



江苏520 2009-05-22 22:12 发表评论
]]>
java利用jmf实现拍照功能http://www.tkk7.com/fundei/archive/2009/05/21/271147.html江苏520江苏520Thu, 21 May 2009 13:03:00 GMThttp://www.tkk7.com/fundei/archive/2009/05/21/271147.html首先到SUN下蝲最新的JMFQ然后安装。http://java.sun.com/products/java-media/jmf/index.jsp         http://www.bt285.cn  

然后Q说一下需?

1Q?用摄像头拍照

2Q?在文本框输入文g?

3Q?按下拍照按钮Q获取摄像头内的囑փ

4Q?在拍下的照片上有一U框截取固定大小的照片?

5Q?保存为本地图像ؓjpg格式Q不得压~画?

技术关键,怿也是大家最感兴的部分也就是如何让一个摄像头工作Qƈ拍下一张照片了?

利用JMFQ代码很单:

//利用q三个类分别获取摄像头驱动,和获取摄像头内的囑փ,获取到的囑փ是一个Swing的Componentlgc?

 

public static Player player = null;
              private CaptureDeviceInfo di = null;
              private MediaLocator ml = null;
              String str1 = "vfw:Logitech USB Video Camera:0";
              String str2 = "vfw:Microsoft WDM Image Capture (Win32):0";
              di = CaptureDeviceManager.getDevice(str2);
              ml = di.getLocator();
              try
              {
              player = Manager.createRealizedPlayer(ml);
              player.start();
              Component comp;
              if ((comp = player.getVisualComponent()) != null)
              {
              add(comp, BorderLayout.NORTH);
              }
              }
              catch (Exception e)
              {
              e.printStackTrace();
              }

接下来就是点L照,获取摄像头内的当前图像?

代码也是很简单:

 

 private JButton capture;
              private Buffer buf = null;
              private BufferToImage btoi = null;
              private ImagePanel imgpanel = null;
              private Image img = null;
              private ImagePanel imgpanel = null;
              JComponent c = (JComponent) e.getSource();
              if (c == capture)//如果按下的是拍照按钮 http://www.5a520.cn
              {
              FrameGrabbingControl fgc =(FrameGrabbingControl)player.getControl
            ("javax.media.control.FrameGrabbingControl");
              buf = fgc.grabFrame(); // 获取当前ƈ存入Bufferc?http://www.bt285.cn
              btoi = new BufferToImage((VideoFormat) buf.getFormat());
              img = btoi.createImage(buf); // show the image
              imgpanel.setImage(img);
              }

保存囑փ的就不多说了Q以下ؓCZ代码

 

 BufferedImage bi = (BufferedImage) createImage(imgWidth, imgHeight);
              Graphics2D g2 = bi.createGraphics();
              g2.drawImage(img, null, null);
              FileOutputStream out = null;
              try
              {
              out = new FileOutputStream(s);
              }
              catch (java.io.FileNotFoundException io)
              {
              System.out.println("File Not Found");
              }
              JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
              JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(bi);
              param.setQuality(1f, false);//不压~图?http://www.bt285.cn
              encoder.setJPEGEncodeParam(param);
              try
              {
              encoder.encode(bi);
              out.close();
              }
              catch (java.io.IOException io)
              {
              System.out.println("IOException");
              }

已经甌JWebCam建立Z个开源项目,攑ֈGROQ大家发挥自q惌力加入自q代码吧,比如拍摄视频Q添加图像处理功能,{等



江苏520 2009-05-21 21:03 发表评论
]]>
用Tomcat 的SSO实现http://www.tkk7.com/fundei/archive/2009/05/19/271145.html江苏520江苏520Tue, 19 May 2009 13:21:00 GMThttp://www.tkk7.com/fundei/archive/2009/05/19/271145.html
  • 修改Tomcat conf/server.xml 打开SSO支持
  • <Host> 节点下增加一个Value节点
    <Valve className="org.apache.catalina.authenticator.SingleSignOn"
    debug="0" requireReauthentication="false"/>
    </Host>
    • container认证realmQ?user、role、server.xml?lt;Realm...>讄.
    tomcat的认证机制有2个要素: user ?role.
      • user 是区别一个个用户的唯一识别了?
      • role 是一些抽象的权限U别Q比?#8220;admin”?#8220;manager”?#8220;member”?#8220;guest”{等Q都是可以自己定义的.一个user可以拥有多种role.
    “可是tomcat怎么L到我的user/role信息呢?我的q些数据都在数据库里阿?” 可以在tomcat的server.xml里用 <Realm> tag来读取这些信息,q且tomcat提供??U现成的Realm实现Q其中有从文仉ȝQ有从JDBCȝQ有从DataSourceȝQ也有从LDAPȝ。具体Realm的写法,和提供的几种Realm的配|方法,可以参考tomcat自己的文档,在此不作l述?(把tomcat自带的webapp: tomcat-docs.war 展开Q看里面?config/realm.html) 如果q这些现成的配置都不能满你的要求的话,那也可以考虑自己写一个Realm的实现类来满_体要求。下面D一个JDBC的Realm的配|例子看一下:
    <Realm  className="org.apache.catalina.realm.JDBCRealm"  debug="99"
    driverName="your.jdbc.driver.here"
    connectionURL="your.jdbc.url.here"
    connectionName="test"
    connectionPassword="test"
    userTable="users"
    userNameCol="user_name"
    userCredCol="user_pass"
    userRoleTable="user_roles"
    roleNameCol="role_name" />
    • webapp使用SSOQ?
      • 告诉tomcatq个webapp要通过container的认?
    具体做法Q?在web.xml里面加上如下的配|:
    <security-constraint>
    <web-resource-collection>
    <web-resource-name>http://www.bt285.cn  BT下蝲 </web-resource-name>
    <url-pattern>/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
    <!-- role name 指定哪个role可以讉K,可以为多个roleQ如两个|站Q?a >http://www.5a520.cn http://www.feng123.com  -->
    <role-name>intrauser</role-name>
    </auth-constraint>
    </security-constraint>
      • 选择一U认证方?
    在web.xml里面加上如下的配|:
    <login-config>
    <auth-method>BASIC</auth-method>
    <realm-name>Intra Web Application</realm-name>
    </login-config>
    <security-role>
    <description>The role that is required to access intrasites</description>
    <role-name>intrauser</role-name>
    </security-role>
    q里?个要点:
        • auth-method
    举例Z单用了最基本的一UBASIC。若使用BASIC方式Q当你去讉K受保护认证的资源Ӟ览器会弹出一个小H口让你输入用户名和密码。(像我们讉KiofficeӞW一ơ弹出来的那个认证窗口)其他q有几种认证方式如:FORM、DIGEST、CLIENT-CERT。其中FORM是可以自己写login画面的,当然html的form内容有些规定Q要W合j2ee和container的要求嘛Q?DIGEST是一U加密的传输Q而CLIENT-CERT没有查过Q有兴趣可以L一下?
        • realm-name
    q个realm-name是这个webapp的认证realm名,注意几个处于同一SSO下的webappQ他们的realm-name要设成一L倹{?如果不设成一P那么换一个webappp重新认证一ơ,达不到SSO的效果?
      • 如何取得当前的User信息
    原本都习惯在login以后Q把一些login用户信息攑ֈsession里面? 现在认证都交lcontainerd了,我们的webapp怎么拿到login用户信息啊? 实Q现在我们的webapp能做的,只有从request里面拿到login用户的userid了?
    String userid = request.gerRemoteUser();

    以上是在一个Tomcat Container上的SSO实现.
    如果是不同的Container上的webapp要做SSOQ这U时候一U可行的Ҏ是,最前面架一个webserverQ比如apacheQ,在webserverq层承担SSO的认证Q务,后面内部可用挂多个container? 具体都用到的时候再调查?



    江苏520 2009-05-19 21:21 发表评论
    ]]>
    如何用java d水印http://www.tkk7.com/fundei/archive/2009/05/18/271144.html江苏520江苏520Mon, 18 May 2009 12:45:00 GMThttp://www.tkk7.com/fundei/archive/2009/05/18/271144.htmlimport java.awt.*
    import java.awt.event.*
    import java.io.*
    import java.awt.image.*
    import org.w3c.dom.*
    import com.sun.image.codec.jpeg.*
    import javax.imageio.*
    Q*Q?br /> author by http:
    //www.5a520.cn
    Q/
    public class ImgBean
    public void ImgBean(){} 
    public void ImgYin(String s,String ImgName)
    try
    File _file 
    = new File(ImgName); 
    Image src 
    = ImageIO.read(_file); 
    int wideth=src.getWidth(null); 
    int height=src.getHeight(null); 
    BufferedImage image
    =new BufferedImage(wideth,height,BufferedImage.TYPE_INT_RGB); 
    Graphics g
    =image.createGraphics(); 
    g.drawImage(src,
    0,0,wideth,height,null); 
    String s
    ="我要加的水印 Q来源http://www.bt285.cn BT下蝲"
    g.setColor(Color.RED); 
    g.setFont(
    new Font("宋体",Font.PLAIN,20)); 
    Font aa
    =new Font("宋体",Font.PLAIN,20); 

    g.drawString(s,wideth
    -150,height-10); 
    g.dispose(); 
    FileOutputStream out
    =new FileOutputStream(ImgName); 
    JPEGImageEncoder encoder 
    = JPEGCodec.createJPEGEncoder(out); 
    encoder.encode(image); 
    out.close(); 
    }
     
    catch(Exception e)
    System.out.println(e); 
    }
     
    }
     
    }




    江苏520 2009-05-18 20:45 发表评论
    ]]>
    վ֩ģ壺 ĻƷ| jizzjizz߲ž| þþƷAVδʮ| 4444wwwѿ| ҹþþþƷӰԺ| ƷƵ| ŷղþ99| EEUSSӰԺWWW߹ۿ| Ļ| ĻƵ| ˳վۿ| һػaaëƬѹۿ| ޾ƷƵѿ| 鶹ƷƵ| ˾Ʒձַ| ҹdj߹ۿ| Ʒ޵һ| ѹ߹ۿ| һѵӰ| ޾ƷһƷ99| 5gӰԺ5gˬӰԺ| þþƷަvDz| Ů˱ͰúˬƵ | һ| ޾ƷŮþþþ | һ˿wwwѸ| ޾ƷĻ| ѹվ߹ۿ | Ʒavɫ| ޹ӰԺ| 岻Ƶ| Դ°߹ۿ| aëƬa԰Ħ| ȫƵѹۿ߿| H߲߹ۿH| VAۺVAVA| 99߾ƷƵѹۿ9| ۺϾƷ˾þ| һ뾫Ʒɫ| ѿhƬվ| һëƬһëƬëƬ|