星期一, 二月 23, 2004

Java类似的竞争技术太多了.

http://www-106.ibm.com/developerworks/xml/edu/x-dw-xxsp-i.html
了解:Cocoon.apache.org

星期五, 二月 20, 2004

pipe PrintWriter data to StreamSouce for XSLT transformation

é??é??:
????????¨XSLT???Printwrite???é??????????°?????¤??????é??(pipe)

Java Technology Forums

Hello All!

For 2 days I'm trying to pipe PrintWriter data to a StreamSource for XSLT transformation.

I got a PrintWriter variable named 'out' that, according to a incoming parameter, is a HttpResponse Writer or a PrintWriter to a PipedWriter the code looks like this:


public void doPost(HttpServletRequest req, HttpServletResponse res) throws IOException {PrintWriter out = null;boolean transform = false;java.io.PipedWriter xmlOutput = null;java.io.PipedReader transformInput = null;StreamSource original = new StreamSource(); if (req.getParameter("format") != null && req.getParameter("format").equals("text/html")) { transform = true; // pipe output of printwriter to streamsource input xmlOutput = new PipedWriter(); transformInput = new PipedReader(xmlOutput); out = new PrintWriter(xmlOutput); original.setReader(transformInput);} else { out = res.getWriter();}try { out.println(""); .... // here xml document data is appended out.println(""); } catch (Exception e) { e.printStackTrace();} if (transform) { System.out.println("transform starting"); // set the result of the transformation to the response StreamResult result = new StreamResult(res.getWriter()); StreamSource stylesheet = new StreamSource("z:/temp/transform.xsl"); System.out.println("document streams initialized"); try { TransformerFactory factory = TransformerFactory.newInstance(); Transformer formatter = factory.newTransformer(stylesheet); System.out.println("formatter created"); formatter.transform(original, result); System.out.println("transform ready"); } catch (Exception e) { e.printStackTrace(); } } // end transform}



When I run this example (a servlet) there is no response at all when I set the parameter format=text/html, neither a stacktrace is printed.

To the console every System.out except for 'transform ready'.

Can someone tell me what I need to do to make it work, or what is wrong with the code above??

Daniel Portier...





!!!Re: How to pipe PrintWriter data to StreamSouce for XSLT transformation?
Author: flairn
In Reply To: How to pipe PrintWriter data to StreamSouce for XSLT transformation? May 24, 2002 8:46 AM

Reply 1 of 5


I'd like to know how to do this also.

Or, otherwise, I'd like to find out how can I convert "outxml" below - containing the XML document - into a StreamSource object to pass to another servlet for "transformation? ( I do not want to create file.)



ServletOutputStream outxml = null;
resp.setContentType("text/xml");
outxml = resp.getOutputStream();
try
{
requ.marshal(outxml);
}
catch (Exception ex)
{
System.out.println("Exception encountered2: " + ex.getMessage());
ex.printStackTrace();
}
finally
{
outxml.close();
}




Re: !!!Re: How to pipe PrintWriter data to StreamSouce for XSLT transformation?
Author: DrClap
In Reply To: !!!Re: How to pipe PrintWriter data to StreamSouce for XSLT transformation? May 24, 2002 10:23 AM

Reply 2 of 5


Only one question: Why?


Re: !!!Re: How to pipe PrintWriter data to StreamSouce for XSLT transformation?
Author: flairn
In Reply To: Re: !!!Re: How to pipe PrintWriter data to StreamSouce for XSLT transformation? May 24, 2002 12:40 PM

Reply 3 of 5


I want to pass the XML in string form to another servlet to process (transform, etc).

This routine will occur 100's of times per day - i.e., invoked by user entry in a web application.

I would prefer to pass a session object (for example., a String containing the XML) to the other servlet, rather than create a temp file for the other servlet to read (- where I have to be concerned with deleting the file after use, etc).

Thanks for any help!


Re: !!!Re: How to pipe PrintWriter data to StreamSouce for XSLT transformation?
Author: DrClap
In Reply To: Re: !!!Re: How to pipe PrintWriter data to StreamSouce for XSLT transformation? May 24, 2002 1:39 PM

Reply 4 of 5


> I would prefer to pass a session object (for example.,
> a String containing the XML) to the other servlet,
> rather than create a temp file for the other servlet
> to read (- where I have to be concerned with deleting
> the file after use, etc).
>
> Thanks for any help!

Well of course that would be preferable. So why are you writing it to the servlet response and then trying to claw it back? Have your "requ.marshal" call output the XML to e.g. a StringWriter, then just extract the String from that and use it.


Re: !!!Re: How to pipe PrintWriter data to StreamSouce for XSLT transformation?
Author: flairn
In Reply To: Re: !!!Re: How to pipe PrintWriter data to StreamSouce for XSLT transformation? May 24, 2002 2:45 PM

Reply 5 of 5


Thanks for setting me straight Doc!

Sometimes us newbies get so wound up we cant think outside of the "box", as it were

;-)

Java Technology Forums

Java Technology Forums
<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
xmlns:java='java.util.ResourceBundle' exclude-result-prefixes='java' version='1.0'>
<xsl:strip-space elements='*'/>
<xsl:output method='html' indent='yes' version='4.0'/>
<xsl:output encoding='ISO-8859-1'/>
<xsl:template match='page'>
<html>
<body>
<xsl:apply-templates select='paragraph'/>
<xsl:variable name='resources' select='java:getBundle('thoth')'/>
<xsl:value-of select='java:getString($resources,'general.title')'/>
</body>
</html>
</xsl:template>
</xsl:stylesheet>"

Transform a dom object to String/转换DOM对象为字符串

目的:把一个XML通过XSLT转换后的结果作为字符串返回.

Java Technology Forums: "transform a dom object to String? "
based on abhishek_srivastava code, here's a simple toString() method:

/**
* Prints a textual representation of a DOM object into a text string..
*
* @param document DOM object to parse.
* @return String representation of document.
*/
public static String document2String(Document document) {
String result = null;

StringWriter strWtr = new StringWriter();
StreamResult strResult = new StreamResult(strWtr);
TransformerFactory tfac = TransformerFactory.newInstance();
try {
Transformer trans = tfac.newTransformer();
trans.transform(new DOMSource(document.getDocumentElement()), strResult);
} catch (Exception e) {
System.err.println("XMLUtils.document2String(): " + e);
}
result = strResult.getWriter().toString();

return result;
}//document2String()

星期四, 二月 19, 2004

XSLT 求和模式

number.xml
<numbers>12 24 24 15 16 17</numbers>

total.xsl

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:template match="/">
<xsl:value-of select="sum(node()//workage[text()>2])"/>
------
<xsl:value-of select="sum(node()//workage(1|0002|4))"/>
------CR
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:template match="/">
<xsl:call-template name="total-number">
<xsl:with-param name="list" select="."/>
</xsl:template>
</xsl:template>
</xsl:template>
<xsl:template name="total-number">
<xsl:param name="list"/>
<xsl:variable name="wlist" select="concat(normalize-space($list),' ')"/>
<xsl:choose>
<xsl:when test="$wlist !=' '">
<xsl:variable name="first" select="substring-befor($wlist,' ')"/>
<xsl:variable name="rest" select="substring-after($wlist,' ')"/>
<xsl:variable name="total">
<xsl:call-template name="total-numbers">
<xsl:with-param name="list" select="$rest"/>
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="number($first)+number($total)"/>
</xsl:when>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>

XSLT 条件过滤

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" version="1.0" encoding="UTF-8" indent="no"/>
<xsl:template match="/">
<!--给定某个条件的求和-->

<xsl:value-of select="sum(node()//workage[number(text())> 2])"/>|||

<!--选定某些用户来计算工资-->

<xsl:value-of select="sum(node()//workage[userid[text()='0002']])"/>|||

</xsl:template>
</xsl:stylesheet>

如何得到XSLT节点的set求和

<a href="http://localhost/payroll/frame.jsp">frame</a>: "<?xml version='1.0' encoding='UTF-8'?>
<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
<xsl:output method='html' version='1.0' encoding='UTF-8' indent='no'/>
<xsl:template match='/'>
here:
<xsl:for-each select='node()'>
<xsl:value-of select='sum(row/workage)'/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
"

星期一, 二月 16, 2004

openldap windowxp 设置问题.

配置完slapd.conf,修改所有的目录为window格式的目录.
启动后,用slapadd.exe 不能添加进用户数据:
解决方法:首先删除ldbm所在目录下生产的文件的.在编写ldif文件:
dn: dc=goldpeak,dc=com
objectClass: dcObject
objectClass: organization
dc: goldpeak
o: Example Corporation
description: The Example Corportation

使用:slapadd.exe -f ../slapd.conf -l 1.ldif

ok.

下载LDAP 管理工具:http://www.iit.edu/~gawojar/ldap/

有关OpenLdap的设置

有关OpenLDAP的设置
我刚刚配完openldap具体如下:
安装软件包需要注意的问题
编译
编译和优化
清除不必要的文件

配置
配置“/etc/ldap/slapd.conf”文件
配置“/etc/rc.d/init.d/ldap”脚本文件
更多的资料

保证OpenLDAP的安全
使得重要的配置文件不可改变

OpenLDAP的创建和维护工具
离线创建数据库
IDIF输入文件(用文本表示的输入文件)
为LDAP创建数据库
ldapmodify

OpenLDAP的用户工具
搜索LDAP的数据项

安装到系统中的文件

概述
LDAP(Lightweight Directory Access Protocol)是用来访问信息服务的标准协议。这个协议是用在Internet传输协议上,如:TCP,能够访问单独的目录服务或X.500目录。

注意事项

下面所有的命令都是Unix兼容的命令。
源路径都为“/var/tmp”(当然在实际情况中也可以用其它路径)。
安装在RedHat Linux 6.1下测试通过。
要用“root”用户进行安装。
OpenLDAP的版本号是1_2_8。

软件包的来源
OpenLDAP的主页:http://www.openldap.org/。

下载:openldap-1_2_8.tgz。

安装软件包需要注意的问题
最好在编译前和编译后都做一张系统中所有文件的列表,然后用“diff”命令去比较它们,找出其中的差别并知道到底把软件安装在哪里。只要简单地在编译之前运行一下命令“find /* >ldap1”,在编译和安装完软件之后运行命令“find /* > ldap2”,最后用命令 “diff ldap1 ldap2 > ldap”找出变化。

编译
把软件包(tar.gz)解压缩:

[root@deep]# cp openldap-version.tgz /var/tmp
[root@deep]# cd /var/tmp/
[root@deep]# tar xzpf openldap-version.tgz

编译和优化
转到OpenLDAP的新目录下。

编辑“string.h”文件(vi +52 include/ac/string.h),删掉这些几行:

#else
/* some systems have strdup(), but fail to declare it */
extern char *(strdup)();

上面的这几行对Linux系统是没有用的必须删掉。

下面设置编译器的编译参数:

CC="egcs"
CFLAGS="-O9 -funroll-loops -ffast-math -malign-double -mcpu=pentiumpro -march=pentiumpro -fomit-frame-
pointer -fno-exceptions"
./configure
--prefix=/usr
--libexecdir=/usr/sbin
--localstatedir=/var/run
--sysconfdir=/etc
--enable-shared
--with-gnu-ld

这些编译参数告诉编译器如何编译OpenLDAP:

l 编译共享库
l 假定C编译器使用GNU ld

开始编译:

[root@deep]# make depend
[root@deep]# make
[root@deep]# cd tests/
[root@deep]# make
[root@deep]# cd ..
[root@deep]# make install

“make depend” 命令编译必要的相关文件,“make”把源文件编译成可执行的二进制文件。“make install”把二进制文件和相关的配置文件安装到相应的目录中去。在“test”目录下的“make”命令在安装LDAP服务器之前进行一些必要的测试保证软件安装完成后能正常运行。如何测试失败在继续安装之前先要解决这些问题。

[root@deep]# install -d -m 700 /var/ldap
[root@deep]# echo localhost > /etc/openldap/ldapserver
[root@deep]# strip /usr/lib/liblber.so.1.0.0
[root@deep]# strip /usr/lib/libldap.so.1.0.0
[root@deep]# strip /usr/lib/libldap.a
[root@deep]# strip /usr/lib/liblber.a
[root@deep]# strip /usr/sbin/in.xfingerd
[root@deep]# strip /usr/sbin/go500
[root@deep]# strip /usr/sbin/go500gw
[root@deep]# strip /usr/sbin/mail500
[root@deep]# strip /usr/sbin/rp500
[root@deep]# strip /usr/sbin/fax500
[root@deep]# strip /usr/sbin/rcpt500
[root@deep]# strip /usr/sbin/slapd
[root@deep]# strip /usr/sbin/ldif2ldbm
[root@deep]# strip /usr/sbin/ldif2index
[root@deep]# strip /usr/sbin/ldif2id2entry
[root@deep]# strip /usr/sbin/ldif2id2children
[root@deep]# strip /usr/sbin/ldbmcat
[root@deep]# strip /usr/sbin/ldif
[root@deep]# strip /usr/sbin/centipede
[root@deep]# strip /usr/sbin/ldbmtest
[root@deep]# strip /usr/sbin/slurpd
[root@deep]# strip /usr/bin/ud
[root@deep]# strip /usr/bin/ldapadd
[root@deep]# strip /usr/bin/ldapsearch
[root@deep]# strip /usr/bin/ldapmodify
[root@deep]# strip /usr/bin/ldapmodrdn
[root@deep]# strip /usr/bin/ldappasswd
[root@deep]# strip /usr/bin/ldapdelete

上面的“install”命令在“/var”目录下创建一个名为“ldap”的新目录并且把它的属性设成只能被超级用户“root”读、写和执行。

“strip”命令清除目标文件中所有的符号信息,这样可执行文件就会更小,能够提高一点程序的性能。

清除不必要的文件
用下面的命令删除不必要的文件:

[root@deep]# cd /var/tmp
[root@deep]# rm -rf ldap openldap-version.tgz

“rm”命令删除所有编译和安装OpenLDAP所需要的源程序,并且把“/var/tmp”目录下的OpenLDAP软件的压缩包删除掉。

配置
可以到这去下载“floppy.tgz”文件:http: //pages.infinit.net/lotus1/doc/opti/floppy.tgz。把“floppy.tgz”文件解开之后,可以在相应的目录下发现我们在这本书中介绍的所有软件的配置文件。这样就没有必要手工重新生成这些文件,或者用拷贝粘贴的方法把它们粘贴到配置文件中去。不管是打算自己动手生成配置文件还是拷贝现成的,你都要学会自己修改配置文件并且把配置文件拷贝到正确的目录下。下面将具体说明。

为了运行OpenLDAP,必须创建或者把下面的文件拷贝到相应的目录下:

l 把“slapd.conf”文件拷贝到“/etc/openldap”目录下
l 把“ldap”文件拷贝到“/etc/rc.d/init.d”目录下

可以把“floppy.tgz”解压之后,找到上面列出来的文件,并拷贝到“/etc/ssh”目录下,或者用拷贝粘贴的方法从本书中直接粘贴出。

配置“/etc/ldap/slapd.conf”文件
“/etc/openldap/slapd.conf”文件是LDAP服务器最重要的配置文件,配置权限、口令、数据库类型和数据库位置等等。

编辑“slap.conf”文件(vi /etc/openldap/slapd.conf)加入:

#
# See slapd.conf(5) for details on configuration options.
# This file should NOT be world readable.
#
include /etc/openldap/slapd.at.conf
include /etc/openldap/slapd.oc.conf
schemacheck off
#referral ldap://ldap.itd.umich.edu
pidfile /var/run/slapd.pid
argsfile /var/run/slapd.args
#######################################################################
# ldbm database definitions
#######################################################################
database ldbm
suffix "o=openarch, c=com"
directory /var/ldap
rootdn "cn=admin, o=openarch, c=com"
rootpw secret
# cleartext passwords, especially for the rootdn, should
# be avoid. See slapd.conf(5) for details.
# ldbm indexed attribute definitions
index cn,sn,uid
index objectclass pres,eq
index default none
# ldbm access control definitions
defaultaccess read
access to attr=userpassword
by self write
by dn="cn=admin, o=openarch, c=com" write
by * compare

下面解释一下上面配置文件中的一些设置:

suffix “o=openarch, c=com”

suffix(后缀)设置想要创建的子树的根的DN(distinguished name)。换句话说,就是表示数据库中到底放些什么。

directory /var/ldap

设置LDAP数据库和索引文件所在的目录。必须设置为“/var/ldap”因为我们在安装阶段已经指定了LDAP的后台数据库。

rootdn “cn=admin, o=openarch, c=com”

设置管理LDAP目录的超级用户的DN。这个用户名(admin)并不要出现在“/etc/passwd”文件里。

rootpw secret

设置这个数据库的超级用户的口令验证方式。也就是上面“rootdn”设置的用户的口令。千万不要用明文进行口令验证,一定要用加密的口令。

index cn,sn,uid | index objectclass pres,eq | index default none

这三句设置在数据库中创建和维护怎样的索引。“index cn,sn,uid)为cn、sn和uid属性创建和维护索引, “index objectclass pres,eq”为objectclass属性创建相等索引(equality indexes), “index default none”表示不为别的属性创建索引。查看用户手册可以得到更多的信息。

