Java7中NIO.2的使用——文件递归操作

王朝学院·作者佚名  2016-08-27
窄屏简体版  字體: 小  |  中  |  大  |  超大  

众所周知,递归编程是一项有争议的技术,因为它需要大量的内存,但是它能简化一些编程任务。基本上,一个递归操作都是程序调用自己传递参数修改的值或者参数传递到当前的程序循环中。递归编程通常用来计算阶乘斐波那契数列,回文,谢尔宾斯基地毯等问题。下面的代码演示了用递归实现的阶乘。

/*** Calculate the factorial of n (n! = 1 * 2 * 3 * … * n).

*

*@paramn the number to calculate the factorial of.

*@returnn! - the factorial of n.*/staticintfact(intn) {//Base Case://If n <= 1 then n! = 1.if(n <= 1) {return1;

}//Recursive Case://If n > 1 then n! = n * (n-1)!else{returnn * fact(n-1);

}

}

许多文件的操作需要访问文件树结构下的文件,只用递归操作再合适不过。NIO.2 在接口中封装了遍历文件树的过程。这个接口叫FileVisitor,在java.nio.file包中。

这一节我们从FileVisitor学起,一旦你熟悉了FileVisitor,你就能开发一系列执行操作包括文件树的游历,文件的查找,删除,拷贝和移动。

-----------------------------------------------------------------------------------------------------------------------

FileVisitor接口

如前面提到的,FileVisitor接口提供了对文件树递归遍历的支持。接口中的方法可以在访问文件的时候,目录访问之前,目录访问之后,发生失败后采取控制,一旦你获得控制,你就能决定如何访问文件,通过FileVisitResult枚举决定当访问下一个访问结果时如何处理。这个枚举有四个枚举常量:

FileVisitResult.CONTINUE: 这个访问结果表明,遍历过程应该继续。根据FileVisitor的方法返回类型可以翻译成不同的行为。FileVisitResult.SKIP_SIBLINGS: 这个访问结果表明,遍历过程应该继续没有访问这个文件或目录的兄弟姐妹节点。FileVisitResult.SKIP_SUBTREE: 这次访问结果表明,遍历过程应该继续除了这个目录中剩下其他的条目。FileVisitResult.TERMINATE: 这次访问结果表明,遍历过程应该终止。这些枚举的常亮可以用下面的代码进行遍历。

for(FileVisitResult constant : FileVisitResult.values())

System.out.PRintln(constant);

下面的章节来讨论实现FileVisitor接口的方法如何控制遍历过程。

FileVisitor.visitFile()方法

这个方法用在一个在目录中的文件时被调用。通常,这个方法返回CONTINUE 或TERMINATE。 例如:当寻找一个文件时,方法应该返回CONTINUE知道文件找到,和文件找到后返回TERMINATE。

当方法调用后,它接收一个file的引用一节文件的一些基本属性。如果发生IO异常,它会抛出IOException异常。次方法的签名如下:

FileVisitResult visitFile(T file, BasicFileAttributes attrs)throwsIOException

FileVisitor.preVisitDirectory()方法

此方法在开始访问以为目录的条目开始之前被调用。如果方法返回CONTINUE则 目录中的条目将被访问。如果方法返回SKIP_SUBTREE则目录里的条目不被访问。当然你也可以访问文件或是目录的兄弟节点如果方法返回SKIP_SIBLINGS。方法签名为:

FileVisitResult preVisitDirectory(T dir, BasicFileAttributes attrs)throwsIOException

FileVisitor.postVisitDirectory()方法

当整个目录里的所有条目访问以后或访问突然结束时此方法被调用。当这个方法被调用后,它会持有目录和IOException的引用——如果没有异常发生则会返回null,或发生一个异常返回对应的错误。下面是此方法的签名:

FileVisitResult postVisitDirectory(T dir, IOException exc)throwsIOException

FileVisitor.visitFileFailed()方法

因为各种不同的原因导致文件不能访问时此方法被调用,例如文件的属性不允许读取或目录不允许打开。方法签名如下:

FileVisitResult visitFileFailed(T file, IOException exc)throwsIOException

----------------------------------------------------------------------------------------------------------------

