初學(xué)Java千元,一直搞不懂java里面的io關(guān)系仗岖,在網(wǎng)上找了很多大多都是給個結(jié)構(gòu)圖草草描述也看的不是很懂悲幅。而且沒有結(jié)合到j(luò)ava8 的最新技術(shù),所以自己來整理一下瘾杭,有錯的話請指正诅病,也希望大家提出寶貴意見。
首先看個圖:(如果你也是初學(xué)者,我相信你看了真?zhèn)€人都不好了贤笆,想想java設(shè)計者真是煞費苦心坝蕖!)
這是Javaio 比較基本的一些處理流芥永,除此之外我們還會提到一些比較深入的基于io的處理類篡殷,比如console類,SteamTokenzier,Externalizable接口埋涧,Serializable接口等等一些高級用法極其原理板辽。
一、java io的開始:文件
1. 我們主要講的是流飞袋,流的本質(zhì)也是對文件的處理戳气,我們循序漸進(jìn)一步一步從文件將到流去。
2. java 處理文件的類 File,java提供了十分詳細(xì)的文件處理方法巧鸭,舉了其中幾個例子瓶您,其余的可以去
packagecom.hxw.io;
importjava.io.*;
publicclassFileExample{
publicstaticvoidmain(String[]?args)?{
createFile();
}
/**
*?文件處理示例
*/
publicstaticvoidcreateFile()?{
File?f=newFile("E:/電腦桌面/jar/files/create.txt");
try{
f.createNewFile();//當(dāng)且僅當(dāng)不存在具有此抽象路徑名指定名稱的文件時,不可分地創(chuàng)建一個新的空文件纲仍。
System.out.println("該分區(qū)大小"+f.getTotalSpace()/(1024*1024*1024)+"G");//返回由此抽象路徑名表示的文件或目錄的名稱呀袱。
f.mkdirs();//創(chuàng)建此抽象路徑名指定的目錄,包括所有必需但不存在的父目錄郑叠。
//????????????f.delete();?//??刪除此抽象路徑名表示的文件或目錄
System.out.println("文件名??"+f.getName());//??返回由此抽象路徑名表示的文件或目錄的名稱夜赵。
System.out.println("文件父目錄字符串?"+f.getParent());//?返回此抽象路徑名父目錄的路徑名字符串;如果此路徑名沒有指定父目錄乡革,則返回?null寇僧。
}catch(Exception?e)?{
e.printStackTrace();
}
}
}
二、字節(jié)流:
1.字節(jié)流有輸入和輸出流沸版,我們首先看輸入流InputStream,我們首先解析一個例子(FileInputStream)嘁傀。
packagecom.hxw.io;
importjava.io.File;
importjava.io.FileInputStream;
importjava.io.IOException;
importjava.io.InputStream;
publicclassFileCount?{
/**
*?我們寫一個檢測文件長度的小程序,別看這個程序挺長的视粮,你忽略try?catch塊后發(fā)現(xiàn)也就那么幾行而已细办。
*/
publicstaticvoidmain(String[]?args)?{
//TODO?自動生成的方法存根
intcount=0;//統(tǒng)計文件字節(jié)長度
InputStreamstreamReader?=null;//文件輸入流
try{
streamReader=newFileInputStream(newFile("D:/David/Java/java?高級進(jìn)階/files/tiger.jpg"));
/*1.new?File()里面的文件地址也可以寫成D:\\David\\Java\\java?高級進(jìn)階\\files\\tiger.jpg,前一個\是用來對后一個
*?進(jìn)行轉(zhuǎn)換的,F(xiàn)ileInputStream是有緩沖區(qū)的蕾殴,所以用完之后必須關(guān)閉笑撞,否則可能導(dǎo)致內(nèi)存占滿,數(shù)據(jù)丟失钓觉。
*/
while(streamReader.read()!=-1)?{//讀取文件字節(jié)茴肥,并遞增指針到下一個字節(jié)
count++;
}
System.out.println("---長度是:?"+count+"?字節(jié)");
}catch(finalIOException?e)?{
//TODO?自動生成的?catch?塊
e.printStackTrace();
}finally{
try{
streamReader.close();
}catch(IOException?e)?{
//TODO?自動生成的?catch?塊
e.printStackTrace();
}
}
}
}
我們一步一步來,首先荡灾,上面的程序存在問題是炉爆,每讀取一個自己我都要去用到FileInputStream堕虹,我輸出的結(jié)果是“---長度是: 64982 字節(jié)”,那么進(jìn)行了64982次操作芬首!可能想象如果文件十分龐大,這樣的操作肯定會出大問題逼裆,所以引出了緩沖區(qū)的概念郁稍。可以將streamReader.read()改成streamReader.read(byte[]b)此方法讀取的字節(jié)數(shù)目等于字節(jié)數(shù)組的長度胜宇,讀取的數(shù)據(jù)被存儲在字節(jié)數(shù)組中耀怜,返回讀取的字節(jié)數(shù),InputStream還有其他方法mark,reset,markSupported方法桐愉,例如:
markSupported 判斷該輸入流能支持mark和reset方法财破。
mark用于標(biāo)記當(dāng)前位置;在讀取一定數(shù)量的數(shù)據(jù)(小于readlimit的數(shù)據(jù))后使用reset可以回到mark標(biāo)記的位置从诲。
FileInputStream不支持mark/reset操作左痢;BufferedInputStream支持此操作;
mark(readlimit)的含義是在當(dāng)前位置作一個標(biāo)記系洛,制定可以重新讀取的最大字節(jié)數(shù)俊性,也就是說你如果標(biāo)記后讀取的字節(jié)數(shù)大于readlimit,你就再也回不到回來的位置了描扯。
通常InputStream的read()返回-1后定页,說明到達(dá)文件尾,不能再讀取绽诚。除非使用了mark/reset典徊。
2.FileOutputStream 循序漸進(jìn)版, InputStream是所有字節(jié)輸出流的父類恩够,子類有ByteArrayOutputStream,FileOutputStream,ObjectOutputStreanm,這些我們在后面都會一一說到卒落。先說FileOutputStream
我以一個文件復(fù)制程序來說,順便演示一下緩存區(qū)的使用玫鸟。(Java I/O默認(rèn)是不緩沖流的导绷,所謂“緩沖”就是先把從流中得到的一塊字節(jié)序列暫存在一個被稱為buffer的內(nèi)部字節(jié)數(shù)組里,然后你可以一下子取到這一整塊的字節(jié)數(shù)據(jù)屎飘,沒有緩沖的流只能一個字節(jié)一個字節(jié)讀妥曲,效率孰高孰低一目了然。有兩個特殊的輸入流實現(xiàn)了緩沖功能钦购,一個是我們常用的BufferedInputStream.)
packagecom.hxw.io;
importjava.io.*;
publicclassFileCopy?{
publicstaticvoidmain(String[]?args)?{
//?TODO自動生成的方法存根
byte[]?buffer=newbyte[512];//一次取出的字節(jié)數(shù)大小,緩沖區(qū)大小
intnumberRead=0;
FileInputStream?input=null;
FileOutputStream?out?=null;
try{
input=newFileInputStream("D:/David/Java/java?高級進(jìn)階/files/tiger.jpg");
out=newFileOutputStream("D:/David/Java/java?高級進(jìn)階/files/tiger2.jpg");//如果文件不存在會自動創(chuàng)建
while((numberRead=input.read(buffer))!=-1)?{//numberRead的目的在于防止最后一次讀取的字節(jié)小于buffer長度檐盟,
out.write(buffer,0,?numberRead);//否則會自動被填充0
}
}catch(finalIOException?e)?{
//?TODO自動生成的?catch?塊
e.printStackTrace();
}finally{
try{
input.close();
out.close();
}catch(IOException?e)?{
//?TODO自動生成的?catch?塊
e.printStackTrace();
}
}
}
}
3.讀寫對象:ObjectInputStream 和ObjectOutputStream ,該流允許讀取或?qū)懭胗脩糇远x的類押桃,但是要實現(xiàn)這種功能葵萎,被讀取和寫入的類必須實現(xiàn)Serializable接口,其實該接口并沒有什么方法,可能相當(dāng)于一個標(biāo)記而已羡忘,但是確實不合缺少的谎痢。實例代碼如下:
packagecom.hxw.io;
importjava.io.*;
publicclassObjetStream?{
/**
*?@param?args
*/
publicstaticvoidmain(String[]?args)?{
//?TODO自動生成的方法存根
ObjectOutputStream?objectwriter=null;
ObjectInputStream?objectreader=null;
try{
objectwriter=newObjectOutputStream(newFileOutputStream("D:/David/Java/java?高級進(jìn)階/files/student.txt"));
objectwriter.writeObject(newStudent("gg",22));
objectwriter.writeObject(newStudent("tt",18));
objectwriter.writeObject(newStudent("rr",17));
objectreader=newObjectInputStream(newFileInputStream("D:/David/Java/java?高級進(jìn)階/files/student.txt"));
for(inti?=0;?i?<3;?i++)?{
System.out.println(objectreader.readObject());
}
}catch(IOException?|?ClassNotFoundException?e)?{
//?TODO自動生成的?catch?塊
e.printStackTrace();
}finally{
try{
objectreader.close();
objectwriter.close();
}catch(IOException?e)?{
//?TODO自動生成的?catch?塊
e.printStackTrace();
}
}
}
}
classStudentimplementsSerializable{
privateString?name;
privateintage;
publicStudent(String?name,intage)?{
super();
this.name?=?name;
this.age?=?age;
}
@Override
publicString?toString()?{
return"Student?[name="+?name?+",?age="+?age?+"]";
}
}
運行后系統(tǒng)輸出:
Student [name=gg, age=22]
Student [name=tt, age=18]
Student [name=rr, age=17]
4.有時沒有必要存儲整個對象的信息,而只是要存儲一個對象的成員數(shù)據(jù)卷雕,成員數(shù)據(jù)的類型假設(shè)都是Java的基本數(shù)據(jù)類型节猿,這樣的需求不必使用到與Object輸入、輸出相關(guān)的流對象漫雕,可以使用DataInputStream滨嘱、DataOutputStream來寫入或讀出數(shù)據(jù)。下面是一個例子:(DataInputStream的好處在于在從文件讀出數(shù)據(jù)時浸间,不用費心地自行判斷讀入字符串時或讀入int類型時何時將停止太雨,使用對應(yīng)的readUTF()和readInt()方法就可以正確地讀入完整的類型數(shù)據(jù)。)
packagecom.hxw;
publicclassMember?{
privateString?name;
privateintage;
publicMember()?{
}
publicMember(String?name,intage)?{
this.name?=?name;
this.age?=?age;
}
publicvoidsetName(String?name){
this.name?=?name;
}
publicvoidsetAge(intage)?{
this.age?=?age;
}
publicString?getName()?{
returnname;
}
publicintgetAge()?{
returnage;
}
}
打算將Member類實例的成員數(shù)據(jù)寫入文件中魁蒜,并打算在讀入文件數(shù)據(jù)后囊扳,將這些數(shù)據(jù)還原為Member對象。下面的代碼簡單示范了如何實現(xiàn)這個需求梅惯。
packagecom.hxw;
importjava.io.*;
publicclassDataStreamDemo
{
publicstaticvoidmain(String[]args)
{
Member[]?members?=?{newMember("Justin",90),
newMember("momor",95),
newMember("Bush",88)};
try
{
DataOutputStreamdataOutputStream?=newDataOutputStream(newFileOutputStream(args[0]));
for(Member?member:members)
{
//寫入UTF字符串
dataOutputStream.writeUTF(member.getName());
//寫入int數(shù)據(jù)
dataOutputStream.writeInt(member.getAge());
}
//所有數(shù)據(jù)至目的地
dataOutputStream.flush();
//關(guān)閉流
dataOutputStream.close();
DataInputStreamdataInputStream?=newDataInputStream(newFileInputStream(args[0]));
//讀出數(shù)據(jù)并還原為對象
for(inti=0;i
{
//讀出UTF字符串
String?name?=dataInputStream.readUTF();
//讀出int數(shù)據(jù)
intscore?=dataInputStream.readInt();
members[i]?=?newMember(name,score);
}
//關(guān)閉流
dataInputStream.close();
//顯示還原后的數(shù)據(jù)
for(Member?member?:?members)
{
System.out.printf("%s\t%d%n",member.getName(),member.getAge());
}
}
catch(IOException?e)
{
e.printStackTrace();
}
}
}
5.PushbackInputStream類繼承了FilterInputStream類是iputStream類的修飾者宪拥。提供可以將數(shù)據(jù)插入到輸入流前端的能力(當(dāng)然也可以做其他操作)。簡而言之PushbackInputStream類的作用就是能夠在讀取緩沖區(qū)的時候提前知道下一個字節(jié)是什么铣减,其實質(zhì)是讀取到下一個字符后回退的做法她君,這之間可以進(jìn)行很多操作,這有點向你把讀取緩沖區(qū)的過程當(dāng)成一個數(shù)組的遍歷葫哗,遍歷到某個字符的時候可以進(jìn)行的操作缔刹,當(dāng)然,如果要插入劣针,能夠插入的最大字節(jié)數(shù)是與推回緩沖區(qū)的大小相關(guān)的校镐,插入字符肯定不能大于緩沖區(qū)吧!下面是一個示例捺典。
packagecom.hxw.io;
importjava.io.ByteArrayInputStream;//導(dǎo)入ByteArrayInputStream的包
importjava.io.IOException;
importjava.io.PushbackInputStream;
/**
*?回退流操作
*?*/
publicclassPushBackInputStreamDemo?{
publicstaticvoidmain(String[]?args)throwsIOException?{
String?str?="hello,rollenholt";
PushbackInputStream?push?=null;//?聲明回退流對象
ByteArrayInputStream?bat?=null;//?聲明字節(jié)數(shù)組流對象
bat?=newByteArrayInputStream(str.getBytes());
push?=newPushbackInputStream(bat);//?創(chuàng)建回退流對象鸟廓,將拆解的字節(jié)數(shù)組流傳入
inttemp?=0;
while((temp?=?push.read())?!=?-1)?{//?push.read()逐字節(jié)讀取存放在temp中,如果讀取完成返回-1
if(temp?==',')?{//?判斷讀取的是否是逗號
push.unread(temp);//回到temp的位置
temp?=?push.read();//接著讀取字節(jié)
System.out.print("(回退"+?(char)?temp?+")?");//?輸出回退的字符
}else{
System.out.print((char)?temp);//?否則輸出字符
}
}
}
}
6.SequenceInputStream:有些情況下襟己,當(dāng)我們需要從多個輸入流中向程序讀入數(shù)據(jù)引谜。此時,可以使用合并流擎浴,將多個輸入流合并成一個SequenceInputStream流對象员咽。SequenceInputStream會將與之相連接的流集組合成一個輸入流并從第一個輸入流開始讀取,直到到達(dá)文件末尾贮预,接著從第二個輸入流讀取贝室,依次類推契讲,直到到達(dá)包含的最后一個輸入流的文件末尾為止。 合并流的作用是將多個源合并合一個源滑频。其可接收枚舉類所封閉的多個字節(jié)流對象捡偏。
packagecom.hxw.io;
importjava.io.*;
importjava.util.Enumeration;
importjava.util.Vector;
publicclassSequenceInputStreamTest?{
/**
*?@param?args
*????????????SequenceInputStream合并流,將與之相連接的流集組合成一個輸入流并從第一個輸入流開始讀取峡迷,
*????????????直到到達(dá)文件末尾霹琼,接著從第二個輸入流讀取,依次類推凉当,直到到達(dá)包含的最后一個輸入流的文件末尾為止。
*????????????合并流的作用是將多個源合并合一個源售葡】春迹可接收枚舉類所封閉的多個字節(jié)流對象。
*/
publicstaticvoidmain(String[]?args)?{
doSequence();
}
privatestaticvoiddoSequence()?{
//?創(chuàng)建一個合并流的對象
SequenceInputStream?sis?=null;
//?創(chuàng)建輸出流挟伙。
BufferedOutputStream?bos?=null;
try{
//?構(gòu)建流集合楼雹。
Vector?vector?=newVector();
vector.addElement(newFileInputStream("D:\text1.txt"));
vector.addElement(newFileInputStream("D:\text2.txt"));
vector.addElement(newFileInputStream("D:\text3.txt"));
Enumeration?e?=?vector.elements();
sis?=newSequenceInputStream(e);
bos?=newBufferedOutputStream(newFileOutputStream("D:\text4.txt"));
//?讀寫數(shù)據(jù)
byte[]?buf?=newbyte[1024];
intlen?=0;
while((len?=?sis.read(buf))?!=?-1)?{
bos.write(buf,0,?len);
bos.flush();
}
}catch(FileNotFoundException?e1)?{
e1.printStackTrace();
}catch(IOException?e1)?{
e1.printStackTrace();
}finally{
try{
if(sis?!=null)
sis.close();
}catch(IOException?e)?{
e.printStackTrace();
}
try{
if(bos?!=null)
bos.close();
}catch(IOException?e)?{
e.printStackTrace();
}
}
}
}
7.PrintStream 說這個名字可能初學(xué)者不熟悉,如果說System.out.print()你肯定熟悉尖阔,System.out這個對象就是PrintStream贮缅,這個我們不做過多示例
三、字符流(顧名思義介却,就是操作字符文件的流)
1.java 使用Unicode存儲字符串谴供,在寫入字符流時我們都可以指定寫入的字符串的編碼。前面介紹了不用拋異常的處理字節(jié)型數(shù)據(jù)的流ByteArrayOutputStream齿坷,與之對應(yīng)的操作字符類的類就是CharArrayReader,CharArrayWriter類桂肌,這里也會用到緩沖區(qū),不過是字符緩沖區(qū)永淌,一般講字符串放入到操作字符的io流一般方法是
CharArrayReaderreader=mew CharArrayReader(str.toCharArray()); 一旦會去到CharArrayReader實例就可以使用CharArrayReader訪問字符串的各個元素以執(zhí)行進(jìn)一步讀取操作崎场。不做例子
2.我們用FileReader,PrintWriter來做示范
packagecom.hxw.io;
importjava.io.FileNotFoundException;
importjava.io.FileReader;
importjava.io.IOException;
importjava.io.PrintWriter;
importjava.nio.CharBuffer;
publicclassPrint?{
/**
*?@param?args
*/
publicstaticvoidmain(String[]?args)?{
//?TODO自動生成的方法存根
char[]?buffer=newchar[512];//一次取出的字節(jié)數(shù)大小,緩沖區(qū)大小
intnumberRead=0;
FileReader?reader=null;//讀取字符文件的流
PrintWriter?writer=null;//寫字符到控制臺的流
try{
reader=newFileReader("D:/David/Java/java?高級進(jìn)階/files/copy1.txt");
writer=newPrintWriter(System.out);//PrintWriter可以輸出字符到文件遂蛀,也可以輸出到控制臺
while((numberRead=reader.read(buffer))!=-1)?{
writer.write(buffer,0,?numberRead);
}
}catch(IOException?e)?{
//?TODO自動生成的?catch?塊
e.printStackTrace();
}finally{
try{
reader.close();
}catch(IOException?e)?{
//?TODO自動生成的?catch?塊
e.printStackTrace();
}
writer.close();//這個不用拋異常
}
}
}
3.相對我們前面的例子是直接用FileReader打開的文件谭跨,我們這次使用鏈接流,一般比較常用的都用鏈接流李滴,所謂鏈接流就是就多次對流的封裝螃宙,這樣能更好的操作個管理數(shù)據(jù),(比如我們利用DataInputStream(BufferedInputStream(FileInputStream))將字節(jié)流層層包裝后悬嗓,我們可以讀取readByte(),readChar()這樣更加具體的操作污呼,注意,該流屬于字節(jié)流對字符進(jìn)行操作包竹,)字符流用CharArrayReader就可以了燕酷。下面的示例我們將用到j(luò)2se 5中的一個可變參數(shù)進(jìn)行一個小度擴(kuò)展籍凝。使用BufferedWriter 和BufferedReader用文件級聯(lián)的方式進(jìn)行寫入,即將多個文件寫入到同一文件中(自帶緩沖區(qū)的輸出輸出流BufferedReader和BufferedWriter,該流最常用的屬readLine()方法了苗缩,讀取一行數(shù)據(jù)饵蒂,并返回String)。
packagecom.hxw.io;
importjava.io.BufferedReader;
importjava.io.BufferedWriter;
importjava.io.FileReader;
importjava.io.FileWriter;
importjava.io.IOException;
importjava.util.Iterator;
publicclassFileConcatenate?{
/**
*?包裝類進(jìn)行文件級聯(lián)操作
*/
publicstaticvoidmain(String[]?args)?{
//?TODO自動生成的方法存根
try{
concennateFile(args);
}catch(IOException?e)?{
//?TODO自動生成的?catch?塊
e.printStackTrace();
}
}
publicstaticvoidconcennateFile(String...fileName)throwsIOException{
String?str;
//構(gòu)建對該文件您的輸入流
BufferedWriter?writer=newBufferedWriter(newFileWriter("D:/David/Java/java?高級進(jìn)階/files/copy2.txt"));
for(String?name:?fileName){
BufferedReader?reader=newBufferedReader(newFileReader(name));
while((str=reader.readLine())!=null)?{
writer.write(str);
writer.newLine();
}
}
}
}
4.Console類,該類提供了用于讀取密碼的方法酱讶,可以禁止控制臺回顯并返回char數(shù)組退盯,對兩個特性對保證安全有作用,平時用的不多泻肯,了解就行渊迁。
5.StreamTokenizer 類,這個類非常有用灶挟,它可以把輸入流解析為標(biāo)記(token), StreamTokenizer 并非派生自InputStream或者OutputStream琉朽,而是歸類于io庫中,因為StreamTokenizer只處理InputStream對象稚铣。
首先給出我的文本文件內(nèi)容:
'水上漂'
青青草
"i love wyhss"
{3211}
23223 3523
i love wyh 箱叁,。
. ,
下面是代碼:
packagecom.hxw.io;
importjava.io.BufferedReader;
importjava.io.FileReader;
importjava.io.IOException;
importjava.io.StreamTokenizer;
/**
*?使用StreamTokenizer來統(tǒng)計文件中的字符數(shù)
*?StreamTokenizer?類獲取輸入流并將其分析為“標(biāo)記”惕医,允許一次讀取一個標(biāo)記耕漱。
*?分析過程由一個表和許多可以設(shè)置為各種狀態(tài)的標(biāo)志控制。
*?該流的標(biāo)記生成器可以識別標(biāo)識符抬伺、數(shù)字螟够、引用的字符串和各種注釋樣式。
*
*??默認(rèn)情況下沛简,StreamTokenizer認(rèn)為下列內(nèi)容是Token:?字母齐鲤、數(shù)字、除C和C++注釋符號以外的其他符號椒楣。
*??如符號"/"不是Token给郊,注釋后的內(nèi)容也不是,而"\"是Token捧灰。單引號和雙引號以及其中的內(nèi)容淆九,只能算是一個Token。
*??統(tǒng)計文章字符數(shù)的程序毛俏,不是簡單的統(tǒng)計Token數(shù)就萬事大吉炭庙,因為字符數(shù)不等于Token。按照Token的規(guī)定煌寇,
*??引號中的內(nèi)容就算是10頁也算一個Token焕蹄。如果希望引號和引號中的內(nèi)容都算作Token,應(yīng)該調(diào)用下面的代碼:
*????st.ordinaryChar('\'');
*?st.ordinaryChar('\"');
*/
publicclassStreamTokenizerExample?{
/**
*?統(tǒng)計字符數(shù)
*?@param?fileName?文件名
*?@return????字符數(shù)
*/
publicstaticvoidmain(String[]?args)?{
String?fileName?="D:/David/Java/java?高級進(jìn)階/files/copy1.txt";
StreamTokenizerExample.statis(fileName);
}
publicstaticlongstatis(String?fileName)?{
FileReader?fileReader?=null;
try{
fileReader?=newFileReader(fileName);
//創(chuàng)建分析給定字符流的標(biāo)記生成器
StreamTokenizer?st?=newStreamTokenizer(newBufferedReader(
fileReader));
//ordinaryChar方法指定字符參數(shù)在此標(biāo)記生成器中是“普通”字符阀溶。
//下面指定單引號腻脏、雙引號和注釋符號是普通字符
st.ordinaryChar('\'');
st.ordinaryChar('\"');
st.ordinaryChar('/');
String?s;
intnumberSum?=0;
intwordSum?=0;
intsymbolSum?=0;
inttotal?=0;
//nextToken方法讀取下一個Token.
//TT_EOF指示已讀到流末尾的常量鸦泳。
while(st.nextToken()?!=StreamTokenizer.TT_EOF)?{
//在調(diào)用?nextToken?方法之后,ttype字段將包含剛讀取的標(biāo)記的類型
switch(st.ttype)?{
//TT_EOL指示已讀到行末尾的常量永品。
caseStreamTokenizer.TT_EOL:
break;
//TT_NUMBER指示已讀到一個數(shù)字標(biāo)記的常量
caseStreamTokenizer.TT_NUMBER:
//如果當(dāng)前標(biāo)記是一個數(shù)字做鹰,nval字段將包含該數(shù)字的值
s?=?String.valueOf((st.nval));
System.out.println("數(shù)字有:"+s);
numberSum?++;
break;
//TT_WORD指示已讀到一個文字標(biāo)記的常量
caseStreamTokenizer.TT_WORD:
//如果當(dāng)前標(biāo)記是一個文字標(biāo)記,sval字段包含一個給出該文字標(biāo)記的字符的字符串
s?=?st.sval;
System.out.println("單詞有:?"+s);
wordSum?++;
break;
default:
//如果以上3中類型都不是鼎姐,則為英文的標(biāo)點符號
s?=?String.valueOf((char)?st.ttype);
System.out.println("標(biāo)點有:?"+s);
symbolSum?++;
}
}
System.out.println("數(shù)字有?"+?numberSum+"個");
System.out.println("單詞有?"+?wordSum+"個");
System.out.println("標(biāo)點符號有:?"+?symbolSum+"個");
total?=?symbolSum?+?numberSum?+wordSum;
System.out.println("Total?=?"+?total);
returntotal;
}catch(Exception?e)?{
e.printStackTrace();
return-1;
}finally{
if(fileReader?!=null)?{
try{
fileReader.close();
}catch(IOException?e1)?{
}
}
}
}
}