“slapd.conf”文件中的最后一部分是和LDAP目录的访问控制相关的。

defaultaccess read
access to attr=userpassword
by self write
by dn="cn=admin, o=openarch, c=com" write
by * compare

这些设置对“o=openarch,c=com”子树中的所有项都是有效的。任何人都有读的权限,除了“userpasswd”属性拥有这一项的用户可以改变其它所有的属性。“userpassword”属性只能被admin修改,但是任何人都可以比较。查看用户手册可以得到更多的信息。

配置“/etc/rc.d/init.d/ldap”脚本文件
配置“/etc/rc.d/init.d/ldap”脚本文件用来启动和停止ldap服务。

创建“ldap”脚本文件(touch /etc/rc.d/init.d/ldap)并加入:

#!/bin/sh
#
# ldap This shell script takes care of starting and stopping
# ldap servers (slapd and slurpd).
#
# chkconfig: - 70 40
# description: LDAP stands for Lightweight Directory Access Protocol, used
# for implementing the industry standard directory services.
# processname: slapd
# config: /etc/openldap/slapd.conf
# pidfile: /var/run/slapd.pid
# Source function library.
. /etc/rc.d/init.d/functions
# Source networking configuration.
. /etc/sysconfig/network
# Check that networking is up.
[ ${NETWORKING} = "no" ] && exit 0
[ -f /usr/sbin/slapd ] || exit 0
[ -f /usr/sbin/slurpd ] || exit 0
RETVAL=0
# See how we were called.
case "$1" in
start)
# Start daemons.
echo -n "Starting ldap: "
daemon slapd
RETVAL=$?
if [ $RETVAL -eq 0 ]; then
if grep -q "^replogfile" /etc/openldap/slapd.conf; then
daemon slurpd
RETVAL=$?
[ $RETVAL -eq 0 ] && pidof slurpd | cut -f 1 -d " " > /var/run/slurpd
fi
fi
echo
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/ldap
;;
stop)
# Stop daemons.
echo -n "Shutting down ldap: "
killproc slapd
RETVAL=$?
if [ $RETVAL -eq 0 ]; then
if grep -q "^replogfile" /etc/openldap/slapd.conf; then
killproc slurpd
RETVAL=$?
fi
fi
echo
if [ $RETVAL -eq 0 ]; then
rm -f /var/lock/subsys/ldap
rm -f /var/run/slapd.args
fi
;;
status)
status slapd
RETVAL=$?
if [ $RETVAL -eq 0 ]; then
if grep -q "^replogfile" /etc/openldap/slapd.conf; then
status slurpd
RETVAL=$?
fi
fi
;;
restart)
$0 stop
$0 start
RETVAL=$?
;;
reload)
killproc -HUP slapd
RETVAL=$?
if [ $RETVAL -eq 0 ]; then
if grep -q "^replogfile" /etc/openldap/slapd.conf; then
killproc -HUP slurpd
RETVAL=$?
fi
fi
;;
*)
echo "Usage: $0 start|stop|restart|status}"
exit 1
esac
exit $RETVAL