SimpleFileVisitor类

实现FileVisitor接口必须要求实现所有的方法,如果你只需要实现其中一个或几个方法,就显得有些不合需要的。在这种情况下,继承SimpleFileVisitor类就显得简单很多,它实现了FileVisitor接口。

例如,你想遍历所有的目录并列出所有的名字,你可以很容易地使用postVisitDirectory()和visitFileFailed() 方法。

classListTreeextendsSimpleFileVisitor<Path>{

@OverridepublicFileVisitResult postVisitDirectory(Path dir, IOException exc) {

System.out.println("Visited directory: " +dir.toString());returnFileVisitResult.CONTINUE;

}

@OverridepublicFileVisitResult visitFileFailed(Path file, IOException exc) {

System.out.println(exc);returnFileVisitResult.CONTINUE;

}

}

开始递归过程

一旦你创建了递归机制,就可以开始这个过程通过调用Files.walkFileTree()方法。最简单的Files.walkFileTree()的方法传递一个开始文件(通常是根),还有一个 文件访问者对象去调用每个文件。例如,下面的例子。

Path listDir = Paths.get("C:/rafaelnadal");//define the starting file treeListTree walk =newListTree();//instantiate the walktry{

Files.walkFileTree(listDir, walk);//start the walk}catch(IOException e){

System.err.println(e);

}

第二个重载的walkFileTree()方法第一个参数是开始的文件,然后是自定义的遍历的选项,目录层级的最大访问数,还有 walk 实例。

Path listDir = Paths.get("C:/rafaelnadal");//define the starting fileListTree walk =newListTree();//instantiate the walkEnumSet opts = EnumSet.of(FileVisitOption.FOLLOW_LINKS);//follow linkstry{

Files.walkFileTree(listDir, opts, Integer.MAX_VALUE, walk);//start the walk}catch(IOException e){

System.err.println(e);

}

-----------------------------------------------------------------------------------------------------------------------------------

写一个文件搜索程序

大多数操作系统会提供专用的工具用来搜索文件(例如,在linux下可以使用find命令,同时windows也提供了文件搜索工具),从最简单的搜索,到高级搜索,所有的工具都是用同一种方式工作:你指定搜索条件然后等待工具返回匹配的文件。但是,如果你要使用编程方式完成这个功能,FileVisitor接口能帮助你实现遍历查找。无论你是通过名字,扩展名来查找文件还是通过正则表达式在文件内部搜索文本或符号,这些方法都是访问每个文件和执行一些检查来确定这个文件是否满足你的搜索条件。

如果你基于FileVisitor来实现你的文件搜索工具,你需要注意下面几点:

visitFile()方法用在执行当前文件和你要搜索的文件比较的最合适的方法。在这一点上,你可以提取每个文件的名字,扩展名或者它的属性或打开文件用来读取。你可以使用文件名字,扩展名或是其他的方式来决定哪个文件是你要搜索的那个。有时你需要把这些信息混合到复杂的查询中。这个方法不能用来查找目录。如果你要查找目录,根据不同的情况,可以使用preVisitDirectory()或postVisitDirectory() 方法来实现比较。如果文件不能访问,则 visitFileFailed() 方法会返回 FileVisitResult.CONTINUE,因为这个问题不会决定整个搜索过程终止。如果你通过名字检索一个文件并且你知道在整个文件树中有一个对应名字的文件,这时你可以返回FileVisitResult.TERMINATE一旦你使用visistFile()找到了他。否则,将会返回FileVisitResult.CONTINUE。检索流程可以跟踪符号链接。在子目录树找到符号链接的目标文件之前就能跟踪符号链接就能检索到,这样看来是一个很好的主意。但不总是个好主意,例如,在删除文件的时候则不可用。通过名字检索文件

下面的程序通过名字对文件进行检索rafa_1.jpg在默认目录下,当找到后终止检索。

