HKEY_CURRENT_USER/Control Panel/International
中的iTime = 1?br /> 对应键gؓ(f)HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\OLEAUT(OLEAUT有可能不存在,那就自己创徏一?
??xml version="1.0" encoding="utf-8" standalone="yes"?> q会(x)使得我们使用中文操作pȝ的计机用v来很不方便,因ؓ(f)我们qx打字必用的切换打字法的快捷键Q恰恰就是这个! 当然Q你可以直接在Windows => Preferences... => General => KeysL换掉q个快捷键,不过可能q(sh)(x)有其他快捷键与我们的中文操作pȝ有冲H。这里介l一个一x逸,也是?#8220;Eclipse?#8221;的方法来改变q种尬局面:(x) 在MyEclipse的启动选项中,其实有Duser.languageq样一设|,在MyEclipse安装完之后,它的默认值是{于en的,只要把它Ҏ(gu)zhQ重启MyEclipse之后Q即可将Content Assist的快捷键Ҏ(gu)Alt + /?/p>
具体修改方式如下Q?/p>
【方法一】右击MyEclipse快捷方式Q选择属性,打开属性对话框Q如下:(x) ?-Duser.language=en 改ؓ(f) -Duser.language=zhQ?/font> 【方法二】在Eclipse安装目录下,有一个eclipse.ini的配|文Ӟ用文本编辑器打开它,扑ֈ-Duser.language=enq样一行,它改ؓ(f)-Duser.language=zh卛_Q?/font> 改完之后Q可以到Edit => Content Assist菜单下或快捷键设|面板中看到新的快捷键:(x) q样Q就通过更改MyEclipse的默认系l语aQ来辑ֈ更改使用?fn)惯Q如快捷键)(j)的目的?/font>
]]>
]]>
U定QPOI目2.0版现在已l接q正式发行阶D,开发进度迅速,不断有新的功能集成到原有的系l,同时也有对原有系l的修改。ؓ(f)?jin)保证本文的及(qing)?性,本文按照最q的1.9开发版说明。虽然编译最q的发行版源代码也能正常q行Q但现在的代码和2.0的发行版?x)有一些出入?br />
一、Excel基础
Microsoft Excel 97文g格式也被UCؓ(f)BIFF8Q最q版本的Excel只对该格式作?jin)少量的改动。增加对新格式的支持除了(jin)增加目的复杂性之外,唯一的效果也许只是不?不每个用户升代码Q没有什么实际的好处。因此,在下文说明中Q凡是提到Excel 97格式的地方其实都是指Excel?7到XP的格式?br />
二、HSSF概况
POI目实现的Excel 97文g格式UCؓ(f)HSSF——也怽已经猜到QHSSF是Horrible SpreadSheet Format的羃写,也即“讨厌的电(sh)子表格格?#8221;Q微软某些原本单的事情q分复杂Q同时又q分单地处理?jin)某些原本需要灵zL的事情Q让Z胜佩 服!Q也许HSSF的名字有Ҏ(gu)E,本质而言它是一个非怸肃、正规的API。通过HSSFQ你可以用纯Java代码来读取、写入、修改Excel?件?br />
前面一文章提C(jin)POIFSQ那么HSSF和POIFS又有什么关pdQ就象其他POI的API一PHSSF建立?POIFS的基上,因此在HSSF内的有些代码和前文的某些代码很相伹{不q,当我们编写基于HSSF API的代码时Q一般不需要了(jin)解POIFS API的细节?br />
HSSF取操作提供了(jin)两类APIQusermodel和eventusermodelQ即“用户模型”?#8220;??用户模型”。前者很好理解,后者比较抽象,但操作效率要高得多。usermodel主要?org.apache.poi.hssf.usermodel和org.apache.poi.hssf.eventusermodel包实玎ͼ?HSSF的早期版本中Qorg.apache.poi.hssf.eventusermodel属于eventmodel包)(j)?br />
usermodel包把Excel文g映射成我们熟(zhn)的l构Q诸如Workbook、Sheet、Row、Cell{,它把整个l构以一l对象的形式保存 在内存(sh)中。eventusermodel要求用户熟?zhn)文g格式的底层结构,它的操作风格cM于XML的SAX API和AWT的事件模型(q就是eventusermodel名称的v源)(j)Q要掌握H门才能用好。另外,eventusermodel的API只提供读 取文件的功能Q也是说不能用q个API来修Ҏ(gu)件?br />
三、通过usermodeld文g
用HSSF的usermodeld文g很简单。首先创Z个InputStreamQ然后创Z个HSSFWorkbookQ?br />
InputStream myxls = new FileInputStream("workbook.xls"));
HSSFWorkbook wb = new HSSFWorkbook(myxls);
有了(jin)HSSFWorkbook实例Q接下来可以提取工作表、工作表的行和列Q例如:(x)
HSSFSheet sheet = wb.getSheetAt(0); // W一个工作表
HSSFRow row = sheet.getRow(2); // W三?br />
HSSFCell cell = row.getCell((short)3); // W四个单元格
上面q段代码提取出第一个工作表W三行第四单元格。利用单元格对象可以获得它的|提取单元格的值时h意它的类型:(x)
if (cell.getCellType() == HSSFCell.CELL_TYPE_STRING) {
("单元格是字符Ԍ值是Q?" + cell.getStringCellValue());
} else if (cell.getCellType() == HSSFCell.CELL_TYPE_NUMERIC) {
("单元格是数字Q值是Q?" + cell.getCellValue());
} else () {
("单元格的g是字W串或数倹{?);
}
如果搞错?jin)数据类型,E序遇到异常。特别地Q用HSSF处理日期数据要小?j)。Excel内部以数值的形式保存日期数据Q区别日期数据的唯一办法是通过单元格的格式Q如果你曄在Excel中设|过日期格式Q应该明白这是什么意思)(j)?br />
因此Q对于包含日期数据的单元|cell.getCellType()返回HSSFCell.CELL_TYPE_NUMERICQ不q利用工具函 数HSSFDateUtil.isCellDateFormatted(cell)可以判断出单元格的值是否ؓ(f)日期?isCellDateFormatted函数通过比较单元格的日期和Excel的内|日期格式得出结论——可以想象,按照q种判断Ҏ(gu)Q很多时?isCellDateFormatted函数?x)返回否定的l论Q存在一定的误判可能?br />
本文附录包含?jin)一个在Servlet环境中利用HSSF创徏和返回Excel工作的实例?br />
四、通过usermodel写入文g
写入XLS文g比读取XLS文gq要单。创Z个HSSFWorkbook实例Q然后在适当的时候创Z个把文g写入盘的OutputStreamQ但延迟到处理结束时创徏OutputStream也可以:(x)
HSSFWorkbook wb = new HSSFWorkbook();
FileOutputStream fileOut
= new FileOutputStream("workbook.xls");
wb.write(fileOut);
fileOut.close();
创徏工作表及(qing)其内容必M相应的父对象出发Q例如:(x)
HSSFSheet sheet = wb.createSheet();
HSSFRow row = sheet.createRow((short)0);
HSSFCell cell = row.createCell((short)0);
cell.setCellValue(1);
row.createCell((short)1).setCellValue(1.2);
row.createCell((short)2).setCellValue("一个字W串");
row.createCell((short)3).setCellValue(true);
如果要设|单元格的样式,首先要创Z个样式对象,然后把它指定l一个单元格——或者把它指定给多个h相同样式的单元格Q例如,如果Excel表格?有一个摘要行Q摘要行的数据必L_体、斜体,你可以创Z个summaryRowStyle样式对象Q然后把q个样式指定l所有摘要行上的单元根{?br />
注意QCellFormat和CellStyle对象是工作簿对象的成员,单元格对象只是引用它们?br />
...
HSSFCellStyle style = workbook.createCellStyle();
style.setDataFormat
(HSSFDataFormat.getBuiltinFormat("($#,##0_);[Red]($#,##0)"));
style.setFillBackgroundColor(HSSFColor.AQUA.index);
style.setFillPattern(HSSFCellStyle.BIG_SPOTS);
...
someCell.setCellStyle(style);
someOtherCell.setCellStyle(style);
版本较新的HSSF允许使用数量有限的Excel公式。这一功能目前q是“BetaU质?#8221;Q正式用之前务必仔l测试。指定公式的方式cdQsomeCell.setCellFormula(SUM(A1:A2:);?br />
当前Q公式中已经可以调用所有内建的函数或操作符Q但逻辑操作W和函数Q例如IF函数Q除外,q部分功能目前还在开发之中?br />
五、通过eventusermodeld文g
通过eventusermodeld文g要比使用usermodel复杂得多Q但效率也要高(sh),因ؓ(f)它要求应用程序一边读取数据,一边处理数据?eventusermodel实际上模拟了(jin)DOM环境下SAX处理XML文档的办法,应用E序首先要注册期望处理的数据Qeventusermodel?在遇到匹配的数据l构时回调应用程序注册的Ҏ(gu)。用eventusermodel最大的困难在于你必ȝ(zhn)Excel工作的内部l构?br />
在HSSF中,低层ơ的二进制结构称录(RecordQ。记录有不同的类型,每一U类型由org.apache.poi.hssf.record?中的一个JavacLq。例如,BOFRecord记录表示Workbook或Sheet区域的开始,RowRecord表示有一个行存在q保存其样式?息。所有具有CellValueRecordInterface接口的记录表CExcel的单元格Q包括NumericRecord?LabelSSTRecord和FormulaRecordQ还有其他一些,其中部分已被弃置不用Q部分用于优化处理,但一般而言QHSSF可以转换?们)(j)?br />
下面是一个注册事件处理句柄的例子Q?br />
private EventRecordFactory factory = new EventRecordFactory();
factory.registerListener(new ERFListener() {
public boolean processRecord(Record rec) {
(got BOF Record);
return true;
}
}, new short[] {BOFRecord.sid});
factory.processRecords(someInputStream);
六、HSSF?sh)子表格l构
如前所qͼHSSF建立在POIFS的基上。具体地_(d)Excel 97+文g是OLE 2复合文档Q?OLE 2 Compound DocumentQ,底层的OLE 2复合文档保存?sh)(jin)一个L命名为WorkbookQExcel 95除外QHSSF不支持Excel 95Q的。然而,宏和囄q不保存在Workbook,它们有自q立的,有时甚至?x)放到OLE 2 CDF文g之内的另一个目录。理x况下Q宏也应该被保留Q不q目前POI目中还没有合适的API来处理宏?br />
每一个流之内是一l记录,一个记录其实就是一个字节数l,可分录头、记录体两部分。记录头指明?jin)记录的cdQ也即IDQ以?qing)后l数据的长度Q记录体被分割成多个字段QF(tun)ieldQ,字段包含数值数据(包括对其他记录的引用Q、字W数据或标记?br />
下图概要说明?jin)Excel工作的l构Q?br />
Bla.xls {
OLE2CDF headers
"Workbook" stream {
Workbook {
Static String Table Record..
Sheet names… and pointers
}
Sheet {
ROW
ROW
…
NUMBER RECORD (cell)
LABELSST Record (cell)
…
}
Sheet
}
}
… images, macros, etc.
Document Summary
Summary
七、通过HPSFd文档属?br />
在Microsoft Word、Excel、PowerPoint{Y件中Q用户可以通过“文g”→“属?#8221;菜单l文档添加附加信息,包括文档的标题、主题、摘要、类别、关键词{,同时应用软g本nq(sh)(x)加入最后访问的用户、最后访问和修改/打印的日期时间等信息?br />
文档的属性和正文是分开保存的。如前所qͼOLE 2 CDF文g内部p是一个容器,里面包含许多cM目录和文件的l构Q而POIFS是用来讉K其中的文件的工具。这些文件也UCؓ(f),文档的属性就保存?POIFS文gpȝ中专用的里面。以一个Word文档ZQ虽然在资源理器中你只看到一个叫做MyFile.doc的文档,其实在这个文档的内部Q又 包含?jin)一个WordDocument、一个SummaryInformation和一个DocumentSummaryInformation文档Q通常 q(sh)(x)有其他的文档Q这里暂且不?br />
你能够猜?gu)些文档(?j)分别包含什么内容吗Q不错,W(xu)ordDocument包含?jin)你?Word里面~辑的文本,文档的属性保存在SummaryInformation和DocumentSummaryInformation里面。也许将 所有属性保存在单个文档里面看v来太单了(jin)Q所以Microsoft军_(j)要用两个流Qؓ(f)?jin)事情更复杂一点,q两个流的名字前面还加上?jin)八q制?\005字符——这是一个不可打印的字符Q因此前面就把它省略?jin)?br />
Microsoft定义的标准属性有一个好处,它们q不在乎L档到底是什么类型——不是Word文档、Excel工作还是PowerPointqȝ。只要你知道如何dExcel文档的属性,q道了(jin)如何d其他文档的属性?br />
d文档属性其实ƈ不复杂,因ؓ(f)JavaE序可以利用POI目的HPSF包。HPSF?Horrible Property Set Format的羃写,译成中文是“讨厌的属性集格式”。HPSF包是POI目实现的读取属性工P目前q(sh)支持属性写入?br />
对于dMicrosoft定义的标准属性,通过HPSF提供的API可以很方便地办到Q但如果要读取Q意属性集p用到更一般化的APIQ可以想象它 要比d标准属性的API复杂不少。本文只介绍d标准属性的单APIQ因为对大多数应用程序来说这已经完全_?jin)?br />
下面是一个读取OLE 2 CDF文档的标题(titleQ属性的JavaE序Q?br />
import java.io.*;
import org.apache.poi.hpsf.*;
import org.apache.poi.poifs.eventfilesystem.*;
/**
* dOLE 2文档标题的示例程序,
* 在命令行参数中指定文档的文g名字?br />
*/
public class ReadTitle
{
public static void main(String[] args) throws IOException
{
final String filename = args[0];
POIFSReader r = new POIFSReader();
r.registerListener(new MyPOIFSReaderListener(),
"\005SummaryInformation");
r.read(new FileInputStream(filename));
}
static class MyPOIFSReaderListener
implements POIFSReaderListener
{
public void processPOIFSReaderEvent(POIFSReaderEvent event)
{
SummaryInformation si = null;
try
{
si = (SummaryInformation)
PropertySetFactory.create(event.getStream());
}
catch (Exception ex)
{
throw new RuntimeException
("属性集\"" + event.getPath() +
event.getName() + "\": " + ex);
}
final String title = si.getTitle();
if (title != null)
System.out.println("标题: \"" + title + "\"");
else
System.out.println("该文档没有标?");
}
}
}
main()Ҏ(gu)利用POIFS的事件系l从命o(h)行指定的OLE 2文档d名ؓ(f)\005SummaryInformation的流Q当P(yng)OIFSReader 遇到q个时Q它把控制传递给MyPOIFSReaderListener的processPOIFSReaderEvent()Ҏ(gu)?br />
processPOIFSReaderEvent() 到底有什么用呢?它通过参数获得一个输入流Q该输入包含了(jin)文档标题{属性。ؓ(f)?jin)访问文档的属性,我们从输入流创徏一个PropertySet实例Q如下所C:(x)
si = (SummaryInformation) PropertySetFactory.create(event.getStream());
q个语句其实包含三个步骤的操作:(x)
?event.getStream()从POIFSReader传入的POIFSReaderEvent获得输入?br />
?以刚才获得的输入ؓ(f)参数Q调用PropertySetFactory的静(rn)态方法create()。正如其名字所暗示的, PropertySetFactory是一个工厂类Q它有一?#8220;机器”能够把一个输入流转换成一个PropertySet实例Q这台机器就是create ()Ҏ(gu)?br />
?把create()Ҏ(gu)q回的PropertySet定型QcastQ成为SummaryInformation。PropertySet提供?jin)按照一?办法d属性集的各U机ӞSummaryInformation是PropertySet的子c,即SummaryInformationcd PropertySetcȝ基础上增加了(jin)操作Microsoft标准属性的便捷Ҏ(gu)?br />
在这个处理过E中Q可能引起错误的因素?多,因此我们把这部分内容攑օ?jin)一个try块——不q这个示例程序只按照最单的方式处理?jin)异常,在实际应用中Q最好能够对可能出现的不同异常类型分别处 理。除?jin)一般的I/O异常之外Q还有可能遇到HPSFҎ(gu)的异常,例如Q如果输入流不包含属性集或属性集非法Q就?x)抛?NoPropertySetStreamException异常?br />
有一U错误不太常见,但也不是l无可能——\005SummaryInformation包含一个合法的属性集Q但不是摘要信息属性集。如果出现这U情况,则定型成SummaryInformation操作?x)失败,引发ClassCastException异常?br />
获得SummaryInformation实例之后Q剩下的事情很单了(jin)Q只要调用getTitle()Ҏ(gu)Q然后输出结果?br />
除了(jin)getTitle()之外QSummaryInformationq包含其他一些便h法,例如getApplicationName()?getAuthor()、getCharCount()、和getCreateDateTime(){。HPSF的JavaDoc文档详细说明?jin)所有这?Ҏ(gu)?br />
八、文档摘要信?br />
遗憾的是Qƈ非所有的属性都保存在摘要信息属性集之中。许多(但不是全部)(j)OLE 2文gq有另一个属性集Q称?#8220;文档摘要信息”Q对应的是\005DocumentSummaryInformation。这个属性集保存的属性包括文 档的cd、PowerPointqȝ的多媒体剪辑数量Q等{?br />
要访问文档摘要信息属性集Q程序的处理q程也和上例怼Q只是注?的目标应该改成\005DocumentSummaryInformation——有Ӟ你可能想要同时注册到摘要信息和文档摘要信息这两个。其余的 处理方式和前面的例子差不多,你应该把包含文档摘要信息的流传递给PropertySetFactory.create()Q但q次工厂Ҏ(gu)返回一?DocumentSummaryInformation对象Q而不是前面例子中的SummaryInformation对象Q。如果同时注册到?jin)两个流Q?注意(g)查返回值的具体cdQ或者用Java的instanceof操作W,或者用专用的isSummaryInformation()?isDocumentSummaryInformation()Ҏ(gu)。记住,create()Ҏ(gu)q回的L一个PropertySet对象Q因此你L 可以对create()q回对象调用isSummaryInformation()和isDocumentSummaryInformation()?法,PropertySetcM所以要提供q两个方法,是因为属性集可能是自定义的?br />
如果你想要处理自定义的属性集Q或者要从标准的属性集d用户定义的属性,必须使用一个更一般化的APIQ前面已l提刎ͼq个API要复杂得多,本文不再讨论Q请参见HPSF的HOW-TO文档和POI的文档?br />
l束语:(x)本文探讨?jin)HSSF的应用以?qing)如何输出到Excel文gQ另外还涉及(qing)?jin)HPSF以及(qing)如何d属性集文档摘要信息。POI是一个功能非常强大的?目,许多主题本文未涉及(qing)Q例如如何用HSSF SerializerXML文档转换成Excel格式{,q一切就有待你自己去研究?jin)?br />
参考:(x)
Jakarta POI目主页
Jakarta POI 源代?br />
?ji)、附?br />
实例Q利用Servlet创徏和返回一个工作簿?br />
package org.apache.poi.hssf.usermodel.examples;
import java.io.*;
import java.net.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.poi.hssf.usermodel.*;
public class HSSFCreate extends HttpServlet {
public void init(ServletConfig config)
throws ServletException {
super.init(config);
}
public void destroy() {
}
/** 处理HTTP GET 和POSTh
* @param requestQ请?br />
* @param responseQ应{?br />
*/
protected void processRequest(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("application/vnd.ms-excel");
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet("new sheet");
// 创徏一个新的行Q添加几个单元格?br />
// 行号?开始计?br />
HSSFRow row = sheet.createRow((short)0);
// 创徏一个单元格Q设|单元格的?br />
HSSFCell cell = row.createCell((short)0);
cell.setCellValue(1);
row.createCell((short)1).setCellValue(1.2);
row.createCell((short)2).setCellValue("一个字W串?);
row.createCell((short)3).setCellValue(true);
// 写入输出l果
OutputStream out = response.getOutputStream();
wb.write(out);
out.close();
}
/** 处理HTTP GETh
* @param requestQ请?br />
* @param responseQ应{?br />
*/
protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/** 处理HTTP POSTh
* @param requestQ请?br />
* @param responseQ应{?br />
*/
protected void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
/** q回关于Servlet的简单说?br />
*/
public String getServletInfo() {
return "CZQ在Servlet中用HSSF创徏Excel工作?;
}
}
POI HSSF 操作MS Excelq?(OMIS二期设计阶段LExcel导入导出实现Ҏ(gu)Q?br />
POI HSSF 操作MS Excelq?br />
POI HSSF是一个专门操作EXCEL的java包,可通过Ujava操作xls文g?br />
POI HSSF的类文g都放在在org.apache.poi.hssf包下Q通过此包中的cd可实现用java操作Excel文g?jin)?br />
下面是用POI HSSF操作Excel文g的方法简qͼ(x)
一Q?建立Excel工作?br />
HSSFWorkbook wb = new HSSFWorkbook();
二, 建立Excel工作表,每个工作表对应的是Excel界面左下角的一个标{sheet1Qsheet2 …
HSSFSheet sheet1 = wb.createSheet("new sheet");
三, 在工作表中徏立单元格
//首先Q徏立行对像Q行号作为参ClcreateRowҎ(gu)Q第一行由0开始计?br />
HSSFRow row = sheet.createRow((short)0);
//建单元格
HSSFCell cell = row.createCell((short)0);
//l单元格赋?br />
cell.setCellValue(1);
//也可同一行内完成建立单元格和赋?br />
row.createCell((short)1).setCellValue(1.2);
row.createCell((short)2).setCellValue("This is a string");
row.createCell((short)3).setCellValue(true);
//数据格式可通过创徏单元格值时默认如上面所?br />
//也可以创建单元格后调用setCellType指定
cell.setCellType(CELL_TYPE_NUMERIC);
四, 向单元格插入日期?br />
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet("new sheet");
// 可通过Sheet.setSheetName(sheetindex,"SheetName",encoding)讑֮工作表名
// 创徏新行q向其加入单元格Q行L(fng)0开始?br />
HSSFRow row = sheet.createRow((short)0);
// 创徏一个单元格q向其输入一日期|但这W一个单元格q是日期格式?br />
HSSFCell cell = row.createCell((short)0);
cell.setCellValue(new Date());
// 我们这W二个单元格Ҏ(gu)日期格式Q这需要从工作薄创Z个新的单元格格式Q这?/ 以只影响当前建立的一个单元格?br />
HSSFCellStyle cellStyle = wb.createCellStyle();
cellStyle.setDataFormat(HSSFDataFormat.getBuiltinFormat("m/d/yy h:mm"));
cell = row.createCell((short)1);
cell.setCellValue(new Date());
cell.setCellStyle(cellStyle);
五, 各种单元格样?br />
HSSFCellStyle cellStyle = wb.createCellStyle();
//寚w
cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER);
//带边?br />
cellStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN);
//颜色与填充样?br />
cellStyle.setFillBackgroundColor(HSSFColor.AQUA.index);
cellStyle.setFillPattern(HSSFCellStyle.BIG_SPOTS);
cellStyle.setFillForegroundColor(HSSFColor.ORANGE.index);
cellStyle.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
六, 行高,列宽?br />
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet("new sheet");
HSSFRow row = sheet.createRow((short)0);
//2是行高?br />
row.setRowHeight(2);
//3是列P4是列宽?br />
sheet.setColumnWidth(3, 4);
七,例程
?先调用一个方法将Oracle数据库中的数据取出,攑ֈList实例中,q里我调用了(jin)srrd目中ProductDatacȝ listProductQuery()取得一个List实例。List中的对象是一pd名ؓ(f)ProductQuery实体cȝ实例。然后读ListQ将 ProductQuery实例中的数据取出攑ֈHSSFCell单元g。最后将HSSFWorkbook中的数据输出到输出流Q完成数据导出?br />
//建工作薄
HSSFWorkbook wb = new HSSFWorkbook();
//建名为example的工作表
HSSFSheet sheet = wb.createSheet("example");
//l工作表?列定义列?br />
sheet.setColumnWidth((short)0,(short)2500);
sheet.setColumnWidth((short)1,(short)6000);
sheet.setColumnWidth((short)2,(short)3500);
sheet.setColumnWidth((short)3,(short)9000);
sheet.setColumnWidth((short)4,(short)8000);
sheet.setColumnWidth((short)5,(short)8000);
sheet.setColumnWidth((short)6,(short)20000);
sheet.setColumnWidth((short)7,(short)8000);
//在表中徏?br />
HSSFRow row = sheet.createRow(0);
//建立单元?br />
HSSFCell cell[] = new HSSFCell[8];
for (short i = 0; i < 8; i++) {
cell= row.createCell(i);
//单元格定义成UTF_16~码Q这h能输出数据不会(x)q
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
}
//写单元格标题
cell[0].setCellValue("登记ID");
cell[1].setCellValue("登记?);
cell[2].setCellValue("所在地?jng)ID");
cell[3].setCellValue("产品中文?);
cell[4].setCellValue("产品英文?);
cell[5].setCellValue("产品服务对象");
cell[6].setCellValue("产品功能描述");
cell[7].setCellValue("产品cd");
//查询数据库,取得数据列表的List实例
List list = new ArrayList();
ProductDataManager mgr = new ProductDataManager();
try {
list = mgr.listProductQuery("","", "", "", "", "1999-2-1", "2004-2-1");
} catch (SrrdException e) {
e.printStackTrace();
}
//从List中取出数据放入工作表?br />
if (list != null && list.size() > 0) {
for (int i = 0; i < list.size() - 1; i++) {
ProductQuery query = (ProductQuery) list.get(i);
HSSFRow datarow = sheet.createRow(i + 1);
HSSFCell data[] = new HSSFCell[8];
for (short j = 0; j < 8; j++) {
data[j] = datarow.createCell(j);
//单元格定义成UTF_16~码Q这h能输出数据不会(x)q
data[j].setEncoding(HSSFCell.ENCODING_UTF_16);
}
data[0].setCellValue(query.getCertId());
data[1].setCellValue(query.getCertNum());
data[2].setCellValue(query.getCityCode());
data[3].setCellValue(query.getSoftWareCname());
data[4].setCellValue(query.getSoftWareEname());
data[5].setCellValue(query.getSoftwareFor());
data[6].setCellValue(query.getSoftwareFuncDesc());
data[7].setCellValue(query.getSoftwareType());
}
}
//工作薄输出到输出流
ServletOutputStream sos=response.getOutputStream();
wb.write(sos);
sos.close();
//也可输出成xls文g
File file = new File("workbook.xls");
try {
FileOutputStream fileOut = new FileOutputStream(file);
wb.write(fileOut);
fileOut.close();
} catch (IOException e) {
e.printStackTrace();
}
/*****************************************************/
package com.kang.test.project;
import org.apache.log4j.Logger;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Calendar;
import java.util.List;
import javax.servlet.ServletOutputStream;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFFont;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.util.HSSFColor;
public class TestPOI {
/**
* Logger for this class
*/
private static final Logger log = Logger.getLogger(TestPOI.class);
private static String xmlFile=String.valueOf(Calendar.getInstance().getTimeInMillis())+".xls";
private static String file_path="e:\\";
public static void main(String[] args) {
TestPOI tpoi=new TestPOI();
String temp=file_path+xmlFile;
log.info("-----temp:"+temp);
tpoi.creatExcelByPOI(temp);
tpoi.getExcelConmentByPOI(temp);
}
/**
* 生成excel文g
*
* @param filename
*/
public void creatExcelByPOI(String filename){
log.info("-----生成excel文g-----开?----filename:"+filename);
FileOutputStream ops=null;
HSSFWorkbook workbook=new HSSFWorkbook();
HSSFSheet sheet=workbook.createSheet();
sheet.setColumnWidth((short)0, (short)2000);
sheet.setColumnWidth((short)1, (short)4000);
sheet.setColumnWidth((short)2, (short)4000);
sheet.setColumnWidth((short)3, (short)8000);
sheet.setColumnWidth((short)4, (short)1000);
sheet.setColumnWidth((short)5, (short)2000);
sheet.setColumnWidth((short)6, (short)2000000);
sheet.setColumnWidth((short)7, (short)200000);
sheet.setColumnWidth((short)8, (short)20000);
sheet.setColumnWidth((short)9, (short)20000);
//sheet.setDefaultColumnWidth((short)50);
for(int i=0;i<10;i++){
log.info("-----i:"+"W?+i+"?);
HSSFRow row=sheet.createRow((short)i);
for (int j=0;j<10;j++){
HSSFCell cell = row.createCell((short)j);
/**
* 讄其它数据 讄风格
*/
HSSFCellStyle style = workbook.createCellStyle();
style.setBorderBottom(HSSFCellStyle.BORDER_THIN); // 讄单无格的Ҏ(gu)为粗?br />
style.setBottomBorderColor(HSSFColor.BLACK.index); // 讄单元格的Ҏ(gu)颜色Q?br />
style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
style.setLeftBorderColor(HSSFColor.BLACK.index);
style.setBorderRight(HSSFCellStyle.BORDER_THIN);
style.setRightBorderColor(HSSFColor.BLACK.index);
style.setBorderTop(HSSFCellStyle.BORDER_THIN);
style.setTopBorderColor(HSSFColor.BLACK.index);
// style.setWrapText(true);//文本区域随内容多自动调?br />
// style.setFillForegroundColor(HSSFColor.LIME.index);
// style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
style.setBorderBottom(HSSFCellStyle.BORDER_THIN); // 讄单无格的Ҏ(gu)为粗?br />
style.setBottomBorderColor(HSSFColor.BLACK.index); // 讄单元格的Ҏ(gu)颜色Q?br />
style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
style.setLeftBorderColor(HSSFColor.BLACK.index);
style.setBorderRight(HSSFCellStyle.BORDER_THIN);
style.setRightBorderColor(HSSFColor.BLACK.index);
style.setBorderTop(HSSFCellStyle.BORDER_MEDIUM);
style.setTopBorderColor(HSSFColor.BLACK.index);
style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);// 最好的讄Pattern
// 单元D景的昄模式Q?br />
style.setFillForegroundColor(new HSSFColor.BLUE_GREY().getIndex()); // 讄单元D景色;
style.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 水^寚w方式
// style.setWrapText(true); //文本区域随内容多自动调?br />
// style.setFillPattern(HSSFCellStyle.//);
// 讄字体Color,首先创徏Font对象,后对font讄,然后做ؓ(f)参数传给style
HSSFFont font = workbook.createFont();
font.setColor(HSSFFont.SS_NONE);
// font.setFontHeightInPoints((short)24);
font.setFontName("Courier New");
// font.setItalic(true);
// font.setStrikeout(true);//l字体加上删除线
font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
style.setFont(font);
style.setWrapText(true);
cell.setCellStyle(style);
//cell.setCellNum((short)(i*10+j));
cell.setCellType(HSSFCell.CELL_TYPE_STRING);
cell.setEncoding(HSSFCell.ENCODING_UTF_16);
cell.setCellStyle(style);
cell.setCellValue("今天是第"+j+"天,好好学习(fn)天天向上Q解x法我已经扑ֈ?jin),具体应该是这L(fng)用poi包的hssfQ怎样让excel中的单元格cell里面的文字自动换行啊");
log.info("-----j:"+"W?+j+"?);
}
}
try {
ops=new FileOutputStream(filename);
workbook.write(ops);
ops.flush();
/**
* 在servlet或Controller?br />
* response.setContentType("application/vnd.ms-excel");
* response.addHeader("Content-Disposition","attachment;filename=testReport.xls");//讄下蝲的文件名U?br />
* ServletOutputStream output=response.getOutputStream();
* workbook.write(output);
* output.close();
*/
} catch (FileNotFoundException e) {
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}finally{
try {
ops.close();
} catch (IOException e) {
e.printStackTrace();
}
}
log.info("-----生成excel文g-----完毕-----");
}
/**
* 解析excel文g
* @param filename
*/
public void getExcelConmentByPOI(String filename){
log.info("-----解析excel文g-----开?----filename:"+filename);
InputStream is;
try {
is = new FileInputStream(filename);
HSSFWorkbook book=new HSSFWorkbook(is);
HSSFSheet sheet=book.getSheetAt(0);
log.info("-----sheet.getPhysicalNumberOfRows():"+sheet.getPhysicalNumberOfRows());
for(int i=0;i<sheet.getPhysicalNumberOfRows();i++){
HSSFRow row=sheet.getRow(i);
log.info("-----W?+i+"?);
for(int j=0;j<row.getPhysicalNumberOfCells();j++){
HSSFCell cell=row.getCell((short)j);
log.info("-----W?+j+"?内容Q?+cell.getStringCellValue());
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
log.info("-----解析excel文g-----完毕-----");
}
/**
*
*/
public void getExcelOnWeb(){
}
}
再看java的String replaceAll(String regex, String replacement)Ҏ(gu)的例?
把字W串ab.c变成ab/c
String.replaceAll()是用regular expression 来作为参数的。但是java本n的字W串对于转义W\也有cM的处理。首先,java?x)?#8220;\\\\”解释成一个字W串(其中包含两个char)—?#8220;\\”q个是你在JDK的文档里看到的?
接下来,׃replaceAll是以正则表达式作为参敎ͼ所?#8220;\\”被解释成一个regex。对于一个regex来说q就代表着一个字W,是“\”。对后面的那?个\来说Q最l会(x)被解释成“\\”?
再来个例?
Microsoft的Officepd产品拥有大量的用PW(xu)ord、Excel也成为办公文件的首选。在Java中,已经有很多对于Word、Excel的开源的解决Ҏ(gu)Q其中比较出色的是Apache的Jakata目的POI子项目。该目的官方网站是http://jakarta.apache.org/poi/?/p>
POI包括一pd的APIQ它们可以操作基于MicroSoft OLE 2 Compound Document Format的各U格式文Ӟ可以通过q些API在Java中读写Excel、Word{文件。POI是完全的Java Excel和Java Word解决Ҏ(gu)。POI子项目包括:(x)POIFS、HSSF、HDF、HPSF。表7-2对它们进行了(jin)要介l?/p>
?-2 POI子项目介l?
子项目名 |
说明 |
POIFS(POI File System) |
POIFS是POI目中最早的最基础的一个模块,是Java到OLE 2 Compound Document Format的接口,支持d功能Q所有的其他目都依赖与该项目?/p> |
HSSF(Horrible Spreadsheet Format) |
HSSF是Java到Microsoft Excel 97(-2002)文g的接口,支持d功能 |
HWPF(Horrible Word Processing Format) |
HWPF是Java到Microsoft Word 97文g的接口,支持d功能Q但目前该模块还处于刚开始开发阶D,只能实现一些简单文件的操作Q在后箋版本中,?x)提供更强大的支?/p> |
HPSF(Horrible Property Set Format) |
HPSF 是Java到OLE 2 Compound Document Format文g的属性设|的接口Q属性设|通常用来讄文档的属性(标题Q作者,最后修Ҏ(gu)期等Q,q可以设|用户定义的属性。HPSF支持d功能Q当前发布版本中直支持读功能?/p> |
7.3.1 对Excel的处理类
下面通过HSSF提供的接口对Excel文gl行处理。首先需要下载POI的包Q可以到apache的官方网站下载,地址为:(x)http://apache.justdn.org/jakarta/poi/Q本书采用的是poi-2.5.1-final-20040804.jarQ读者可以下载当前的E_版本。把下蝲的包按照前面介绍的方式加入Build PathQ然后新Z个ch7.poi包,q创Z个ExcelReadercR?/p>
ExcelReadercd以读取一个XLS文gQ然后将其内定w行提取出来Q写入文本文件。其代码如下?/p>
代码7.6
public class ExcelReader {
// 创徏文g输入?/p>
private BufferedReader reader = null;
// 文gcd
private String filetype;
// 文g二进制输入流
private InputStream is = null;
// 当前的Sheet
private int currSheet;
// 当前位置
private int currPosition;
// Sheet数量
private int numOfSheets;
// HSSFWorkbook
HSSFWorkbook workbook = null;
// 讄Cell之间以空格分?/p>
private static String EXCEL_LINE_DELIMITER = " ";
// 讄最大列?/p>
private static int MAX_EXCEL_COLUMNS = 64;
// 构造函数创Z个ExcelReader
public ExcelReader(String inputfile) throws IOException, Exception {
// 判断参数是否为空或没有意?/p>
if (inputfile == null || inputfile.trim().equals("")) {
throw new IOException("no input file specified");
}
// 取得文g名的后缀名赋值给filetype
this.filetype = inputfile.substring(inputfile.lastIndexOf(".") + 1);
// 讄开始行?
currPosition = 0;
// 讄当前位置?
currSheet = 0;
// 创徏文g输入?/p>
is = new FileInputStream(inputfile);
// 判断文g格式
if (filetype.equalsIgnoreCase("txt")) {
// 如果是txt则直接创建BufferedReaderd
reader = new BufferedReader(new InputStreamReader(is));
}
else if (filetype.equalsIgnoreCase("xls")) {
// 如果是Excel文g则创建HSSFWorkbookd
workbook = new HSSFWorkbook(is);
// 讄Sheet?/p>
numOfSheets = workbook.getNumberOfSheets();
}
else {
throw new Exception("File Type Not Supported");
}
}
// 函数readLined文g的一?/p>
public String readLine() throws IOException {
// 如果是txt文g则通过readerd
if (filetype.equalsIgnoreCase("txt")) {
String str = reader.readLine();
// I则略去,直接d下一?/p>
while (str.trim().equals("")) {
str = reader.readLine();
}
return str;
}
// 如果是XLS文g则通过POI提供的APId文g
else if (filetype.equalsIgnoreCase("xls")) {
// Ҏ(gu)currSheetD得当前的sheet
HSSFSheet sheet = workbook.getSheetAt(currSheet);
// 判断当前行是否到但前Sheet的结?/p>
if (currPosition > sheet.getLastRowNum()) {
// 当前行位|清?/p>
currPosition = 0;
// 判断是否q有Sheet
while (currSheet != numOfSheets - 1) {
// 得到下一张Sheet
sheet = workbook.getSheetAt(currSheet + 1);
// 当前行数是否已经到达文g末尾
if (currPosition == sheet.getLastRowNum()) {
// 当前Sheet指向下一张Sheet
currSheet++;
continue;
} else {
// 获取当前行数
int row = currPosition;
currPosition++;
// d当前行数?/p>
return getLine(sheet, row);
}
}
return null;
}
// 获取当前行数
int row = currPosition;
currPosition++;
// d当前行数?/p>
return getLine(sheet, row);
}
return null;
}
// 函数getLineq回Sheet的一行数?/p>
private String getLine(HSSFSheet sheet, int row) {
// Ҏ(gu)行数取得Sheet的一?/p>
HSSFRow rowline = sheet.getRow(row);
// 创徏字符创缓冲区
StringBuffer buffer = new StringBuffer();
// 获取当前行的列数
int filledColumns = rowline.getLastCellNum();
HSSFCell cell = null;
// 循环遍历所有列
for (int i = 0; i < filledColumns; i++) {
// 取得当前Cell
cell = rowline.getCell((short) i);
String cellvalue = null;
if (cell != null) {
// 判断当前Cell的Type
switch (cell.getCellType()) {
// 如果当前Cell的Type为NUMERIC
case HSSFCell.CELL_TYPE_NUMERIC: {
// 判断当前的cell是否为Date
if (HSSFDateUtil.isCellDateFormatted(cell)) {
// 如果是Datecd则,取得该Cell的Date?/p>
Date date = cell.getDateCellValue();
// 把Date转换成本地格式的字符?/p>
cellvalue = cell.getDateCellValue().toLocaleString();
}
// 如果是纯数字
else {
// 取得当前Cell的数?/p>
Integer num = new Integer((int) cell
.getNumericCellValue());
cellvalue = String.valueOf(num);
}
break;
}
// 如果当前Cell的Type为STRIN
case HSSFCell.CELL_TYPE_STRING:
// 取得当前的Cell字符?/p>
cellvalue = cell.getStringCellValue().replaceAll("'", "''");
break;
// 默认的Cell?/p>
default:
cellvalue = " ";
}
} else {
cellvalue = "";
}
// 在每个字D之间插入分割符
buffer.append(cellvalue).append(EXCEL_LINE_DELIMITER);
}
// 以字W串q回该行的数?/p>
return buffer.toString();
}
// close函数执行的关闭操作
public void close() {
// 如果is不ؓ(f)I,则关闭InputSteam文g输入?/p>
if (is != null) {
try {
is.close();
} catch (IOException e) {
is = null;
}
}
// 如果reader不ؓ(f)I则关闭BufferedReader文g输入?/p>
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
reader = null;
}
}
}
}
7.3.2 ExcelReader的运行效?/p>
下面创徏一个main函数Q用来测试上面的ExcelReaderc,代码如下?/p>
代码7.7
public static void main(String[] args) {
try{
ExcelReader er=new ExcelReader("c:\\xp.xls");
String line=er.readLine();
while(line != null){
System.out.println(line);
line=er.readLine();
}
er.close();
}catch(Exception e){
e.printStackTrace();
}
}
main函数先创Z个ExcelReaderc,然后调用它提供的接口readLineQ对XLS文gq行dQ打印到控制収ͼ处理前的XLS文g如图7-12所C?/p>
?-12 处理前的XLS文g内容
q行main函数q行内容提取后,Eclipse的控制台输出如图7-13所C?/p>
?-13 输出l果
可以看到QExcel文g中的内容已经被成功的输出?jin)出来?/p>
7.3.3 POI中Excel文gCell的类?/p>
在读取每一个Cell的值的时候,通过getCellTypeҎ(gu)获得当前Cell的类型,在Excel中Cell?U类型,如表7-3所C?/p>
?-3 Cell的类?
CellType |
说明 |
CELL_TYPE_BLANK |
I?/p> |
CELL_TYPE_BOOLEAN |
布尔?/p> |
CELL_TYPE_ERROR |
错误 |
CELL_TYPE_FORMULA |
公式?/p> |
CELL_TYPE_STRING |
字符串型 |
CELL_TYPE_NUMERIC |
数值型 |
本例采用?jin)CELL_TYPE_STRING和CELL_TYPE_NUMERICcdQ因为在Excel文g中只有字W串和数字。如果Cell的Type为CELL_TYPE_NUMERICӞq需要进一步判断该Cell的数据格式,因ؓ(f)它有可能是DatecdQ在Excel中的Datecd也是以Doublecd的数字存储的。Excel中的Date表示当前旉?900q??日相隔的天数Q所以需要调用HSSFDateUtil的isCellDateFormattedҎ(gu)Q判断该Cell的数据格式是否是Excel Datecd。如果是Q则调用getDateCellValueҎ(gu)Q返回一个Javacd的Date?/p>
实际上Excel的数据格式有很多Q还支持用户自定义的cdQ在Excel中,选择一个单元格然后右键选择“讄单元格格?#8221;Q在弹出的单元格格式中选中“数字”Q如?-14所C?/p>
?-14 Excel的单元格格式
图中的数据有数倹{货币、时间、日期、文本等格式。这些数据格式在POI中的HSSFDataFormatc里都有相应的定义?/p>
HSSFDataFormat是HSSF子项目里面定义的一个类。类HSSFDataFormat允许用户新徏数据格式cd。HSSFDataFormatcd含静(rn)态方法static java.lang.String getBuiltinFormat(short index)Q它可以Ҏ(gu)~号q回内置数据cd。另外static short getBuiltinFormat(java.lang.String format)Ҏ(gu)则可以根据数据类型返回其~号Qstatic java.util.List getBuiltinFormats()可以q回整个内置的数据格式列表?/p>
在HSSFDataFormat里一共定义了(jin)49U内|的数据格式Q如?-4所C?/p>
?-4 HSSFDataFormat的数据格?/p>
内置数据cd |
~号 |
"General" |
0 |
"0" |
1 |
"0.00" |
2 |
"#,##0" |
3 |
"#,##0.00" |
4 |
"($#,##0_);($#,##0)" |
5 |
"($#,##0_);[Red]($#,##0)" |
6 |
"($#,##0.00);($#,##0.00)" |
7 |
"($#,##0.00_);[Red]($#,##0.00)" |
8 |
"0%" |
9 |
"0.00%" |
0xa |
"0.00E+00" |
0xb |
"# ?/?" |
0xc |
"# ??/??" |
0xd |
"m/d/yy" |
0xe |
"d-mmm-yy" |
0xf |
"d-mmm" |
0x10 |
"mmm-yy" |
0x11 |
"h:mm AM/PM" |
0x12 |
"h:mm:ss AM/PM" |
0x13 |
"h:mm" |
0x14 |
"h:mm:ss" |
0x15 |
"m/d/yy h:mm" |
0x16 |
保留国际化用 |
0x17 - 0x24 |
"(#,##0_);(#,##0)" |
0x25 |
"(#,##0_);[Red](#,##0)" |
0x26 |
"(#,##0.00_);(#,##0.00)" |
0x27 |
"(#,##0.00_);[Red](#,##0.00)" |
0x28 |
"_($*#,##0_);_($*(#,##0);_($* \"-\"_);_(@_)" |
0x29 |
"_(*#,##0.00_);_(*(#,##0.00);_(*\"-\"??_);_(@_)" |
0x2a |
"_($*#,##0.00_);_($*(#,##0.00);_($*\"-\"??_);_(@_)" |
0x2b |
"_($*#,##0.00_);_($*(#,##0.00);_($*\"-\"??_);_(@_)" |
0x2c |
"mm:ss" |
0x2d |
"[h]:mm:ss" |
0x2e |
"mm:ss.0" |
0x2f |
"##0.0E+0" |
0x30 |
"@" - This is text format |
0x31 |
在上面表中,字符串类型所对应的是数据格式?@"Q最后一行)(j)Q也是HSSFDataFormat中定义的gؓ(f)0x31Q?9Q的那行。Datecd的值的范围?xe-0x11Q本例子中的Date格式?"m/d/yy""Q在HSSFDataFormat定义的gؓ(f)0xeQ?4Q?/p>
需要注意的一Ҏ(gu)Q所创徏的Excel必须是在Microsoft Excel 97到Excel XP的版本上的,如果在Excel 2003中创建文件后Q在使用POIq行解析Ӟ可能?x)出现问题。它?x)把Datecd当作自定义类型。POI目前只提供对Microsoft Excel XP以下的版本的支持Q在以后的版本中Q希望会(x)提供对Microsoft Excel 2003更好的支持?/p>
7.3.4 对Word的处理类
除了(jin)支持对Excel文g的读取外QPOIq提供对Word的DOC格式文g的读取。但在它的发行版本中没有发布对Word支持的模块,需要另外下载一个POI的扩展的Jar包。用户可以到http://www.ibiblio.org/maven2/org/textmining/tm-extractors/0.4/下蝲Q本书采用的是tm-extractors-0.4_zip?/p>
下蝲后,把该包加入工E的Build Path中,然后在ch7.poi包下新徏一个类WordReaderQ该cL供一个静(rn)态方法r(sh)eadDocQ读取一个DOC文gq返回文本。函数内容很单,是调用WordExtractor的API来提取DOC的内容到字符Ԍ该函数的代码如下?/p>
代码7.8
public static String readDoc(String doc) throws Exception {
// 创徏输入读取DOC文g
FileInputStream in = new FileInputStream(new File(doc));
WordExtractor extractor = null;
String text = null;
// 创徏WordExtractor
extractor = new WordExtractor();
// 对DOC文gq行提取
text = extractor.extractText(in);
return text;
}
在同一个类里创Z个main函数Q测试WordReaderQ该main函数代码如下?/p>
代码7.9
public static void main(String[] args) {
try{
String text = WordReader.readDoc("c:/test.doc");
System.out.println(text);
}catch(Exception e){
e.printStackTrace();
}
}
处理前的Doc文g如图7-15所C?/p>
?-15 处理前的Word文档
使用代码处理后的文本如图7-16所C?/p>
?-16 处理后的l果
可以看到Word文档内的文本已经全部被提取了(jin)出来?/p>
请先看下面这D늨序:(x)
public class Hello{
public static void main(String[] args){ //(1)
System.out.println("Hello,world!"); //(2)
}
}
看过q段E序Q对于大多数学过Java 的从来说Q都不陌生。即使没有学qJavaQ而学q其它的高语言Q例如CQ那你也应该能看懂这D代码的意思。它只是单的输出“Hello,world”Q一点别的用处都没有Q然而,它却展示?jin)static关键字的主要用法?/p>
?处,我们定义?jin)一个静(rn)态的Ҏ(gu)名ؓ(f)mainQ这意味着告诉Java~译器,我这个方法不需创徏一个此cȝ对象卛_使用。你q得你是怎么q行q个E序吗?一般,我们都是在命令行下,打入如下的命?加下划线为手动输?Q?/p>
javac Hello.java
java Hello
Hello,world!
q就是你q行的过E,W一行用来编译Hello.javaq个文gQ执行完后,如果你查看当前,?x)发现多了(jin)一个Hello.class文gQ那是W一行生的Java二进制字节码。第二行是执行一个JavaE序的最普遍做法。执行结果如你所料。在2中,你可能会(x)惻IZ么要q样才能输出。好Q我们来分解一下这条语句。(如果没有安装Java文档Q请到Sun的官方网站浏览J2SE APIQ首先,System是位于java.lang包中的一个核?j)类Q如果你查看它的定义Q你?x)发现有q样一行:(x)public static final PrintStream out;接着在进一步,点击PrintStreamq个链接,在METHOD面Q你?x)看到大量定义的?gu)Q查找printlnQ会(x)有这样一行:(x)
public void println(String x)?/p>
好了(jin)Q现在你应该明白Z么我们要那样调用?jin),out是System的一个静(rn)态变量,所以可以直接用,而out所属的cL一个printlnҎ(gu)?/p>
?rn)态方?/strong>
通常Q在一个类中定义一个方法ؓ(f)staticQ那是_(d)无需本类的对象即可调用此Ҏ(gu)。如下所C:(x)
class Simple{
static void go(){
System.out.println("Go...");
}
}
public class Cal{
public static void main(String[] args){
Simple.go();
}
}
调用一个静(rn)态方法就?#8220;cd.Ҏ(gu)?#8221;,?rn)态方法的使用很简单如上所C。一般来_(d)?rn)态方法常ؓ(f)应用E序中的其它cL供一些实用工h用,在Java的类库中大量的静(rn)态方法正是出于此目的而定义的?/p>
?rn)态变?/strong>
?rn)态变量与?rn)态方法类伹{所有此cd例共享此?rn)态变量,也就是说在类装蝲Ӟ只分配一块存储空_(d)所有此cȝ对象都可以操控此块存储空_(d)当然对于final则另当别Z(jin)。看下面q段代码Q?/p>
class Value{
static int c=0;
static void inc(){
c++;
}
}
class Count{
public static void prt(String s){
System.out.println(s);
}
public static void main(String[] args){
Value v1,v2;
v1=new Value();
v2=new Value();
prt("v1.c="+v1.c+" v2.c="+v2.c);
v1.inc();
prt("v1.c="+v1.c+" v2.c="+v2.c);
}
}
l果如下Q?/p>
v1.c=0 v2.c=0
v1.c=1 v2.c=1
由此可以证明它们׃n一块存储区。static变量有点cM于C中的全局变量的概c(din)值得探讨的是?rn)态变量的初始化问题。我们修改上面的E序Q?/p>
class Value{
static int c=0;
Value(){
c=15;
}
Value(int i){
c=i;
}
static void inc(){
c++;
}
}
class Count{
public static void prt(String s){
System.out.println(s);
}
Value v=new Value(10);
static Value v1,v2;
static{
prt("v1.c="+v1.c+" v2.c="+v2.c);
v1=new Value(27);
prt("v1.c="+v1.c+" v2.c="+v2.c);
v2=new Value(15);
prt("v1.c="+v1.c+" v2.c="+v2.c);
}
public static void main(String[] args){
Count ct=new Count();
prt("ct.c="+ct.v.c);
prt("v1.c="+v1.c+" v2.c="+v2.c);
v1.inc();
prt("v1.c="+v1.c+" v2.c="+v2.c);
prt("ct.c="+ct.v.c);
}
}
q行l果如下Q?/p>
v1.c=0 v2.c=0
v1.c=27 v2.c=27
v1.c=15 v2.c=15
ct.c=10
v1.c=10 v2.c=10
v1.c=11 v2.c=11
ct.c=11
q个E序展示?jin)?rn)态初始化的各U特性。如果你初次接触JavaQ结果可能o(h)你吃惊。可能会(x)对static后加大括h到困惑。首先要告诉你的是,static定义的变量会(x)优先于Q何其它非static变量Q不论其出现的顺序如何。正如在E序中所表现的,虽然v出现在v1和v2的前面,但是l果却是v1和v2的初始化在v的前面。在static{后面跟着一D代码,q是用来q行昑ּ的静(rn)态变量初始化Q这D代码只?x)初始化一ơ,且在c被W一ơ装载时。如果你能读懂ƈ理解q段代码Q会(x)帮助你对static关键字的认识。在涉及(qing)到承的时候,?x)先初始化父cȝstatic变量Q然后是子类的,依次cL。非?rn)态变量不是本文的主题Q在此不做详l讨论,请参考Think in Java中的讲解?/p>
?rn)态类
通常一个普通类不允许声明ؓ(f)?rn)态的Q只有一个内部类才可以。这时这个声明ؓ(f)?rn)态的内部cd以直接作Z个普通类来用,而不需实例一个外部类。如下代码所C:(x)
public class StaticCls{
public static void main(String[] args){
OuterCls.InnerCls oi=new OuterCls.InnerCls();
}
}
class OuterCls{
public static class InnerCls{
InnerCls(){
System.out.println("InnerCls");
}
}
}
输出l果?x)如你所料:(x)
InnerCls
和普通类一栗内部类的其它用法请参阅Think in Java中的相关章节Q此处不作详解?/p>
二、this & super
在上一拙作中Q我们讨Z(jin)static的种U用法,通过用static来定义方法或成员Qؓ(f)我们~程提供?jin)某U便利,从某U程度上可以说它cM于C语言中的全局函数和全局变量。但是,q不是说有了(jin)q种便利Q你便可以随处用,如果那样的话Q你侉K要认真考虑一下自己是否在用面向对象的思想~程Q自qE序是否是面向对象的。好?jin),现在开始讨论this&superq两个关键字的意义和用法?/p>
在Java中,this通常指当前对象,super则指父类的。当你想要引用当前对象的某种东西Q比如当前对象的某个Ҏ(gu)Q或当前对象的某个成员,你便可以利用this来实现这个目的,当然Qthis的另一个用途是调用当前对象的另一个构造函敎ͼq些马上p讨论。如果你惛_用父cȝ某种东西Q则非super莫属。由于this与super有如此相似的一些特性和与生俱来的某U关p,所以我们在q一块儿来讨论,希望能帮助你区分和掌握它们两个?/p>
在一般方法中
最普遍的情况就是,在你的方法中的某个Ş参名与当前对象的某个成员有相同的名字Q这时ؓ(f)?jin)不至于hQ你侉K要明用this关键字来指明你要使用某个成员Q用方法是“this.成员?#8221;Q而不带this的那个便是Ş参。另外,q可以用“this.Ҏ(gu)?#8221;来引用当前对象的某个Ҏ(gu)Q但q时this׃是必ȝ?jin),你可以直接用?gu)名来讉K那个Ҏ(gu)Q编译器?x)知道你要调用的是那一个。下面的代码演示?jin)上面的用法Q?/p>
public class DemoThis{
private String name;
private int age;
DemoThis(String name,int age){
setName(name); //你可以加上this来调用方法,像这P(x)this.setName(name);但这q不是必ȝ
setAge(age);
this.print();
}
public void setName(String name){
this.name=name;//此处必须指明你要引用成员变量
}
public void setAge(int age){
this.age=age;
}
public void print(){
System.out.println("Name="+name+" Age="+age);//在此行中q不需要用thisQ因为没有会(x)Dh的东?br> }
public static void main(String[] args){
DemoThis dt=new DemoThis("Kevin","22");
}
}
q段代码很简单,不用解释你也应该能看明白。在构造函C你看到用this.print(),你完全可以用print()来代替它Q两者效果一栗下面我们修改这个程序,来演Csuper的用法?/p>
class Person{
public int c;
private String name;
private int age;
protected void setName(String name){
this.name=name;
}
protected void setAge(int age){
this.age=age;
}
protected void print(){
System.out.println("Name="+name+" Age="+age);
}
}
public class DemoSuper extends Person{
public void print(){
System.out.println("DemoSuper:");
super.print();
}
public static void main(String[] args){
DemoSuper ds=new DemoSuper();
ds.setName("kevin");
ds.setAge(22);
ds.print();
}
}
在DemoSuper中,重新定义的printҎ(gu)覆写?jin)父cȝprintҎ(gu)Q它首先做一些自q事情Q然后调用父cȝ那个被覆写了(jin)的方法。输出结果说明了(jin)q一点:(x)
DemoSuper:
Name=kevin Age=22
q样的用方法是比较常用的。另外如果父cȝ成员可以被子c访问,那你可以像用this一样用它Q用“super.父类中的成员?#8221;的方式,但常怽q不是这h讉K父类中的成员名的?/p>
在构造函C
构造函数是一U特D的Ҏ(gu)Q在对象初始化的时候自动调用。在构造函CQthis和super也有上面说的U种使用方式Qƈ且它q有Ҏ(gu)的地方,L(fng)下面的例子:(x)
class Person{
public static void prt(String s){
System.out.println(s);
}
Person(){
prt("A Person.");
}
Person(String name){
prt("A person name is:"+name);
}
}
public class Chinese extends Person{
Chinese(){
super(); //调用父类构造函敎ͼ1Q?br> prt("A chinese.");//(4)
}
Chinese(String name){
super(name);//调用父类h相同形参的构造函敎ͼ2Q?br> prt("his name is:"+name);
}
Chinese(String name,int age){
this(name);//调用当前h相同形参的构造函敎ͼ3Q?br> prt("his age is:"+age);
}
public static void main(String[] args){
Chinese cn=new Chinese();
cn=new Chinese("kevin");
cn=new Chinese("kevin",22);
}
}
在这D늨序中Qthis和super不再是像以前那样?#8220;.”q接一个方法或成员Q而是直接在其后跟上适当的参敎ͼ因此它的意义也就有了(jin)变化。super后加参数的是用来调用父类中具有相同Ş式的构造函敎ͼ??处。this后加参数则调用的是当前具有相同参数的构造函敎ͼ?处。当?dng)在Chinese的各个重载构造函CQthis和super在一般方法中的各U用法也仍可使用Q比?处,你可以将它替换ؓ(f)“this.prt”(因ؓ(f)它承了(jin)父类中的那个Ҏ(gu)Q或者是“super.prt”Q因为它是父cM的方法且可被子类讉KQ,它照样可以正运行。但q样g有点画蛇添的味道?jin)?/p>
最后,写了(jin)q么多,如果你能?#8220;this通常指代当前对象Qsuper通常指代父类”q句话牢记在?j),那么本篇便达C(jin)目的Q其它的你自?x)在以后的编E实践当中慢慢体?x)、掌握。另外关于本中提到的承,请参阅相关Java教程?/p>
三、final
final在Java中ƈ不常用,然而它却ؓ(f)我们提供?jin)诸如在C语言中定义常量的功能Q不仅如此,finalq可以让你控制你的成员、方法或者是一个类是否可被覆写或承等功能Q这些特点final在Java中拥有了(jin)一个不可或~的CQ也是学?fn)Java时必要知道和掌握的关键字之一?/p>
final成员
当你在类中定义变量时Q在其前面加上final关键字,那便是说Q这个变量一旦被初始化便不可改变Q这里不可改变的意思对基本cd来说是其g可变Q而对于对象变量来说其引用不可再变。其初始化可以在两个地方Q一是其定义处,也就是说在final变量定义时直接给其赋|二是在构造函C。这两个地方只能选其一Q要么在定义时给|要么在构造函Cl|不能同时既在定义时给?jin)|又在构造函Cl另外的倹{下面这D代码演CZ(jin)q一点:(x)
import java.util.List;
import java.util.ArrayList;
import java.util.LinkedList;
public class Bat{
final PI=3.14; //在定义时便给址?br> final int i; //因ؓ(f)要在构造函Cq行初始化,所以此处便不可再给?br> final List list; //此变量也与上面的一?br> Bat(){
i=100;
list=new LinkedList();
}
Bat(int ii,List l){
i=ii;
list=l;
}
public static void main(String[] args){
Bat b=new Bat();
b.list.add(new Bat());
//b.i=25;
//b.list=new ArrayList();
System.out.println("I="+b.i+" List Type:"+b.list.getClass());
b=new Bat(23,new ArrayList());
b.list.add(new Bat());
System.out.println("I="+b.i+" List Type:"+b.list.getClass());
}
}
此程序很单的演示?jin)final的常规用法。在q里使用在构造函Cq行初始化的Ҏ(gu)Q这使你有了(jin)一点灵zL。如Bat的两个重载构造函数所C,W一个缺省构造函C(x)Z提供默认的|重蝲的那个构造函C(x)Ҏ(gu)你所提供的值或cd为final变量初始化。然而有时你q不需要这U灵zL,你只需要在定义时便l定其值ƈ怸变化Q这时就不要再用q种Ҏ(gu)。在mainҎ(gu)中有两行语句注释掉了(jin)Q如果你L注释Q程序便无法通过~译Q这便是_(d)不论是i的值或是list的类型,一旦初始化Q确实无法再更改。然而b可以通过重新初始化来指定i的值或list的类型,输出l果中显CZ(jin)q一点:(x)
I=100 List Type:class java.util.LinkedList
I=23 List Type:class java.util.ArrayList
q有一U用法是定义Ҏ(gu)中的参数为finalQ对于基本类型的变量Q这样做q没有什么实际意义,因ؓ(f)基本cd的变量在调用Ҏ(gu)时是传值的Q也是说你可以在方法中更改q个参数变量而不?x)?jing)响到调用语句Q然而对于对象变量,却显得很实用Q因为对象变量在传递时是传递其引用Q这样你在方法中对对象变量的修改也会(x)影响到调用语句中的对象变量,当你在方法中不需要改变(sh)为参数的对象变量Ӟ明确使用finalq行声明Q会(x)防止你无意的修改而媄(jing)响到调用Ҏ(gu)?br>另外Ҏ(gu)中的内部cd用到Ҏ(gu)中的参变量时Q此参变?sh)必d明ؓ(f)final才可使用Q如下代码所C:(x)
public class INClass{
void innerClass(final String str){
class IClass{
IClass(){
System.out.println(str);
}
}
IClass ic=new IClass();
}
public static void main(String[] args){
INClass inc=new INClass();
inc.innerClass("Hello");
}
}
finalҎ(gu)
方法声明ؓ(f)finalQ那p明你已经知道q个Ҏ(gu)提供的功能已l满你要求Q不需要进行扩展,q且也不允许M从此cȝ承的cL覆写q个Ҏ(gu)Q但是承仍然可以承这个方法,也就是说可以直接使用。另外有一U被UCؓ(f)inline的机Ӟ它会(x)使你在调用finalҎ(gu)Ӟ直接方法主体插入到调用处,而不是进行例行的Ҏ(gu)调用Q例如保存断点,压栈{,q样可能?x)你的E序效率有所提高Q然而当你的Ҏ(gu)M非常庞大Ӟ或你在多处调用此Ҏ(gu)Q那么你的调用主体代码便?x)迅速膨胀Q可能反而会(x)影响效率Q所以你要慎用finalq行Ҏ(gu)定义?/p>
finalc?/strong>
当你final用于cn上时Q你需要仔l考虑Q因Z个finalcL无法被Q何hl承的,那也意味着此类在一个承树(wi)中是一个叶子类Qƈ且此cȝ设计已被认ؓ(f)很完而不需要进行修Ҏ(gu)扩展。对于finalcM的成员,你可以定义其为finalQ也可以不是final。而对于方法,׃所属类为final的关p,自然也就成了(jin)final型的。你也可以明的lfinalcM的方法加上一个finalQ但q显然没有意义?/p>
下面的程序演CZ(jin)finalҎ(gu)和finalcȝ用法Q?/p>
final class final{
final String str="final Data";
public String str1="non final data";
final public void print(){
System.out.println("final method.");
}
public void what(){
System.out.println(str+"\n"+str1);
}
}
public class FinalDemo { //extends final 无法l承
public static void main(String[] args){
final f=new final();
f.what();
f.print();
}
}
从程序中可以看出QfinalcM普通类的用几乎没有差别,只是它失M(jin)被承的Ҏ(gu)。finalҎ(gu)与非finalҎ(gu)的区别也很难从程序行看出Q只是记住慎用?/p>
final在设计模式中的应?/strong>
在设计模式中有一U模式叫做不变模式,在Java中通过final关键字可以很Ҏ(gu)的实现这个模式,在讲解final成员时用到的E序Bat.java是一个不变模式的例子。如果你Ҏ(gu)感兴,可以参考阎宏博士编写的《Java与模式》一书中的讲解?/p>
到此为止Qthis,static,supert和final的用已l说完了(jin)Q如果你对这四个关键字已l能够大致说出它们的区别与用法,那便说明你基本已l掌握。然而,世界上的M东西都不是完无~的QJava提供q四个关键字Q给E序员的~程带来?jin)很大的便利Q但q不是说要让你到处用,一旦达到滥用的E序Q便适得其反Q所以在使用时请一定要认真考虑?/p>
声明为static的变量实质上是全局变量。当声明一个对象时Qƈ不生static变量的拷贝,而是该类所有的实例变量q同一个static变量。声明ؓ(f)static的方法有以下几条限制Q?
·
它们仅能调用其他的static Ҏ(gu)?
·
它们只能讉Kstatic数据?
·
它们不能以Q何方式引用this 或superQ关键字super 与承有养I在下一章中描述Q?
如果你需要通过计算来初始化你的static变量Q你可以声明一个static块,Static 块仅在该c被加蝲时执行一ơ。下面的例子昄的类有一个staticҎ(gu)Q一些static变量Q以?qing)一个static 初始化块Q?
// Demonstrate static variablesQmethodsQand blocks.
class UseStatic {
static int a = 3;
static int b;
static void meth(int x) {
System.out.println("x = " + x);
System.out.println("a = " + a);
System.out.println("b = " + b);
}
static {
System.out.println("Static block initialized.");
b = a * 4;
}
public static void main(String args[]) {
meth(42);
}
}
一旦UseStatic c被装蝲Q所有的static语句被运行。首先,a被设|ؓ(f)3Q接着static 块执?打印一条消?Q最后,b被初始化为a*4 ?2。然后调用main()Qmain() 调用meth() Q把?2传递给x?个println ( ) 语句引用两个static变量a和bQ以?qing)局部变量x ?
注意Q在一个static Ҏ(gu)中引用Q何实例变量都是非法的?
下面是该E序的输出:(x)
Static block initialized.
x = 42
a = 3
b = 12
在定义它们的cȝ外面Qstatic Ҏ(gu)和变量能独立于Q何对象而被使用。这P你只要在cȝ名字后面加点可符卛_。例如,如果你希望从cd面调用一个staticҎ(gu)Q你可以使用下面通用的格式:(x)
classname.method( )
q里Qclassname 是类的名字,在该cM定义staticҎ(gu)。可以看刎ͼq种格式与通过对象引用变量调用非staticҎ(gu)的格式类伹{一个static变量可以以同L(fng)格式来访问——类名加点号q算W。这是Java 如何实现全局功能和全局变量的一个控制版本?
下面是一个例子。在main() 中,staticҎ(gu)callme() 和static 变量b在它们的cM外被讉K?
class StaticDemo {
static int a = 42;
static int b = 99;
static void callme() {
System.out.println("a = " + a);
}
}
class StaticByName {
public static void main(String args[]) {
StaticDemo.callme();
System.out.println("b = " + StaticDemo.b);
}
}
下面是该E序的输出:(x)
a = 42
b = 99
static成员是不能被其所在class创徏的实例访问的?/p>
如果不加static修饰的成员是对象成员Q也是归每个对象所有的?
加static修饰的成员是cL员,是可以׃个类直接调用Qؓ(f)所有对象共有的
When coding location.href="fileName.html" what we are actually coding is document.location.href="fileName.html" or self.location.href="fileName.html", the self specifies the current window, or window.location.href="fileName.html".
When we need to target another window we need to navigate the window object hierarchy, either by specifying the parent frame, or the top frame (which may in fact be the same thing).
top.location.href="fileName.html" targets the top document.
top.frameName.location.href="fileName.html" targets the frame frameName within the top document.
parent.location.href="fileName.html" targets the parent of the current document.
parent.frameName.location.href="fileName.html" targets the child frame frameName of the parent of the current document, i.e. a sibling frame.
Feedback on 'Q18 Where does the target="" go when using location.href=""?'
string->byte
Byte static byte parseByte(String s)
byte->string
Byte static String toString(byte b)
char->string
Character static String to String (char c)
string->Short
Short static Short parseShort(String s)
Short->String
Short static String toString(Short s)
String->Integer
Integer static int parseInt(String s)
Integer->String
Integer static String tostring(int i)
String->Long
Long static long parseLong(String s)
Long->String
Long static String toString(Long i)
String->Float
Float static float parseFloat(String s)
Float->String
Float static String toString(float f)
String->Double
Double static double parseDouble(String s)
Double->String
Double static String toString(Double d)
q是一个例子,说的是JAVA中数据数型的转换。供大家学习(fn)参?nbsp;
package cn.com.lwkj.erts.register;
import java.sql.Date;
public class TypeChange {
public TypeChange() {
}
//change the string type to the int type
public static int stringToInt(String intstr)
{
Integer integer;
integer = Integer.valueOf(intstr);
return integer.intValue();
}
//change int type to the string type
public static String intToString(int value)
{
Integer integer = new Integer(value);
return integer.toString();
}
//change the string type to the float type
public static float stringToFloat(String floatstr)
{
Float floatee;
floatee = Float.valueOf(floatstr);
return floatee.floatValue();
}
//change the float type to the string type
public static String floatToString(float value)
{
Float floatee = new Float(value);
return floatee.toString();
}
//change the string type to the sqlDate type
public static java.sql.Date stringToDate(String dateStr)
{
return java.sql.Date.valueOf(dateStr);
}
//change the sqlDate type to the string type
public static String dateToString(java.sql.Date datee)
{
return datee.toString();
}
public static void main(String[] args)
{
java.sql.Date day ;
day = TypeChange.stringToDate("2003-11-3");
String strday = TypeChange.dateToString(day);
System.out.println(strday);
}
}
三、安装Eclipse
首先下蝲eclipse-SDK-3.1.2-win32.zipQeclipse-SDK-3.1.2-win32.zip下蝲地址为:(x)
http://www.eclipse.org/downloads/Q;
然后eclipse-SDK-3.1.2-win32.zip直接解压到D盘根目录Q?br>
到这里, Eclipse安装完毕?br>
四、安装MyEclipse
首先下蝲EnterpriseWorkbenchInstaller_4.1.1GA_E3.1.exeQEnterpriseWorkbenchInstaller_4.1.1GA_E3.1.exe 的下载地址为:(x)
http://www.myeclipseide.com/ContentExpress-display-ceid-10.htmlQ;
然后安装EnterpriseWorkbenchInstaller_4.1.1GA_E3.1.exe。注意:(x)当安装到下图所C的步骤的时候要选择Eclipse的安装\径(如图Q,其他选项保持默认?br>
安装完毕之后Q将MyEclipse安装目录下的features和pluginsq?个目录覆盖到Eclipse的安装目录下?br>
最后将刚才安装?MyEclipse 卸蝲?br>
解释一下上面这样做的原因:(x) 因ؓ(f)MyEclipse是Eclipse的插Ӟ所以只要把features和pluginsq?个目录覆盖到Eclipse的安装目录,Eclipse׃(x)自动认出q些插g?
到这里,MyEclipse安装完毕?br>
五、破解MyEclipse
q行MyEclipse4.1.1注册机MyEclipseKeyGen.exeQ选择MyEclipse的版本号Q输入注册名Q生成序列号。(MyEclipse4.x注册机的下蝲地址为:(x)
http://esoft.g8.com.cn/UploadFiles/2006-5/520753587.rarQ?br>
q行eclipse.exeQ首ơ运行要求指定WorkspaceQ,依次点击Window ----> Preferences ---->MyEclipse---->Subscription ----> Enter SubscriptionQ输入注册名以及(qing)注册机生成的注册码?br>
到这里,MyEclipse破解完毕?/p>
六、指定Eclipse+MyEclipse的JRE 和Tomcat 服务?/strong>
1.讑֮Eclipse+MyEclipse的JRE
一般情况下QEclipse可以自动扑ֈJREQ我们不用进行过多的讄?br>
2.讑֮Eclipse+MyEclipse的Tomcat 服务?br>
只需讄图中所标注的两处即可,图中其余部分是自动生成的?br>
到这里,我们的Eclipse+MyEclipse开发环境就搭徏完毕?jin)?br>
七、新Z个项目来试一下Eclipse+MyEclipse开发环境是否搭建成?br>
1.在Eclipse中依ơ点?#8220; File ----> New ----> Project” , 在弹出的“New Project”对话框中依次点击“Web Project ---->MyEclipse---->J2EE Projects---->Web Project”Q?再点“Next”Q在“Project Name”中输入项目的名字“test”,最后点“Finish”?br>
2.在Eclipse左边Package Explorer列表中点?#8220;test”Q将目test展开。右键点?WebRoot ----> New ----> JSP , 新徏一个名为hello.jsp?JSP 面 ?代码如下图(图中标注部分需要我们手动添加,其余部分是系l自动生成的Q:(x)
3. 再用同样的方法, 新徏一个叫 hello_result.jsp 的JSP文gQ?代码如下图:(x)
4. deployQ部|Ԍ(j)目?
点击 deploy 按钮Q用U线M(jin)的按钮就?deploy 按钮Q, 在弹出的H口中点击AddQ?部vtest目Q如图所C)(j)?br>
5. 启动Tomcat服务器?br>
如下图所C(用红U画?jin)的按钮?启动Tomcat 的按钮)(j)Q?br>
Tomcat 启动输出信息如下图:(x)
6.目test的运行结果:(x)
我们可以去Eclipse的Workspace目录下看看test目的代码,也可以去Tomcat的webapps目录下,看看部v之后?test目的结构?/p>
一?/font>
Java中将字符串作?/span>Stringcd对象来处理。当创徏一?/span>String对象Ӟ被创建的字符串是不能被改变的。每ơ需要改变字W串旉要创Z个新?/span>String对象来保存新的内宏V原始的字符串不变。之所以采用这U方法是因ؓ(f)实现固定的,不可变的字符串比实现可变的字W串更高效。对于那些想得到改变的字W串的情况,有一个叫?/span>StringBuffer?/span>Stringcȝ友类Q它的对象包含了(jin)在创Z后可以改变的字符丌Ӏ?/span>
StringcdStringBufferc都?/span>java.lang中定义。因此它们可以自动的被所有程序用。两者均被说明ؓ(f)finalQ这意味着两者均不含子类?/span>
二?/span>String构造函?/span>
Q?/span>1Q?/span>String()Q?/span> 默认构造函敎ͼ无参?/span>
String s1 = new String();
Q?/span>2Q?/span>String( char chars[]) Q传入字W数l?/span>
char[] myChars={'a', 'b', 'c'};
String s2 = new String(myChars) // 使用字符?#8220;abc”初始?/span>s2
Q?/span>3Q?/span>String( char chars[], int startIndex, int numChars) Q传入一个字W数l,从指定下标位|开始获取指定个数的字符Q用q些字符来初始化字符串变量?/span>
char[] myChars={'h', 'e', 'l', 'l', 'o'};
String s3 = new String(myChars,1,3); //使用字符?#8220;ell”初始?/span>s3
Q?/span>4Q?/span>String(String strObj)Q传入另一个字W串对象Q用该字W串对象的内容初始化
String s4= new String(s3); // q是s4也是“ell”?jin)?/span>
Q?/span>5Q?/span>String(byte asciiChars[])
String(byte asciiChars[], int startIndex, int numChars)
管Java?/span>charcd使用16位(bitQ表C?/span>Unicode~码字符集,?/span>Internet中,
字符串的典型格式使用?/span>ASCII字符集构成的8位数l,因ؓ(f)8?/span>ASCII字符串是共同的,当给定一个字节(byteQ数l时Q?/span>StringcL供了(jin)上面两个初始化字W串的构造函数?/span>
例子Q?/font>
package Examples;
class SubStringConv{
public static void main(String[] args){
byte ascii[]={65,66,67,68,69,70};
String s1=new String(ascii);
System.out.println(s1);
String s2=new String(ascii,2,3);
System.out.println(s2);
}
}
~译和运行后输出Q?/font>
ABCDEF
CDE
三?/font>
Q?/span>1Q调用字W串?/span>length()Ҏ(gu)可以得到该字W串的长度(字符个数Q;
Q?/span>2Q前面说明了(jin)如何使用newq算W创Z个字W串实例。然而这是一U早期的使用字符串常量的处理Ҏ(gu)。对于程序中的每一个字W串帔RQ?/span>Java?x)自动创?/span>String对象。因此,可以使用字符串常量初始化String对象。例如:(x)
String s5="abc";
int i = "abc".length(); //可以字W串作ؓ(f)对象来进行操?/span>
Q?/span>3Q可以?#8220;+”q算W来两个字W串q接h产生一个新?/span>String对象。只?/span>+q算W有一个运数是字W串Q?/span>StringQ实例时Q编译器将另一个运数转换为它的字W串形式。这U操作是通过调用一个由Stringcd义的 字符串{换方?/span>valueOf()来完成的。对于简单类型,valueOf()Ҏ(gu)q回一个字W串Q该字符串包含了(jin)该类型的值的字符丌Ӏ对于对象,valueOf()Ҏ(gu)调用toString()Ҏ(gu)。每一个类都执?/span>toString()Ҏ(gu)Q因为它是由Object定义的?/span>toString()Ҏ(gu)h如下一般Ş式:(x) String toString() ?/span> toString()Ҏ(gu)q回一?/span>String对象Q即字符Ԍ(j)。该对象一般是对类的一个描q?/span>
四、一些字W串操作
Q?/span>1Q字W截?/span>
*char charAt(int where) Q注意,q里q回一?/span>char字符例如Q?/span>
char a ;
a="abcde".charAt(2); //烦(ch)引ؓ(f)2 Q即W三个字W赋l?/span>a
* void getChars(int sourceStart, int sourceEnd, char target[], int targetStart) Q这里是无返回值方法,指定要截取的子字W串的开始和l束下标Q再指定要储存子字符串内字符的数l,和存放这些字W的起始位置。注意,子字W串q不包括位于l束下标的字W?/span>
* byte[] getBytes() q是getBytes()Ҏ(gu)最单的形式Q它实现字W存放于字节数组中。在字W串Q?/span>StringQD出到一个不支持16?/span>Unicode~码的环境时Q?/span>getBytes
()是最有用的。例如,大多?/span>Internet协议和文本文件格式在文本交换时?/span>8?/span>ASCII~码?/span>
* char[] toCharArray() 字W串中所有的字符转换C个字W数l的最当方法,也可以?/span>getChars()Ҏ(gu)实现?/span>
Q?/span>2Q字W串比较
* boolean equals(Object str) 比较两个字符串对象是否相{?/span>,
boolean equalsIgnoreCaseJ(String str) 比较两个字符串对象,且忽略字W的大小?/span>
* regionMatches() Ҏ(gu)允许一个字W串中指定的区间和另一字符串中指定的区间进行比较,它的重蝲形式允许在比较时忽略大小写。下面给?gu)两种?gu)的一般Ş式:(x)
boolean regionMatches(int startIndex,String str2,int str2StartIndex,int numChars)
boolean regionMatches(boolean ignoreCase ,int startIndex,String str2,int str2StartIndex,int numChars)
其中startIndex指定调用此方法的字符串内子字W串的v始位|?/span>
* boolean startsWith(String str) startsWithҎ(gu)q有W二UŞ式:(x)
boolean startWith(String str, int startIndex)
boolean endsWith(String str)
上面的方法用来判断一个给定的字符串是否是从指定的字符串开始或l束?/span>
* int compareTo(String str) Ҏ(gu)用于比较两个字符串的大小。字W串比较的结果及(qing)其含义:(x)
?/font> |
含义 |
于0 |
调用此方法的字符串小于参?/span>str |
大于0 |
调用此方法的字符串大于参?/span>str |
{于0 |
两个字符串相{?/font> |
Q?/span>3Q其他操?/span>
* 搜烦(ch)字符Ԍ(x)
int indexOf( int ch)
int lastIndexOf( int ch)
int indexOf(String str)
int lastIndexOf(String str)
指定搜烦(ch)的v始点Q?/font>
int indexOf( int ch, int startIndex)
int lastIndexOf( int ch ,int startIndex)
int indexOf(String str ,int startIndex)
int lastIndexOf(String str, int startIndex)
* 使用 substring()截取子字W串Q?/span>
String substring(int startIndex) 注意substring?/span>string没有大写Q截取指定位|后的子字符丌Ӏ?/span>
String substring(int startIndex,int endIndex) 截取指定起始位置和结束位|的子字W串。注意截取的字字W串不包括结束位|的字符?/span>
* concat() q接q个字符Ԍ?/span>+ q算W执行相同功能?/span>
String concat(String str)
* replace() 用另一个字W取代指定字W串中指定字W:(x)
String replace(char original, char replacement) 例如Q?/span>
String s=”Hello”.replace(‘l’,’w’); //执行?/span> s =”Hewwo”;
* trim() q回一个字W串Q该字符串是删除调用字符串前后的I白W所得的字符?/span>
* 改变字符串内字符的大写
String toLowerCase() q回一个所有字母都是小写的字符?/span>
String toUpperCase()q回一个所有字母都是大写的字符?/span>
* 使用 valueOf()Ҏ(gu)实现数据转换
例如Q?/span>
String str = String.valueOf(3) ; //?/span>intcd转换成字W串cdQ其他基本数据类型和Mcȝ对象也可作ؓ(f)参数?/span>
W二节?/span>StringBuffer
StringBuffer定义?jin)下面三个构造函敎ͼ(x)
StringBuffer() // 默认构造函敎ͼ预留?/span>16个字W的I间Q该I间不需再分?/span>
StringBuffer(int size) // 讄指定~冲区大?/span>
StringBuffer(String str) // 讄StringBuffer对象初始化的内容q?/span>16个字W空_(d)且不需再分配空?/span>
* int length()
调用length()Ҏ(gu)可以得到StringBuffer对象的长度,调用capacity()可以得到ȝ分配定w。两个方法都是返回一?/span>intcd的倹{?/span>
* void ensureCapacity(int capacity)
如果惛_构?/span>StringBuffer对象后ؓ(f)某些字符预分配空_(d)可以使用ensureCapacity()Ҏ(gu)Q设|缓冲区的大,q在事先已知要在StringBuffer上追加大量小字符串的情况下是有用的?/span>ensureCapcity()Ҏ(gu)h如下的一般Ş式:(x) void ensureCapacity(int capacity)
* void setLength(int len)
使用setLength()Ҏ(gu)可以讄StringBuffer对象的长度,它的一般Ş式如下:(x)
void setLength(int len) 如果len大于StringBuffer对象当前?/span>length()值的话,那么?x)?/span>StringBuffer对象后面加上I字W;如果?/span>length()的话,?/span>len后面的字W串?x)丢失?/span>
* char charAt(int where)
void setCharAt(int where, char ch)
使用charAt()Ҏ(gu)可以得到StringBuffer对象中指定位|上的字W,setCharAt() 可以讄指定位置上的字符。它们的一般Ş式如下:(x)
char charAt(int where)
void setCharAt(int where,char ch)
对于q两U法法,where值必L非负的,同时不能过或等?/span>StringBuffer对象的长度?/span>
* getChars(int suorceStart,int sourceEnd,char target[] , int targetStart)
* append()
Append()Ҏ(gu)Q一其他cd数据的字W串形式q接到调?/span>StringBuffer对象的后面,Ҏ(gu)有内|的cd?/span>ObjectQ它都有重蝲形式。下面是几种形式Q?/span>
StringBuffer append(String str)
StringBuffer append(int num)
StringBuffer append(Object obj)
* insert()
Insert()Ҏ(gu)一个字W串插入另一个字W串中。下面是它的几种形式Q?/span>
StringBuffer insert(int index,String str)
StringBuffer insert(int index,char ch)
StringBuffer insert(int index,Object obj)
*reverse() // StringBuffer reverse()
StringBuffer strbf=new StringBuffer(“ABCDEFG”);
strbf.reverse();
System.out.println(strbf); //输出 GFEDCBA
* StringBuffer delete(int startIndex,int endIndex)
StringBuffer deleteCharAt(int loc)
删除指定位置的字W串和指定位|的字符。例如删除第一个字W后的所有字W:(x)
strbf.delete(1,strbf.length());
* replace()
它完成在StringBuffer内部用一个字W串代替另一个指定v始位|和l束位置的字W串的功能,注意的是Q被代替的字W不包括l束位置上的字符Q它的一般Ş式是Q:(x)
StringBuffer replace(int startIndex, int endIndex,String str)
* substring() q回StringBuffer的一部分?/span>
String substring(int startIndex)
String substring(int startIndex, int endIndex)
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=610794
1 |
// 取得檔案 File file = new File("./logo_phpbb.jpg"); int length = (int) file.length(); InputStream fin = new FileInputStream(file); // 填入資料?/font> PreparedStatement pstmt = conn.prepareStatement( "INSERT INTO files VALUES(?, ?)"); pstmt.setString(1, "c_國Logo"); pstmt.setBinaryStream (2, fin, length); pstmt.executeUpdate(); pstmt.clearParameters(); pstmt.close(); fin.close(); |
1 |
Blob blob = result.getBlob(2); // 取得BLOB Clob clob = result.getClob(2) // 取得CLOB |
1 |
import java.io.*; import java.sql.*; public class DBTest { public static void main(String[] args) { String driver = "com.mysql.jdbc.Driver"; String url = "jdbc:mysql://localhost:3306/upload?useUnicode=true&characterEncoding=Big5"; String user = "caterpillar"; String password = "123456"; try { Class.forName(driver); Connection conn = DriverManager.getConnection(url, user, password); // 取得檔案 File file = new File("./logo_phpbb.jpg"); int length = (int) file.length(); InputStream fin = new FileInputStream(file); // 填入資料?/font> PreparedStatement pstmt = conn.prepareStatement( "INSERT INTO files VALUES(?, ?)"); pstmt.setString(1, "c_國Logo"); pstmt.setBinaryStream (2, fin, length); pstmt.executeUpdate(); pstmt.clearParameters(); pstmt.close(); fin.close(); // 從資料n取出檔案 Statement stmt = conn.createStatement(); ResultSet result = stmt.executeQuery("SELECT * FROM files"); result.next(); String description = result.getString(1); Blob blob = result.getBlob(2); // 寫入檔案 System.out.println("檔案描述Q? + description); FileOutputStream fout = new FileOutputStream("./logo_phpbb_2.jpg"); fout.write(blob.getBytes(1, (int)blob.length())); fout.flush(); fout.close(); stmt.close(); conn.close(); } catch(ClassNotFoundException e) { System.out.println("找不到驅動程?); e.printStackTrace(); } catch(SQLException e) { e.printStackTrace(); } catch(IOException e) { e.printStackTrace(); } } } |
如果你运行该E序Q可能会(x)看到q样的序列。但是在q行一ơ,可能看到的就不是q个序列?jin)。我们在四台机器上运行它Q会(x)看到四个不同的序列,包括前面描述的那个序列。这个程序甚至都不能保证?x)正常终止,比打印其他Q何特定字W串都要~Zq种保证。它的行为完全是不确定的?
q里的罪祸首就是String(byte[])构造器。有兛_的规范描q道Q?#8220;在通过解码使用q_~省字符集的指定byte数组来构造一个新的StringӞ该新String的长度是字符集的一个函敎ͼ因此Q它可能不等于byte数组的长度。当l定的所有字节在~省字符集中q全部有效Ӟq个构造器的行为是不确定的”[ Java -API]?
到底什么是字符集?从技术角度上Ԍ它是“被编码的字符集合和字W编码模式的l合?#8221;[Java-API]。换句话_(d)字符集是一个包Q包含了(jin)字符、表C字W的数字~码以及(qing)在字W编码序列和字节序列之间来回转换的方式。{换模式在字符集之间存在着很大的区别:(x)某些是在字符和字节之间做一对一的映,但是大多数都不是q样。ISO-8859-1是唯一能够让该E序按顺序打C0?55的整数的~省字符集,它更为大家所熟知的名字是Latin-1[ISO-8859-1]?
J2SEq行期环境(JREQ的~省字符集依赖于底层的操作系l和语言。如果你想知道你的JRE的缺省字W集Qƈ且你使用的是5.0或更新的版本Q那么你可以通过调用java.nio.charset.Charset.defaultCharset()来了(jin)解。如果你使用的是较早的版本,那么你可以通过阅读pȝ属?#8220;file.encoding”来了(jin)解?
q运的是Q你没有被强制要求必d容忍各种E奇古怪的~省字符集。当你在char序列和byte序列之间做{换时Q你可以且通常是应该显式地指定字符集。除?jin)接受byte数字之外Q还可以接受一个字W集名称的String构造器是专ؓ(f)此目的而设计的。如果你用下面的构造器L换在最初的E序中的String构造器Q那么不缺省的字符集是什么,该程序都保证能够按照序打印??55的整敎ͼ(x)
String str = new String(bytes, "ISO-8859-1");q个构造器声明?x)抛出UnsupportedEncodingException异常Q因此你必须捕获它,或者更适宜的方式是声明mainҎ(gu)抛出它Q要不然E序不能通过~译。尽如此,该程序实际上不会(x)抛出异常。Charset的规范要求Javaq_的每一U实现都要支持某些种cȝ字符集,ISO-8859-1׃列其中?
q个谜题的教训是Q每当你要将一个byte序列转换成一个StringӞ你都在用某一个字W集Q不你是否昑ּ地指定了(jin)它。如果你惌你的E序的行为是可预知的Q那么就请你在每ơ用字W集旉明确地指定。对API的设计者来_(d)提供q么一个依赖于~省字符集的String(byte[])构造器可能q是一个好L?/p>