使得脚本可执行并改变它的权限:

[root@deep]# chmod 700 /etc/rc.d/init.d/ldap

在rc.d目录中创建OpenLDAP脚本的符号链接:

[root@deep]# chkconfig --add ldap

当重新引导系统的时候,OpenLDAP脚本不会自动启动slapd脚本。可以用下面的命令让它可以自动启动:

[root@deep]# chkconfig --level 345 ldap on

用下面的命令也可以手工启动OpenLDAP服务器:

[root@deep]# /etc/rc.d/init.d/ldap start

更多的资料
如果想查找详细的资料可以用man命令查帮助页,读取相关信息:

$ man ldapd ( - LDAP X.500 Protocol Daemon
$ man ldapdelete (1) - ldap delete entry tool
$ man ldapfilter.conf (5) - configuration file for LDAP get filter routines
$ man ldapfriendly (5) - data file for LDAP friendly routines
$ man ldapmodify, ldapadd (1) - ldap modify entry and ldap add entry tools
$ man ldapmodrdn (1) - ldap modify entry RDN tool
$ man ldappasswd (1) - change the password of an LDAP entry
$ man ldapsearch (1) - ldap search tool
$ man ldapsearchprefs.conf (5) - configuration file for LDAP search preference routines
$ man ldaptemplates.conf (5) - configuration file for LDAP display template routines
$ man ldif (5) - LDAP Data Interchange format
$ man slapd ( - Stand-alone LDAP Daemon
$ man slapd.conf (5) - configuration file for slapd, the stand-alone LDAP daemon
$ man slurpd ( - Standalone LDAP Update Replication Daemon
$ man ud (1) - interactive LDAP Directory Server query program

保证OpenLDAP的安全
使得重要的配置文件不可改变
设置不可改变位可以避免需要保护的文件被意外的删除或者覆盖。也可以防止有人创建这个文件的符号链接。一旦“slapd.conf”文件配置完成了之后,用下面的命令设置不可改变位:

[root@deep]# chattr +i /etc/openldap/slapd.conf

OpenLDAP的创建和维护工具
离线创建数据库
如果一下子要创建成千上万的项(entry),用这个方法最合适了,因为用“ldapadd”命令逐个添加要花费相当长的时间。这个工具读取slapd的配置文件和用文本表示的包含所有需要添加的项的输入文件。“ldif2ldbm”的命令语法如下:

[root@deep]# ldif2ldbm -i -f

表示纯文本的LDIF输入文件的文件名。表示slapd配置文件的文件名,这个配置文件设置在什么地方创建索引、创建什么索引,等等。

例如:

[root@deep]# ldif2ldbm -i my-data-file -f /etc/openldap/slapd.conf

纯文本的输入文件的文件名为“my-data-file”

注意:离线创建数据库的时候slapd daemon不能运行。

IDIF输入文件(用文本表示的输入文件)
第一次安装OpenLDAP必须把大量的数据存入OpenLDAP的数据库里。最好把这些数据都用纯文本的文件表示出来,再用下面的命令把数据加入OpenLDAP数据库中。

创建“my-data-file”文件(touch /tmp/my-data-file),下面加入的这些行可以作为参考:

dn: o=openarch, c=com
o: openarch
objectclass: organization
dn: cn=Ronald Smith, o=openarch, c=com
cn: Ronald Smith
sn: Smith
telephonenumber: (480) 757-5856
title: Operator.
objectclass: top

objectclass: person
dn: cn=Anthony Bay, o=openarch, c=com
cn: Anthony Bay
sn: Bay
homephone: (410) 896-3786
mobile: (410) 833-0590
mail: abay@openarch.com
objectclass: top
objectclass: person
dn: cn=George Parker, o=openarch, c=com
cn: George Parker
sn: Parker
telephonenumber: (414) 389-5695
fax: (414) 778-8785
mobile: (414) 470-8669
description: E-Commerce.
objectclass: top
objectclass: person

上面的例子文件让你了解了如何把数据库中的信息装成纯文本的信息,再把这些信息加入OpenLDAP数据库中。还有很多的设置选项可以满足你的需要,请查看OpenLDAP的文档或书籍,以获得更多的信息。

为LDAP创建数据库
就像可以往数据库中加入记录那样,也可以用“ldapadd”命令在LDAP中加入项。例如:用“ldapadd”命令加入“Europe Mourani”这一项,先要创建“/tmp/newentry”文件:

创建“newentry”文件(touch /tmp/newentry),在文件中加入下面的内容:

cn=Europe Mourani, o=openarch, c=com
cn=Europe Mourani
sn=Mourani
mail=emourani@old.com
description=Marketing relation.
objectClass=top
objectClass=person

用下面的命令在LDAP中加入这一项:

[root@deep]# ldapadd -f /tmp/newentry -D "cn=admin, o=openarch, c=com" -W

Enter LDAP Password :

上面的命令假定在配置文件中设置“rootdn”为“cn=admin, o=openarch, c=com”,“rootpw”设置为“secret”。命令还会提示输入口令。

ldapmodify
“ldapmodify”命令建立到LDAP服务器的连接,绑定、修改和加入数据项。通过使用“-f”参数可以设置从标准输入还是文件中得到数据项的信息。

用于“ldapmodify”命令的输入文件的格式:

假定“/tmp/entry”文件存在,而且文件的内容是:

cn=Europe Mourani, o=openarch, c=com
- mail=emourani@old.com # will delete the old mail address for Europe Mourani in the database.
+mail=emourani@new.com # will add the new mail address for Europe Mourani in the database.

用下面的命令改变LDAP中的数据项:

[root@deep]# ladpmodify -D ‘cn=Admin, o=openarch, c=com’ -W -f

这个命令改变了“Europe Mourani”数据项的mail属性,把这个属性值改为:emourani@new.com。

OpenLDAP的用户工具
下面列出的是一些我们经常要用到的命令,当然还有很多其它的命令,更详细的信息可以查看man帮助页或其它文档。

搜索LDAP的数据项
“ldapsearch”命令建立到LDAP服务器的连接、绑定并用过滤器进行搜索。

用下面的命令搜索LDAP数据库中的数据项:

[root@deep]# ldapsearch -b
[root@deep]# ldapsearch -b ‘o=openarch.com’ ‘cn=a*’

这个命令把所有以字母“a”开头的数据项的信息显示在道标准输出上。

安装到系统中的文件
> /etc/openldap
> /etc/openldap/ldap.conf
> /etc/openldap/ldap.conf.default
> /etc/openldap/ldapfilter.conf
> /etc/openldap/ldapfilter.conf.default
> /etc/openldap/ldaptemplates.conf
> /etc/openldap/ldaptemplates.conf.default
> /etc/openldap/ldapsearchprefs.conf
> /etc/openldap/ldapsearchprefs.conf.default
> /etc/openldap/slapd.conf
> /etc/openldap/slapd.conf.default
> /etc/openldap/slapd.at.conf
> /etc/openldap/slapd.at.conf.default
> /etc/openldap/slapd.oc.conf
> /etc/openldap/slapd.oc.conf.default
> /etc/openldap/ldapserver
> /etc/rc.d/init.d/ldap
> /etc/rc.d/rc0.d/K40ldap
> /etc/rc.d/rc1.d/K40ldap
> /etc/rc.d/rc2.d/K40ldap
> /etc/rc.d/rc3.d/S70ldap
> /etc/rc.d/rc4.d/S70ldap
> /etc/rc.d/rc5.d/S70ldap
> /etc/rc.d/rc6.d/K40ldap
> /usr/bin/ud
> /usr/bin/ldapsearch
> /usr/bin/ldapmodify
> /usr/bin/ldapdelete
> /usr/bin/ldapmodrdn
> /usr/bin/ldappasswd
> /usr/bin/ldapadd
> /usr/include/ldap.h
> /usr/include/lber.h
> /usr/include/ldap_cdefs.h
> /usr/man/man3/ldap_open.3
> /usr/man/man3/ldap_errlist.3
> /usr/man/man3/ldap_err2string.3
> /usr/man/man3/ldap_first_attribute.3
> /usr/man/man3/ldap_next_attribute.3
> /usr/man/man3/ldap_first_entry.3
> /usr/man/man3/ldap_next_entry.3
> /usr/man/man3/ldap_count_entries.3
> /usr/man/man3/ldap_friendly.3
> /usr/man/man3/ldap_friendly_name.3
> /usr/man/man3/ldap_free_friendlymap.3
> /usr/man/man3/ldap_get_dn.3
> /usr/man/man3/ldap_explode_dn.3
> /usr/man/man3/ldap_explode_dns.3
> /usr/man/man3/ldap_dn2ufn.3
> /usr/man/man3/ldap_is_dns_dn.3
> /usr/man/man3/ldap_get_values.3
> /usr/man/man3/ldap_get_values_len.3
> /usr/man/man3/ldap_value_free.3
> /usr/man/man3/ldap_value_free_len.3
> /usr/man/man3/ldap_count_values.3
> /usr/man/man3/ldap_count_values_len.3
> /usr/man/man3/ldap_getfilter.3
> /usr/man/man3/ldap_init_getfilter.3
> /usr/man/man3/ldap_init_getfilter_buf.3
> /usr/man/man3/ldap_getfilter_free.3
> /usr/man/man3/ldap_getfirstfilter.3
> /usr/man/man3/ldap_getnextfilter.3
> /usr/man/man3/ldap_setfilteraffixes.3
> /usr/man/man3/ldap_build_filter.3
> /usr/man/man3/ldap_modify.3
> /usr/man/man3/ldap_modify_s.3
> /usr/man/man3/ldap_mods_free.3
> /usr/man/man3/ldap_modrdn.3
> /usr/include/disptmpl.h
> /usr/include/srchpref.h
> /usr/lib/liblber.so.1.0.0
> /usr/lib/liblber.so.1
> /usr/lib/liblber.so
> /usr/lib/liblber.la
> /usr/lib/liblber.a
> /usr/lib/libldap.so.1.0.0
> /usr/lib/libldap.so.1
> /usr/lib/libldap.so
> /usr/lib/libldap.la
> /usr/lib/libldap.a
> /usr/man/man1/ud.1
> /usr/man/man1/ldapdelete.1
> /usr/man/man1/ldapmodify.1
> /usr/man/man1/ldapadd.1
> /usr/man/man1/ldapmodrdn.1
> /usr/man/man1/ldappasswd.1
> /usr/man/man1/ldapsearch.1
> /usr/man/man3/cldap_close.3
> /usr/man/man3/cldap_open.3
> /usr/man/man3/cldap_search_s.3
> /usr/man/man3/cldap_setretryinfo.3
> /usr/man/man3/lber-decode.3
> /usr/man/man3/lber-encode.3
> /usr/man/man3/ldap.3
> /usr/man/man3/cldap.3
> /usr/man/man3/ldap_abandon.3
> /usr/man/man3/ldap_add.3
> /usr/man/man3/ldap_add_s.3
> /usr/man/man3/ldap_bind.3
> /usr/man/man3/ldap_bind_s.3
> /usr/man/man3/ldap_simple_bind.3
> /usr/man/man3/ldap_simple_bind_s.3
> /usr/man/man3/ldap_kerberos_bind_s.3
> /usr/man/man3/ldap_kerberos_bind1.3
> /usr/man/man3/ldap_kerberos_bind1_s.3
> /usr/man/man3/ldap_kerberos_bind2.3
> /usr/man/man3/ldap_kerberos_bind2_s.3
> /usr/man/man3/ldap_unbind.3
> /usr/man/man3/ldap_unbind_s.3
> /usr/man/man3/ldap_set_rebind_proc.3
> /usr/man/man3/ldap_cache.3
> /usr/man/man3/ldap_enable_cache.3
> /usr/man/man3/ldap_disable_cache.3
> /usr/man/man3/ldap_destroy_cache.3
> /usr/man/man3/ldap_flush_cache.3
> /usr/man/man3/ldap_uncache_entry.3
> /usr/man/man3/ldap_uncache_request.3
> /usr/man/man3/ldap_set_cache_options.3
> /usr/man/man3/ldap_charset.3
> /usr/man/man3/ldap_set_string_translators.3
> /usr/man/man3/ldap_enable_translation.3
> /usr/man/man3/ldap_translate_from_t61.3
> /usr/man/man3/ldap_translate_to_t61.3
> /usr/man/man3/ldap_t61_to_8859.3
> /usr/man/man3/ldap_8859_to_t61.3
> /usr/man/man3/ldap_compare.3
> /usr/man/man3/ldap_compare_s.3
> /usr/man/man3/ldap_delete.3
> /usr/man/man3/ldap_delete_s.3
> /usr/man/man3/ldap_disptmpl.3
> /usr/man/man3/ldap_modrdn_s.3
> /usr/man/man3/ldap_modrdn2.3
> /usr/man/man3/ldap_modrdn2_s.3
> /usr/man/man3/ldap_init.3
> /usr/man/man3/ldap_result.3
> /usr/man/man3/ldap_msgfree.3
> /usr/man/man3/ldap_search.3
> /usr/man/man3/ldap_search_s.3
> /usr/man/man3/ldap_search_st.3
> /usr/man/man3/ldap_searchprefs.3
> /usr/man/man3/ldap_init_searchprefs.3
> /usr/man/man3/ldap_init_searchprefs_buf.3
> /usr/man/man3/ldap_free_searchprefs.3
> /usr/man/man3/ldap_first_searchobj.3
> /usr/man/man3/ldap_next_searchobj.3
> /usr/man/man3/ldap_sort.3
> /usr/man/man3/ldap_sort_entries.3
> /usr/man/man3/ldap_sort_values.3
> /usr/man/man3/ldap_sort_strcasecmp.3
> /usr/man/man3/ldap_ufn.3
> /usr/man/man3/ldap_ufn_search_s.3
> /usr/man/man3/ldap_ufn_search_c.3
> /usr/man/man3/ldap_ufn_search_ct.3
> /usr/man/man3/ldap_ufn_setprefix.3
> /usr/man/man3/ldap_ufn_setfilter.3
> /usr/man/man3/ldap_ufn_timeout.3
> /usr/man/man3/ldap_url.3
> /usr/man/man3/ldap_is_ldap_url.3
> /usr/man/man3/ldap_url_parse.3
> /usr/man/man3/ldap_free_urldesc.3
> /usr/man/man3/ldap_url_search.3
> /usr/man/man3/ldap_url_search_s.3
> /usr/man/man3/ldap_url_search_st.3
> /usr/man/man5/ldap.conf.5
> /usr/man/man5/ldapfilter.conf.5
> /usr/man/man5/ldapfriendly.5
> /usr/man/man5/ldapsearchprefs.conf.5
> /usr/man/man5/ldaptemplates.conf.5
> /usr/man/man5/ldif.5
> /usr/man/man5/slapd.conf.5
> /usr/man/man5/slapd.replog.5
> /usr/man/man5/ud.conf.5
> /usr/man/man8/centipede.8
> /usr/man/man8/chlog2replog.8
> /usr/man/man8/edb2ldif.8
> /usr/man/man8/go500.8
> /usr/man/man8/go500gw.8
> /usr/man/man8/in.xfingerd.8
> /usr/man/man8/ldapd.8
> /usr/man/man8/ldbmcat.8
> /usr/man/man8/ldif.8
> /usr/man/man8/ldif2ldbm.8
> /usr/man/man8/ldif2index.8
> /usr/man/man8/ldif2id2entry.8
> /usr/man/man8/ldif2id2children.8
> /usr/man/man8/mail500.8
> /usr/man/man8/fax500.8
> /usr/man/man8/rcpt500.8
> /usr/man/man8/slapd.8
> /usr/man/man8/slurpd.8
> /usr/sbin/ldif
> /usr/sbin/in.xfingerd
> /usr/man/man3/ldap_init_templates.3
> /usr/man/man3/ldap_init_templates_buf.3
> /usr/man/man3/ldap_free_templates.3
> /usr/man/man3/ldap_first_disptmpl.3
> /usr/man/man3/ldap_next_disptmpl.3
> /usr/man/man3/ldap_oc2template.3
> /usr/man/man3/ldap_tmplattrs.3
> /usr/man/man3/ldap_first_tmplrow.3
> /usr/man/man3/ldap_next_tmplrow.3
> /usr/man/man3/ldap_first_tmplcol.3
> /usr/man/man3/ldap_next_tmplcol.3
> /usr/man/man3/ldap_entry2text.3
> /usr/man/man3/ldap_entry2text_search.3
> /usr/man/man3/ldap_vals2text.3
> /usr/man/man3/ldap_entry2html.3
> /usr/man/man3/ldap_entry2html_search.3
> /usr/man/man3/ldap_vals2html.3
> /usr/man/man3/ldap_error.3
> /usr/man/man3/ldap_perror.3
> /usr/man/man3/ld_errno.3
> /usr/man/man3/ldap_result2error.3
> /usr/sbin/go500
> /usr/sbin/go500gw
> /usr/sbin/mail500
> /usr/sbin/rp500
> /usr/sbin/fax500
> /usr/sbin/xrpcomp
> /usr/sbin/rcpt500
> /usr/sbin/slapd
> /usr/sbin/ldif2ldbm
> /usr/sbin/ldif2index
> /usr/sbin/ldif2id2entry
> /usr/sbin/ldif2id2children
> /usr/sbin/ldbmcat
> /usr/sbin/centipede
> /usr/sbin/ldbmtest

具体启动脚本时会遇到sladpd进程启动不了的问题,建议用如下方法启动:
#su root -c /usr/local/libexec/slapd -f myslapd.conf
其中slapd被安装在配置文件指定的"libexecdir"目录下,通常为/usr/local/libexec/slpad。
如果启动成功,到同一网络中的一台pc上运行outlook,添加ldap目录服务,然后搜索个人,应该能返回提示"没有符合所搜索项目"之类的提示,说明已经连接到ldap服务器.

但我在用ldapadd添加邮件用户时提示如下错误,请高手指点
#ldapadd -D "cn=manager,dc=openarch,dc=com" -W < mydif.ldif
Enter LDAP Password:
ldap_sasl_interactive_bind_s: No such attribute

哪位高手在redhat上配置过LDAP数据库.我的OpenLdap已经配置好了.测试通过.但在创建库时,.ldif文件中的数据用ldapadd命令导不进去!.ldif文件格式如下:
#----------------------------------------
dn=yourdomain,c=us
objectClass:dcObject
objectClassrgnization
o:yourdomain
dn:cn=Manager,o=yourdomain,c=us
objectClassrganizationlRole
cn:Manager
descriptionirectory Manager
#......
#---------------------------------------
执行ldapadd命令如下:
[root@linux_test openldap-ldbm]# ldapadd -f mail.ldif -x -D "cn=root,o=yourdomain,c=us" -w secret
提示:
adding new entry "o=yourdomain,c=us"
ldap_add: Already exists

ldif_record() = 68
请大家帮忙分析一下,能告诉我怎么才能把.ldif中的条目添加到ldap库里吗???谢谢

改正一点:
*--enable-shared ??????>enable=shared
*--with-gnu-ld -------------->with=gnu-ld
好像ldap的脚本不支持chkconfig!


基本解决了!!!原因是每次在向ldap库里添加记录时首先添加记录头,就是adding new entry "o=yourdomain,c= us",如果不设置强制添加,则不会导入用户记录,所以必须在ldapadd后加上-c.才能成功导入数据.在outlook端能查找到你导入的用户!!!!

谢谢samba!!!

The Next Move in Programming: A Conversation with Sun's Victoria Livschitz

The Next Move in Programming: A Conversation with Sun's Victoria Livschitz

关于ACID中,ISOLATION的解释.

Pessimistic and optimistic locking

Transactional isolation is usually implemented by locking whatever is accessed in a transaction. There are two different approaches to transactional locking: Pessimistic locking and optimistic locking.
The disadvantage of pessimistic locking is that a resource is locked from the time it is first accessed in a transaction until the transaction is finished, making it inaccessible to other transactions during that time. If most transactions simply look at the resource and never change it, an exclusive lock may be overkill as it may cause lock contention, and optimistic locking may be a better approach.With pessimistic
locking, locks are applied in a fail-safe way. In the banking application example, an account is locked as soon as it is accessed in a transaction. Attempts to use the account in other transactions while it is locked will either result in the other process being delayed until the account lock is released, or that the process transaction will be rolled back. The lock exists until the transaction has either been committed or rolled back.With optimistic locking, a resource is not actually locked when it is first is accessed by a transaction. Instead, the state of the resource at the time when it would have been locked with the pessimistic locking approach is saved. Other transactions are able to concurrently access to the resource and the possibility of conflicting changes is possible. At commit time, when the resource is about to be updated in persistent storage, the state of the resource is read from storage again and compared to the state that was saved when the resource was first accessed in the transaction. If the two states differ, a conflicting update was made, and the transaction will be rolled back.

星期五, 二月 13, 2004

jsp or Servlet 测试 代码

System.out.println("ContextPath = "+request.getContextPath());
System.out.println("RequestURI = "+request.getRequestURI());
System.out.println("ServletPath = "+request.getServletPath());
System.out.println("RemoteUser = "+request.getRemoteUser());
System.out.println("submit urL = "+request.getRequestURL());
System.out.println("submit urL = "+request.getPathInfo());
Enumeration ttl = request.getHeaderNames();
while(ttl.hasMoreElements())
{
String tempstr = (String)ttl.nextElement();
System.out.println(tempstr+" = "+ request.getHeader(tempstr));
}

Servlet中如何获得提交前的JSP的地址

通过:
nextPage=request.getHeader("referer");
可以获得提交前的地址.

并传送到提交之前的也面.
nextPage=nextPage.substring(nextPage.indexOf(request.getContextPath())+request.getContextPath().length());

RequestDispatcher rd = getServletContext().getRequestDispatcher(nextPage);
request.getReqeustURI();获得的是当前Servlet的url.

需要注意的是ContextRoot和Root的一致性.
在WebModule和单纯jsp,及Ejb下面的ContextRoot有不同的含义.

星期四, 二月 12, 2004

JSP 和Servlet如何共享 JavaBean?JSP and Servlet how to share JavaBean?

问题提出:
我们需要在提交JSP后,如果出现Business Logic error或其他的Exception.当返回JSP页面的时候,可以在页面的某一个区域出现所有的提示并保留原来填写的内容。

方案:
1.PageContext 是个良好的入口,可惜只是JSP的包装器(wrapper).
2.利用getRequestDispatcher来实现,并把对象传递到页面里.

实现步骤:
1。首先定制JavaBean.
/**
* ErrorViewHelper JavaBean
**/
package com.javafans.Exception;
import java.util.*;
public class ErrorViewHelper
{
private ArrayList errormsg = new ArrayList();
public void setMsg(String msg)
{
errormsg.add("test");
}
public String getMsg()
{
String returnstr="12";
for(int i=0;i<errormsg.size();i++)
returnstr += errormsg.get(i)+"<br>";
return returnstr;
}
}

2.在JSP里面使用<jsp:useBean>
<jsp:useBean id="errorhelper" scope="request" class="com.javafans.Exception.ErrorViewHelper">
</jsp:useBean>
<jsp:getProperty name="errorhelper" property="msg"/>

3.在Servlet 中定义,并把对象传递回来.
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType(CONTENT_TYPE);
PrintWriter out = response.getWriter();
com.javafans.Exception.ErrorViewHelper temptest = new test();
temptest.setMsg("test");
request.setAttribute("errorhelper",temptest);//关键.1
RequestDispatcher rd;//关键 2
rd = getServletContext().getRequestDispatcher("/index.jsp"); //关键 3.
rd.forward(request,response); //关键 4
}

ok.

sessions in servlets


sessions in servlets
:
if (success=true) {
try { HttpSession login=request.getSession(true);
login.getValue('username');
login.getValue('password');
getServletConfig().getServletContext().getRequestDispatcher'/jsp/query.jsp').forward(request,response);
} catch (Exception ex)
{
ex.printStackTrace ();
} } }}"