importjava.io.IOException;importjava.nio.file.FileSystems;importjava.nio.file.FileVisitOption;importjava.nio.file.FileVisitResult;importjava.nio.file.FileVisitor;importjava.nio.file.Files;importjava.nio.file.Path;importjava.nio.file.Paths;importjava.nio.file.attribute.BasicFileAttributes;importjava.util.EnumSet;classSearchimplementsFileVisitor {privatefinalPath searchedFile;publicbooleanfound;publicSearch(Path searchedFile) {this.searchedFile =searchedFile;this.found =false;

}voidsearch(Path file)throwsIOException {

Path name=file.getFileName();if(name !=null&&name.equals(searchedFile)) {

System.out.println("Searched file was found: " + searchedFile +

" in " +file.toRealPath().toString());

found=true;

}

}

@OverridepublicFileVisitResult postVisitDirectory(Object dir, IOException exc)throwsIOException {

System.out.println("Visited: " +(Path) dir);returnFileVisitResult.CONTINUE;

}

@OverridepublicFileVisitResult preVisitDirectory(Object dir, BasicFileAttributes attrs)throwsIOException {returnFileVisitResult.CONTINUE;

}

@OverridepublicFileVisitResult visitFile(Object file, BasicFileAttributes attrs)throwsIOException {

search((Path) file);if(!found) {returnFileVisitResult.CONTINUE;

}else{returnFileVisitResult.TERMINATE;

}

}

@OverridepublicFileVisitResult visitFileFailed(Object file, IOException exc)throwsIOException {//report an error if necessaryreturnFileVisitResult.CONTINUE;

}

}classMain {publicstaticvoidmain(String[] args)throwsIOException {

Path searchFile= Paths.get("rafa_1.jpg");

Search walk=newSearch(searchFile);

EnumSet opts=EnumSet.of(FileVisitOption.FOLLOW_LINKS);

Iterable<Path> dirs =FileSystems.getDefault().getRootDirectories();for(Path root : dirs) {if(!walk.found) {

Files.walkFileTree(root, opts, Integer.MAX_VALUE, walk);

}

}if(!walk.found) {

System.out.println("The file " + searchFile + " was not found!");

}

}

}

使用模式匹配查找文件

有时候你可能只知道要检索文件的部分信息,例如只知道名字或是扩展名,基于这些信息的片段,你可以正则表达式。这个检索将会根据匹配的表达式检索到满足条件的文件位置,或许你要查找的文件正在其中。

下面的代码用来在C:\rafaelnadal目录下查找所有以jpg为扩展名的文件。这个文件会遍历整个目录。

importjava.io.IOException;importjava.nio.file.FileSystems;importjava.nio.file.FileVisitOption;importjava.nio.file.FileVisitResult;importjava.nio.file.FileVisitor;importjava.nio.file.Files;importjava.nio.file.Path;importjava.nio.file.PathMatcher;importjava.nio.file.Paths;importjava.nio.file.attribute.BasicFileAttributes;importjava.util.EnumSet;classSearchimplementsFileVisitor {privatefinalPathMatcher matcher;publicSearch(String glob) {

matcher= FileSystems.getDefault().getPathMatcher("glob:" +glob);

}voidsearch(Path file)throwsIOException {

Path name=file.getFileName();if(name !=null&&matcher.matches(name)) {

System.out.println("Searched file was found: " + name +

" in " +file.toRealPath().toString());

}

}

@OverridepublicFileVisitResult postVisitDirectory(Object dir, IOException exc)throwsIOException {

System.out.println("Visited: " +(Path) dir);returnFileVisitResult.CONTINUE;

}

@OverridepublicFileVisitResult preVisitDirectory(Object dir, BasicFileAttributes attrs)throwsIOException {returnFileVisitResult.CONTINUE;

}

@OverridepublicFileVisitResult visitFile(Object file, BasicFileAttributes attrs)throwsIOException {

search((Path) file);returnFileVisitResult.CONTINUE;

}

@OverridepublicFileVisitResult visitFileFailed(Object file, IOException exc)throwsIOException {//report an error if necessaryreturnFileVisitResult.CONTINUE;

}

}classMain {publicstaticvoidmain(String[] args)throwsIOException {

String glob= "*.jpg";

Path fileTree= Paths.get("C:/rafaelnadal/");

Search walk=newSearch(glob);

EnumSet opts=EnumSet.of(FileVisitOption.FOLLOW_LINKS);

Files.walkFileTree(fileTree, opts, Integer.MAX_VALUE, walk);

}

}

