【文章標題】搜索文本內容——Java代碼的簡單實現(修改版)
【文章作者】曾健生
【作者郵箱】[email protected]
【作者QQ】190678908
【作者博客】http://blog.csdn.net/newjueqi
【編程環境】JDK 1.6.0_01
【作者聲明】歡迎轉載文章,但轉載請保留文章的完整性以及註明文章的出處。
*******************************************************************************
昨天由於編程的要求,需要從300多個源代碼中查找一個關鍵字在哪個源代碼文件中用過,逼於無奈只能一個文件一個文件的查找,結果30分鐘後本人就崩潰了(連續查了200多個文件),看到眼睛都花了還是沒結果。這時我是多麼懷念平時上網用搜索引擎的日子!突然間靈機一動,現在從衆多的源碼文件中查找一個關鍵字,不就是一個典型的搜索行爲,現在學習完Java的IO流後就實現一個文本內容搜索軟件。
本人這個文本搜索軟件的思路很簡單,分爲以下幾步:
1. 遍歷一個目錄裏的每個文件對象
2. 如果文件對象是一個目錄,則通過遞歸繼續遍歷這個目錄下的每個文件
3. 如果文件對象是一個文件,則判斷文件名是否以“.java”結尾(是否Java源文件),如果以“.java”結尾,則讀取文本內容。
4. 把文本的每一行存儲在一個字符串中,通過contains函數判斷該行字符串是否包含關鍵字,如果包含關鍵字就把該行字符串信息寫入到一個配置文件中
5. 關閉文件流。
package newjueqi.NET.csdn.SearchText;
import java.io.*;
//山寨版的LineNumberReader類,讀取文本內容時可獲得當前的代碼行數,實現了Java中的LineNumberReader的功能
class MyLineNumberReader
{
//這裏用的是裝飾器模式,具體的內容可參見本人的博文《打造山寨產品和僞造產品的利器——裝飾模式》
private Reader fr;
private int lineNumber=0; //記錄當前的行數
MyLineNumberReader( Reader fr )
{
this.fr=fr;
}
/*
通過read()函數一個一個字符的讀取,當遇到回車換行就返回讀取的一行字符串
*/
public String readLine()
{
int num=0;
StringBuffer sb=new StringBuffer();
try {
while( (num=fr.read())!=-1 )
{
if( num=='/r')
continue;
else if( num=='/n')
{
lineNumber++; //讀取一行,行號加1
return sb.toString(); //返回讀取的一行字符串
}
else
{
sb.append((char)num );
}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
//防止文本末尾沒加回車換行符,以丟失文本內容
if( sb.length()>0 )
{
lineNumber++;
return sb.toString();
}
return null;
}
//關閉輸入流對象
public void close()
{
try {
fr.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//設置當前的行數
public void setLineNumber(int lineNumber)
{
this.lineNumber=lineNumber;
}
//獲取當前的行數
public int getLineNumber()
{
return lineNumber;
}
}
/*
搜索文本內容的類
輸入的內容爲要查找的目錄和查找的內容
*/
class SearchContent
{
private File f=null; //要查找的目錄對象
private String filename=null; //要查找的目錄路徑
private BufferedWriter bw=null;
private String findtxt=null; //要查找的文本內容
private String fileType=null; //要查找的文件類型
private int totalFileCount=0; //共搜索的文件數
private int findedFileCount=0; //搜索到有用的文件數
private int findContentCount=0; //搜索到的有用信息數目
/**構造函數,
@param f 要查找目錄的對象
@param findtxt 要查找的關鍵字
@param fileType 要查找的文件類型
*/
SearchContent( String filename ,String findtxt, String fileType )
{
this.filename=filename;
this.findtxt=findtxt;
this.fileType=fileType;
}
//暴露的公共接口,開始在指定的目錄中搜索關鍵字
public void startSearchContent()
{
try
{
bw=new BufferedWriter(
new FileWriter( "log.txt"));
f=new File( filename );
//搜索關鍵字的內容
listFile( f );
//顯示文件的統計信息
showInfo();
//關閉文件流
bw.close();
System.out.println( "搜索完畢,搜索結果已保存在log.txt文件中" );
}
catch( Exception e)
{
System.out.println( "搜索出錯!!!" );
}
}
/*
通過遞歸搜索目錄,搜索過程分兩種情況:
1.如果是目錄,則通過遞歸繼續查找目錄下的文件
2.如果是文件,則先判斷是否是fileType類型文件,如果是的話就搜索文件內容
*/
private void listFile( File f )
{
File[] files = f.listFiles();
for(int x=0; x<files.length; x++)
{
if(files[x].isDirectory())
listFile( files[x] );
else
{
//判斷文件名是否以fileType結尾
if( files[x].getName().endsWith( fileType ))
{
FindTxt( files[x]);
}
}
}
}
/*
從文件中搜索制定的內容,分下面幾步
1.使用自定義的山寨版LineNumberReader類,讀取文件的每一行
2.
*/
private void FindTxt(File f )
{
totalFileCount++; //搜索到的文件數加1
boolean flag=false; //記錄當前文件中是否搜索到關鍵字的標誌
MyLineNumberReader br=null;
try {
br = new MyLineNumberReader(
new FileReader(f));
String s=null;
while( (s=br.readLine())!=null)
{
//文本行中是否包含制定的字符串
if(s.contains(findtxt))
{
flag=true; //搜索到文件的關鍵字,標誌變爲真
findContentCount++; //搜到的關鍵字相當的數目加1
bw.write(f.getAbsolutePath());
bw.newLine();
bw.write(" "+br.getLineNumber()+": "+s );
bw.newLine();
bw.newLine();
}
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//如果當前文件中搜索到關鍵字,則把搜索到的有用文件數加1
if( flag==true )
{
findedFileCount++;
}
br.close();
}
//輸出搜索的統計信息
private void showInfo() throws IOException
{
bw.write( " 搜索關鍵字:"+findtxt);
bw.newLine();
bw.write( " 共搜索的.java文件數:"+totalFileCount);
bw.newLine();
bw.write( " 關鍵文件數:"+findedFileCount);
bw.newLine();
bw.write( " 搜索到的關鍵字數目:"+findContentCount );
bw.newLine();
}
}
輸出結果如下:
d:/day4/Demo5.java
4: int age;
d:/day4/Demo5.java
21: p.age = 23;
d:/day4/Demo5.java
25: System.out.println(p.age);
d:/day4/Demo5.java
33: p.age = 25;
d:/day4/Demo6.java
12: private int age;
d:/day4/Demo6.java
25: public void setAge(int myage)
d:/day4/Demo6.java
27: age = myage;
d:/day4/Demo6.java
31: return age;
搜索關鍵字:age
共搜索的.java文件數:10
關鍵文件數:2
搜索到的關鍵字數目:8
最後感嘆一句:使用親手寫的軟件果然很爽很痛快!!!