星期三, 二月 11, 2004

字节编码和字符串关系(Java)

问题:
如果一个字节数组编码包含了非uncode文本,可以把其按照其原始字符集重构为Unicode.
细节:

Byte Encodings and Strings
If a byte array contains non-Unicode text, you can convert the text to Unicode with one of the String constructor methods. Conversely, you can convert a String object into a byte array of non-Unicode characters with the String.getBytes method. When invoking either of these methods, you specify the encoding identifier as one of the parameters.
The example that follows converts characters between UTF-8 and Unicode. UTF-8 is a transmission format for Unicode that is safe for UNIX file systems. The full source code for the example is in the file StringConverter.java.

The StringConverter program starts by creating a String containing Unicode characters:

String original = new String("A" + "\u00ea" + "\u00f1" +
"\u00fc" + "C");

When printed, the String named original appears as:

AêñüC

To convert the String object to UTF-8, invoke the getBytes method and specify the appropriate encoding identifier as a parameter. The getBytes method returns an array of bytes in UTF-8 format. To create a String object from an array of non-Unicode bytes, invoke the String constructor with the encoding parameter. The code that makes these calls is enclosed in a try block, in case the specified encoding is unsupported:

try {
byte[] utf8Bytes = original.getBytes("UTF8");
byte[] defaultBytes = original.getBytes();

String roundTrip = new String(utf8Bytes, "UTF8");
System.out.println("roundTrip = " + roundTrip);
System.out.println();
printBytes(utf8Bytes, "utf8Bytes");
System.out.println();
printBytes(defaultBytes, "defaultBytes");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}