如果你还知道要查找的文件其他信息,你可以创建一个复杂的检索。例如,除了知道文件的名字和类型,你还知道文件大概小于多少KB,或许是文件的创建日期,修改日期,是否是隐藏文件或只读,谁拥有它。下面的代码演示查找所有扩展名为jpg并且文件小于100KB的文件。

importjava.io.IOException;importjava.nio.file.FileSystems;importjava.nio.file.FileVisitOption;importjava.nio.file.FileVisitResult;importjava.nio.file.FileVisitor;importjava.nio.file.Files;importjava.nio.file.Path;importjava.nio.file.PathMatcher;importjava.nio.file.Paths;importjava.nio.file.attribute.BasicFileAttributes;importjava.util.EnumSet;classSearchimplementsFileVisitor {privatefinalPathMatcher matcher;privatefinallongaccepted_size;publicSearch(String glob,longaccepted_size) {

matcher= FileSystems.getDefault().getPathMatcher("glob:" +glob);this.accepted_size =accepted_size;

}voidsearch(Path file)throwsIOException {

Path name=file.getFileName();longsize = (Long) Files.getAttribute(file, "basic:size");if(name !=null&& matcher.matches(name) && size <=accepted_size) {

System.out.println("Searched file was found: " + name + " in " +file.toRealPath().toString()+ " size (bytes):" +size);

}

}

@OverridepublicFileVisitResult postVisitDirectory(Object dir, IOException exc)throwsIOException {

System.out.println("Visited: " +(Path) dir);returnFileVisitResult.CONTINUE;

}

@OverridepublicFileVisitResult preVisitDirectory(Object dir, BasicFileAttributes attrs)throwsIOException {returnFileVisitResult.CONTINUE;

}

@OverridepublicFileVisitResult visitFile(Object file, BasicFileAttributes attrs)throwsIOException {

search((Path) file);returnFileVisitResult.CONTINUE;

}

@OverridepublicFileVisitResult visitFileFailed(Object file, IOException exc)throwsIOException {//report an error if necessaryreturnFileVisitResult.CONTINUE;

}

}classMain {publicstaticvoidmain(String[] args)throwsIOException {

String glob= "*.jpg";longsize = 102400;//100 kilobytes in bytesPath fileTree = Paths.get("C:/rafaelnadal/");

Search walk=newSearch(glob, size);

EnumSet opts=EnumSet.of(FileVisitOption.FOLLOW_LINKS);

Files.walkFileTree(fileTree, opts, Integer.MAX_VALUE, walk);

}

}

根据文件里的内容查找文件

其中一种比较高级的搜索文件的方式是个根据文件中的内容。你可以传递一个字符序列或是一段句子,然后返回这包含这些内容的文件。这种方式也也是最耗时的,因为他要进入每个文件里面,这就意味着要先打开文件,读取,最后关闭它。此外,这里有很多文件格式来支持文本,例如,pdf,MicrosoftWord,Excel,Powerpoint,简单文本,xml, HTML, XHTML等等。每一种格式的读取方式不尽相同。

接下来我们会开发一个程序用你来根据传递的字符串内容来搜索文件,这个传递的字符串里的序列以逗号分隔, 例如:Rafael Nadal,tennis,winner of Roland Garros,BNP Paribas tournament draws。 使用StringTokenizer类,以逗号为分隔符,下面的例子就是提取每个单词或句子放入ArrayList中。

…

String words="Rafael Nadal,tennis,winner of Roland Garros,BNP Paribas tournament draws";

ArrayList<String> wordsarray =newArrayList<>();

…

StringTokenizer st=newStringTokenizer(words, ",");while(st.hasMoreTokens()) {

wordsarray.add(st.nextToken());

}

下面的代码循环ArrayList然后比较从访问的文件中提取的比较每个单词和句子。searchText()方法以提取的文本作为参数。

//search textprivatebooleansearchText(String text) {booleanflag =false;for(intj = 0; j < wordsarray.size(); j++) {if((text.toLowerCase()).contains(wordsarray.get(j).toLowerCase())) {

flag=true;

break;

}

}returnflag;

}

下面的例子根据不同的格式来搜索文本。不要重新造轮子,所以我们使用第三方的类库来实现这些功能。

在PDF文件中搜索

对于读取PDF文件,我们将使用两个非常流行的开源类库:iText(http://itextpdf.com/) 和 Apache PDFBox(http://pdfbox.apache.org/)。

基于iText文档,下面的方法用来从pdf中提取文本。第一步包括创建一个PdfReader访问文件,接着通过提取出PDF的页数,从每个页面中提取文本,提取的文本传递给searchText()方法。如果在提取的文本中找到一token。则停止在当前文件检索,该文件被认为是一个有效的搜索结果,及其存储路径和名称我们可以打印出来后,整个搜索结束。

//search in PDF files using iText librarybooleansearchInPDF_iText(String file) {

PdfReader reader=null;booleanflag =false;try{

reader=newPdfReader(file);intn =reader.getNumberOfPages();

OUTERMOST:for(inti = 1; i <= n; i++) {

String str=PdfTextExtractor.getTextFromPage(reader, i);

flag=searchText(str);if(flag) {

breakOUTERMOST;

}

}

}catch(Exception e) {

}finally{if(reader !=null) {

reader.close();

}returnflag;

}

}

如果你对PDFBox更加熟悉,你可以使用下面的方法。通过PDFParser 类创建PDF文件,然后提取出文件的页数,并完成通过searchText()方法提取每一页的文本。

booleansearchInPDF_PDFBox(String file) {

PDFParser parser=null;

String parsedText=null;

PDFTextStripper pdfStripper=null;

PDDocument pdDoc=null;

COSDocument cosDoc=null;booleanflag =false;intpage = 0;

File pdf=newFile(file);try{

parser=newPDFParser(newFileInputStream(pdf));

parser.parse();

cosDoc=parser.getDocument();

pdfStripper=newPDFTextStripper();

pdDoc=newPDDocument(cosDoc);

OUTERMOST:while(page <pdDoc.getNumberOfPages()) {

page++;

pdfStripper.setStartPage(page);

pdfStripper.setEndPage(page+ 1);

parsedText=pdfStripper.getText(pdDoc);

flag=searchText(parsedText);if(flag) {

breakOUTERMOST;

}

}

}catch(Exception e) {

}finally{try{if(cosDoc !=null) {

cosDoc.close();

}if(pdDoc !=null) {

pdDoc.close();

}

}catch(Exception e) {}returnflag;

}

}

在Microsoft的Word,Excel和PowerPoint中查找