The StringConverter program prints out the values in the utf8Bytes and defaultBytes arrays to demonstrate an important point: The length of the converted text might not be the same as the length of the source text. Some Unicode characters translate into single bytes, others into pairs or triplets of bytes.

The printBytes method displays the byte arrays by invoking the byteToHex method, which is defined in the source file, UnicodeFormatter.java. Here is the printBytes method:

public static void printBytes(byte[] array, String name) {
for (int k = 0; k < array.length; k++) {
System.out.println(name + "[" + k + "] = " + "0x" +
UnicodeFormatter.byteToHex(array[k]));
}
}

The output of the printBytes method follows. Note that only the first and last bytes, the A and C characters, are the same in both arrays:

utf8Bytes[0] = 0x41
utf8Bytes[1] = 0xc3
utf8Bytes[2] = 0xaa
utf8Bytes[3] = 0xc3
utf8Bytes[4] = 0xb1
utf8Bytes[5] = 0xc3
utf8Bytes[6] = 0xbc
utf8Bytes[7] = 0x43
defaultBytes[0] = 0x41
defaultBytes[1] = 0xea
defaultBytes[2] = 0xf1
defaultBytes[3] = 0xfc
defaultBytes[4] = 0x43

字符和字节流(Character and byte Steam)的关系/Java.

From:http://java.sun.com/docs/books/tutorial/i18n/text/stream.html

Character and Byte Streams
The java.io package provides classes that allow you to convert between Unicode character streams and byte streams of non-Unicode text. With the InputStreamReader class, you can convert byte streams to character streams. You use the OutputStreamWriterclass to translate character streams into byte streams. The following figure illustrates the conversion process:


This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

When you create InputStreamReader and OutputStreamWriter objects, you specify the byte encoding that you want to convert. For example, to translate a text file in the UTF-8 encoding into Unicode, you create an InputStreamReader as follows:

FileInputStream fis = new FileInputStream("test.txt");
InputStreamReader isr = new InputStreamReader(fis, "UTF8");

If you omit the encoding identifier, InputStreamReader and OutputStreamWriter rely on the default encoding. You can determine which encoding an InputStreamReader or OutputStreamWriter uses by invoking the getEncoding method, as follows:

InputStreamReader defaultReader = new InputStreamReader(fis);
String defaultEncoding = defaultReader.getEncoding();

The example that follows shows you how to perform character-set conversions with the InputStreamReader and OutputStreamWriter classes. The full source code for this example is in StreamConverter.java. This program displays Japanese characters. Before trying it out, verify that the appropriate fonts have been installed on your system. If you are using the JDK software that is compatible with version 1.1, make a copy of the font.properties file and then replace it with the font.properties.ja file.