微软的办公套装软件文件可以使用Apache POI(http://poi.apache.org/)类库来操作。下面的例子使用版本3.7,基于开发指南,从word中查找字符串的例子。

booleansearchInWord(String file) {

POIFSFileSystem fs=null;booleanflag =false;try{

fs=newPOIFSFileSystem(newFileInputStream(file));

HWPFDocument doc=newHWPFDocument(fs);

WordExtractor we=newWordExtractor(doc);

String[] paragraphs=we.getParagraphText();

OUTERMOST:for(inti = 0; i < paragraphs.length; i++) {

flag=searchText(paragraphs[i]);if(flag) {

breakOUTERMOST;

}

}

}catch(Exception e) {

}finally{returnflag;

}

}

我们从下面的例子中从Excel文本里提取文本。通过HSSFWorkbook创建excel文档,先遍历每个sheet页,然后是逐行,最后每个单元格。

booleansearchInExcel(String file) {

Row row;

Cell cell;

String text;booleanflag =false;

InputStream xls=null;try{

xls=newFileInputStream(file);

HSSFWorkbook wb=newHSSFWorkbook(xls);intsheets =wb.getNumberOfSheets();

OUTERMOST:for(inti = 0; i < sheets; i++) {

HSSFSheet sheet=wb.getSheetAt(i);

Iterator<Row> row_iterator =sheet.rowIterator();while(row_iterator.hasNext()) {

row=(Row) row_iterator.next();

Iterator<Cell> cell_iterator =row.cellIterator();while(cell_iterator.hasNext()) {

cell=cell_iterator.next();inttype =cell.getCellType();if(type ==HSSFCell.CELL_TYPE_STRING) {

text=cell.getStringCellValue();

flag=searchText(text);if(flag) {

breakOUTERMOST;

}

}

}

}

}

}catch(IOException e) {

}finally{try{if(xls !=null) {

xls.close();

}

}catch(IOException e) {}returnflag;

}

}

最后我们可以使用下面的代码从PowerPoint中提取文本。

booleansearchInPPT(String file) {booleanflag =false;

InputStream fis=null;

String text;try{

fis=newFileInputStream(newFile(file));

POIFSFileSystem fs=newPOIFSFileSystem(fis);

HSLFSlideShow show=newHSLFSlideShow(fs);

SlideShow ss=newSlideShow(show);

Slide[] slides=ss.getSlides();

OUTERMOST:for(inti = 0; i < slides.length; i++) {

TextRun[] runs=slides[i].getTextRuns();for(intj = 0; j < runs.length; j++) {

TextRun run=runs[j];if(run.getRunType() ==TextHeaderAtom.TITLE_TYPE) {

text=run.getText();

}else{

text= run.getRunType() + " " +run.getText();

}

flag=searchText(text);if(flag) {

breakOUTERMOST;

}

}

Notes notes=slides[i].getNotesSheet();if(notes !=null) {

runs=notes.getTextRuns();for(intj = 0; j < runs.length; j++) {

text=runs[j].getText();

flag=searchText(text);if(flag) {

breakOUTERMOST;

}

}

}

}

}catch(IOException e) {

}finally{try{if(fis !=null) {

fis.close();

}

}catch(IOException e) {}returnflag;

}

}

此外还有很多其他第三方优秀的类库,上面的例子在处理一些检索时不一定是最高效的。或许可以使用Apache Lucene(http://lucene.apache.org/java/docs/index.html)来获取很高的方式来处理。

在文本文件中搜索

文本文件(.txt,.html,.xml 等)不需要第三方的类库,它们完全可以使用NOI.2 的技术来实现:

booleansearchInText(Path file) {booleanflag =false;

Charset charset= Charset.forName("UTF-8");try(BufferedReader reader =Files.newBufferedReader(file, charset)) {

String line=null;

OUTERMOST:while((line = reader.readLine()) !=null) {

flag=searchText(line);if(flag) {

breakOUTERMOST;

}

}

}catch(IOException e) {

}finally{returnflag;

}

}

写一个完整的检索程序

importcom.itextpdf.text.pdf.PdfReader;importcom.itextpdf.text.pdf.parser.PdfTextExtractor;importjava.io.BufferedReader;importjava.io.File;importjava.io.FileInputStream;importjava.io.IOException;importjava.io.InputStream;importjava.nio.charset.Charset;importjava.nio.file.FileSystems;importjava.nio.file.FileVisitOption;importjava.nio.file.FileVisitResult;importjava.nio.file.FileVisitor;importjava.nio.file.Files;importjava.nio.file.Path;importjava.nio.file.attribute.BasicFileAttributes;importjava.util.ArrayList;importjava.util.EnumSet;importjava.util.Iterator;importjava.util.StringTokenizer;importorg.apache.pdfbox.cos.COSDocument;importorg.apache.pdfbox.pdfparser.PDFParser;importorg.apache.pdfbox.pdmodel.PDDocument;importorg.apache.pdfbox.util.PDFTextStripper;importorg.apache.poi.hslf.HSLFSlideShow;importorg.apache.poi.hslf.model.Notes;importorg.apache.poi.hslf.model.Slide;importorg.apache.poi.hslf.model.TextRun;importorg.apache.poi.hslf.record.TextHeaderAtom;importorg.apache.poi.hslf.usermodel.SlideShow;importorg.apache.poi.hssf.usermodel.HSSFCell;importorg.apache.poi.hssf.usermodel.HSSFSheet;importorg.apache.poi.hssf.usermodel.HSSFWorkbook;importorg.apache.poi.hwpf.HWPFDocument;importorg.apache.poi.hwpf.extractor.WordExtractor;importorg.apache.poi.poifs.filesystem.POIFSFileSystem;importorg.apache.poi.ss.usermodel.Cell;importorg.apache.poi.ss.usermodel.Row;classSearchimplementsFileVisitor {

ArrayList<String> wordsarray =newArrayList<>();

ArrayList<String> documents =newArrayList<>();booleanfound =false;publicSearch(String words) {

wordsarray.clear();

documents.clear();

StringTokenizer st=newStringTokenizer(words, ",");while(st.hasMoreTokens()) {

wordsarray.add(st.nextToken().trim());

}

}voidsearch(Path file)throwsIOException {

found=false;

String name=file.getFileName().toString();intmid = name.lastIndexOf(".");

String ext= name.substring(mid + 1, name.length());if(ext.equalsIgnoreCase("pdf")) {

found=searchInPDF_iText(file.toString());if(!found) {

found=searchInPDF_PDFBox(file.toString());

}

}if(ext.equalsIgnoreCase("doc") || ext.equalsIgnoreCase("docx")) {

found=searchInWord(file.toString());

}if(ext.equalsIgnoreCase("ppt")) {

searchInPPT(file.toString());

}if(ext.equalsIgnoreCase("xls")) {

searchInExcel(file.toString());

}if((ext.equalsIgnoreCase("txt")) || (ext.equalsIgnoreCase("xml")|| ext.equalsIgnoreCase("html"))|| ext.equalsIgnoreCase("htm") || ext.equalsIgnoreCase("xhtml")|| ext.equalsIgnoreCase("rtf")) {

searchInText(file);

}if(found) {

documents.add(file.toString());

}

}//search in text filesbooleansearchInText(Path file) {booleanflag =false;

Charset charset= Charset.forName("UTF-8");try(BufferedReader reader =Files.newBufferedReader(file, charset)) {

String line=null;

OUTERMOST:while((line = reader.readLine()) !=null) {

flag=searchText(line);if(flag) {

breakOUTERMOST;

}

}

}catch(IOException e) {

}finally{returnflag;

}

}//search in Excel filesbooleansearchInExcel(String file) {

Row row;

Cell cell;

String text;booleanflag =false;

InputStream xls=null;try{

xls=newFileInputStream(file);

HSSFWorkbook wb=newHSSFWorkbook(xls);intsheets =wb.getNumberOfSheets();

OUTERMOST:for(inti = 0; i < sheets; i++) {

HSSFSheet sheet=wb.getSheetAt(i);

Iterator<Row> row_iterator =sheet.rowIterator();while(row_iterator.hasNext()) {

row=(Row) row_iterator.next();

Iterator<Cell> cell_iterator =row.cellIterator();while(cell_iterator.hasNext()) {

cell=cell_iterator.next();inttype =cell.getCellType();if(type ==HSSFCell.CELL_TYPE_STRING) {

text=cell.getStringCellValue();

flag=searchText(text);if(flag) {

breakOUTERMOST;

}

}

}

}

}

}catch(IOException e) {

}finally{try{if(xls !=null) {

xls.close();

}

}catch(IOException e) {

}returnflag;

}

}//search in PowerPoint filesbooleansearchInPPT(String file) {booleanflag =false;

InputStream fis=null;

String text;try{

fis=newFileInputStream(newFile(file));

POIFSFileSystem fs=newPOIFSFileSystem(fis);

HSLFSlideShow show=newHSLFSlideShow(fs);

SlideShow ss=newSlideShow(show);

Slide[] slides=ss.getSlides();

OUTERMOST:for(inti = 0; i < slides.length; i++) {

TextRun[] runs=slides[i].getTextRuns();for(intj = 0; j < runs.length; j++) {

TextRun run=runs[j];if(run.getRunType() ==TextHeaderAtom.TITLE_TYPE) {

text=run.getText();

}else{

text= run.getRunType() + " " +run.getText();

}

flag=searchText(text);if(flag) {

breakOUTERMOST;

}

}

Notes notes=slides[i].getNotesSheet();if(notes !=null) {

runs=notes.getTextRuns();for(intj = 0; j < runs.length; j++) {

text=runs[j].getText();

flag=searchText(text);if(flag) {

breakOUTERMOST;

}

}

}

}

}catch(IOException e) {

}finally{try{if(fis !=null) {

fis.close();

}

}catch(IOException e) {

}returnflag;

}

}//search in Word filesbooleansearchInWord(String file) {

POIFSFileSystem fs=null;booleanflag =false;try{

fs=newPOIFSFileSystem(newFileInputStream(file));

HWPFDocument doc=newHWPFDocument(fs);

WordExtractor we=newWordExtractor(doc);

String[] paragraphs=we.getParagraphText();

OUTERMOST:for(inti = 0; i < paragraphs.length; i++) {

flag=searchText(paragraphs[i]);if(flag) {

breakOUTERMOST;

}

}

}catch(Exception e) {

}finally{returnflag;

}

}//search in PDF files using PDFBox librarybooleansearchInPDF_PDFBox(String file) {

PDFParser parser=null;

String parsedText=null;

PDFTextStripper pdfStripper=null;

PDDocument pdDoc=null;

COSDocument cosDoc=null;booleanflag =false;intpage = 0;

File pdf=newFile(file);try{

parser=newPDFParser(newFileInputStream(pdf));

parser.parse();

cosDoc=parser.getDocument();

pdfStripper=newPDFTextStripper();

pdDoc=newPDDocument(cosDoc);

OUTERMOST:while(page <pdDoc.getNumberOfPages()) {

page++;

pdfStripper.setStartPage(page);

pdfStripper.setEndPage(page+ 1);

parsedText=pdfStripper.getText(pdDoc);

flag=searchText(parsedText);if(flag) {

breakOUTERMOST;

}

}

}catch(Exception e) {

}finally{try{if(cosDoc !=null) {

cosDoc.close();

}if(pdDoc !=null) {

pdDoc.close();

}

}catch(Exception e) {

}returnflag;

}

}//search in PDF files using iText librarybooleansearchInPDF_iText(String file) {

PdfReader reader=null;booleanflag =false;try{

reader=newPdfReader(file);intn =reader.getNumberOfPages();

OUTERMOST:for(inti = 1; i <= n; i++) {

String str=PdfTextExtractor.getTextFromPage(reader, i);

flag=searchText(str);if(flag) {

breakOUTERMOST;

}

}

}catch(Exception e) {

}finally{if(reader !=null) {

reader.close();

}returnflag;

}

}//search textprivatebooleansearchText(String text) {booleanflag =false;for(intj = 0; j < wordsarray.size(); j++) {if((text.toLowerCase()).contains(wordsarray.get(j).toLowerCase())) {

flag=true;

break;

}

}returnflag;

}

@OverridepublicFileVisitResult postVisitDirectory(Object dir, IOException exc)throwsIOException {

System.out.println("Visited: " +(Path) dir);returnFileVisitResult.CONTINUE;

}

@OverridepublicFileVisitResult preVisitDirectory(Object dir, BasicFileAttributes attrs)throwsIOException {returnFileVisitResult.CONTINUE;

}

@OverridepublicFileVisitResult visitFile(Object file, BasicFileAttributes attrs)throwsIOException {

search((Path) file);returnFileVisitResult.CONTINUE;

}

@OverridepublicFileVisitResult visitFileFailed(Object file, IOException exc)throwsIOException {//report an error if necessaryreturnFileVisitResult.CONTINUE;

}

}classMain {publicstaticvoidmain(String[] args)throwsIOException {

String words= "Rafael Nadal, tennis, winner of Roland Garros, BNP Paribas tournament draws";

Search walk=newSearch(words);

EnumSet opts=EnumSet.of(FileVisitOption.FOLLOW_LINKS);

Iterable<Path> dirs =FileSystems.getDefault().getRootDirectories();for(Path root : dirs) {

Files.walkFileTree(root, opts, Integer.MAX_VALUE, walk);

}

System.out.println("____________________________________________________________");for(String path_string: walk.documents){

System.out.println(path_string);

}

System.out.println("____________________________________________________________");

}

}

需要注意的是,有些时候程序处理的很慢,这主要取决于文件大小,要检查的文件的个数,目录的层级深度。此外你可以继续完善这个程序,例如支持更多地格式,增加进度条来显示处理的状态,使用多线程加快查找速度。

 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
© 2005- 王朝網路 版權所有 導航