The StreamConverter program converts a sequence of Unicode characters from a String object into a FileOutputStream of bytes encoded in UTF-8. The method that performs the conversion is called writeOutput:

static void writeOutput(String str) {

try {
FileOutputStream fos = new FileOutputStream("test.txt");
Writer out = new OutputStreamWriter(fos, "UTF8");
out.write(str);
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}

The readInput method reads the bytes encoded in UTF-8 from the file created by the writeOutput method. An InputStreamReader object converts the bytes from UTF-8 into Unicode and returns the result in a String. The readInput method is as follows:

static String readInput() {

StringBuffer buffer = new StringBuffer();
try {
FileInputStream fis = new FileInputStream("test.txt");
InputStreamReader isr = new InputStreamReader(fis,
"UTF8");
Reader in = new BufferedReader(isr);
int ch;
while ((ch = in.read()) > -1) {
buffer.append((char)ch);
}
in.close();
return buffer.toString();
} catch (IOException e) {
e.printStackTrace();
return null;
}
}

The main method of the StreamConverter program invokes the writeOutput method to create a file of bytes encoded in UTF-8. The readInput method reads the same file, converting the bytes back into Unicode. Here is the source code for the main method:

public static void main(String[] args) {

String jaString =
new String("\u65e5\u672c\u8a9e\u6587\u5b57\u5217");

writeOutput(jaString);
String inputString = readInput();
String displayString = jaString + " " + inputString;
new ShowString(displayString, "Conversion Demo");
}

The original string (jaString) should be identical to the newly created string (inputString). To show that the two strings are the same, the program concatenates them and displays them with a ShowString object. The ShowString class displays a string with the Graphics.drawString method. The source code for this class is in ShowString.java. When the StreamConverter program instantiates ShowString, the following window appears. The repetition of the characters displayed verifies that the two strings are identical: