------Java培訓(xùn)、Android培訓(xùn)、iOS培訓(xùn)、.Net培訓(xùn)、期待與您交流! -------
一、File類
File類是將文件系統(tǒng)中的文件和文件夾封裝成了對象。提供了更多的屬性和行為可以對這些文件和文件夾進行操作。這些是流對象辦不到的,因為流只操作數(shù)據(jù)。File對象可以作為參數(shù)傳遞給流對象的構(gòu)造函數(shù)。File 類的實例是不可變的;也就是說,一旦創(chuàng)建,File 對象表示的抽象路徑名將永不改變。
1、File類中的方法
(1)、File類的構(gòu)造方法以及字段
1 new File(String pathname);//通過給定路徑名創(chuàng)建一個File對象2 new File(String parent, String child);//通過父目錄和文件名創(chuàng)建File對象3 new File(File parent,Stirng child);//通過把文件目錄路徑封裝對象和文件名創(chuàng)建File對象4 String separator:表示目錄分隔符,可以跨平臺使用。在 UNIX 系統(tǒng)上,此字段的值為 '/';在 Microsoft Windows 系統(tǒng)上,它為 '//'。
創(chuàng)建File文件對象的三種方式:
1 import java.io.*; 2 class FileDemo 3 { 4 public static void main(String[] args) 5 { 6 //可以將一個已存在的,或者不存在的文件或者目錄封裝成file對象 7 File file=null; 8 try 9 {10 ////創(chuàng)建File對象方式一:直接指定字符串路徑名11 file=new File("E://Demo.txt");12 13 //創(chuàng)建File對象方式二:將目錄和文件名封裝成字符串,傳參進去14 String parent="E://";15 String child="Demo.txt";16 file=new File(parent,child);17 18 //創(chuàng)建File對象方式三:將目錄封裝成文件對象和文件名創(chuàng)建對象。這種方式更加靈活,降低了文件于父目錄的關(guān)聯(lián)性19 File parent=new File("D://");20 String child="Demo.txt";21 file=new File(parent,child);22 23 }24 catch (Exception e)25 {26 e.PRintStackTrace();27 }28 }29 }(2)、File類的成員方法
1.創(chuàng)建
1 boolean createNewFile();//在指定位置上創(chuàng)建文件,如果該文件已經(jīng)存在,則不創(chuàng)建,返回false。該方法和輸出流不一樣,輸出流對象一建立就創(chuàng)建文件,而且文件已經(jīng)存在會覆蓋。2 boolean mkdir();//創(chuàng)建文件夾,只能一級3 boolean mkdirs()//創(chuàng)建多級文件夾文件夾
2.刪除
1 boolean delete();//刪除文件目錄或者文件,如果刪除失敗返回false。如果文件正字被使用,則刪除不了,返回false。2 void deleteOnExit();//在程序退出時刪除指定文件
注意:在刪除文件夾時,必須保證這個文件夾中沒有任何內(nèi)容,才可以將該文件夾用delete刪除。
Window的刪除動作是從里往外刪的。而java刪除文件不走回收站,要謹慎操作。
3.判斷
1 boolean canExecute();//判斷文件是否是可執(zhí)行文件2 boolean exists();//判斷文件是否存在3 boolean isFile();//判斷是否是文件4 boolean isDirectory();//判斷是否是目錄5 boolean isHidden();//判斷是否是隱藏文件6 boolean isAbsolute();//判斷是否是絕對路徑
注意:在判斷文件對象是否是文件或者目錄時,必須要先判斷該文件對象封裝的內(nèi)容是否存在。通過exists判斷。
4.獲取信息
1 String getName();//獲取文件名稱 2 String getPath();//獲取文件相對路徑 3 String getParent(); //獲取文件父目錄。返回的是絕對路徑中的父目錄。如果獲取的是相對路徑,返回null。如果相對路徑中有上一層目錄,那么該目錄就是返回結(jié)果。 4 String getAbsolutePath();//獲取文件絕對路徑 5 Long lastModified();//獲取最后一次文件修改時間 6 Long length();//獲取文件大小 7 File[] listRoots();//獲取全部系統(tǒng)根目錄也就是盤符 8 Stirng[] list();//獲取指定目錄下的文件以及文件夾的名稱,包含隱藏文件。調(diào)用list方法的File對象中封裝的必須是目錄,否則會產(chǎn)生NullPointerException,如果訪問的是系統(tǒng)級目錄也會發(fā)生空指針異常,如果 目錄存在但是沒有內(nèi)容,會返回一個數(shù)組,但是長度為0 9 10 String[] list(FilenameFilter filter);//獲取指定目錄中滿足指定過濾器的文件和目錄。其中FilenameFilter是個接口,里面有個方法boolean accept(File dir, String name),返回的是:當且僅當該名 稱應(yīng)該包含在文件列表中時2返回true,否則返回false。11 12 File[] listFiles()//獲取指定目錄下的文件以及文件夾的對象,有了對象就可以操作更多的方法,而list方法只能獲取當前目錄下的文件和文件夾的名稱,這是兩者最大的不同之處。同時,list()方法返回的是沒有完整路徑只有文件名(相對路徑名),而listFiles()方法返回的是所有完整路徑的的文件名(絕對路徑)。System.out.println(File)時,會調(diào)用File的toString方法,而File的toString方法會返回getPath()取得的字符串路徑。13 File[] listFiles(FilenameFilter filter);//返回抽象路徑名數(shù)組,這些路徑名表示此抽象路徑名表示的目錄中滿足指定過濾器的文件和目錄
5.重命名
1 boolean renameTo(File dest);//重命名此文件名
代碼演示:
1 import java.io.*; 2 class FileDemo 3 { 4 public static void main(String[] args) throws Exception 5 { 6 create(); 7 is(); 8 get(); 9 method();10 method_1();11 }12 public static void create()throws Exception{13 File parent=new File("E://");14 File file=new File(parent,"黑馬.txt");15 if(!file.exists())16 sop("文件是否創(chuàng)建成功:"+file.createNewFile());//指定的位置上創(chuàng)建了一個文件17 File dir=new File(parent,"黑馬//安卓//JAVA//JVAVAEE//IOS//php");18 sop("路徑是否創(chuàng)建成功"+dir.mkdirs());//創(chuàng)建多級目錄,如果創(chuàng)建一級目錄用mkdir就可以19 sop("路徑是否被刪除"+dir.delete());//多級目錄被刪除的是最里面的那個目錄,PHP文件夾被刪除了20 21 }22 public static void is()throws Exception{23 File file=new File("E://HelloJava.txt");24 sop("是否存在:"+file.exists());25 if(!file.exists())26 file.createNewFile();//指定的位置上創(chuàng)建了一個文件27 sop("是否是可執(zhí)行:"+file.canExecute()); 28 sop("是否是文件:"+file.isFile());29 sop("是否是路徑:"+file.isDirectory());30 sop("是否隱藏:"+file.isHidden());31 sop("是否是絕對路徑:"+file.isAbsolute());32 //上面的判斷返回的都是false,因為判斷的file對象根本就不存在,33 //所以切記在判斷是否是文件還是目錄的時候一定要先判斷該文件對象封裝的內(nèi)容是否存在。34 }35 public static void get()throws Exception{36 File file=new File("E://黑馬//安卓//java.txt");37 sop("文件大小:"+file.length());38 sop("文件名稱:"+file.getName());39 sop("文件相對路徑:"+file.getPath());//該方法返回的是絕對路徑中的父目錄。40 //如果獲取的是相對路徑,返回null。如果相對路徑中有上一層目錄那么該目錄就是返回結(jié)果。41 sop("文件父目錄:"+file.getParent());42 sop("文件絕對路徑:"+file.getAbsolutePath());43 sop("文件最后一次修改時間:"+file.lastModified());44 }45 public static void method()throws Exception{46 File file=new File("D://Demo.java");47 File[] dir=file.listRoots();//獲取盤符48 for(File f:dir){49 sop(f);50 }51 file=new File("D://");//必須是路徑52 String[] s=file.list();//獲取路徑下的所有文件名,包括隱藏文件,相對路徑文件名53 for(String f:s){54 sop(f);55 }56 57 File[] f=file.listFiles();//獲取路徑下的所有文件名,包括隱藏文件,絕對路徑文件名58 for(File name:f){59 sop(name);//name.getName()和list獲取的信息一樣,都是相對路徑60 }61 62 }63 public static void method_1()throws Exception{64 File file=new File("D://");//獲取D盤目錄下后綴名為.java的文件。65 String[] dir=file.list(new FilenameFilter(){66 public boolean accept(File dir,String name){//匿名內(nèi)部類,覆蓋了accept方法67 return name.endsWith(".java");68 }69 });70 for(String name:dir){71 sop(name); 72 }73 }74 public static void rename()throws Exception{75 //下面的語句可以重新命名文件名76 File f1 = new File("c://Test.java");77 File f2 = new File("d://hahah.java");78 sop("rename:"+f1.renameTo(f2));//這種情況有點像剪切文件一樣。把f1的文件剪切到了f2目錄下。79 80 }81 public static void sop(Object obj){82 System.out.println(obj);83 }84 }需求:獲取D盤目錄下后綴名為.java的文件。
1 import java.io.*; 2 class MyFilenameFilter implements FilenameFilter 3 { 4 private String suffix; 5 MyFilenameFilter(String suffix){ 6 this.suffix=suffix; 7 } 8 public boolean accept(File dir,String name){//復(fù)寫accept方法 9 return name.endsWith(suffix);10 }11 }12 class MyFilenameFilterDemo13 {14 public static void main(String[] args)throws Exception 15 {16 File file=new File("D:");17 String[] dir=file.list(new MyFilenameFilter(".txt"));//只需要往這里傳值就可以了。18 for(String name:dir){19 System.out.println(name);20 }21 }22 }需求:獲取D盤目錄下的隱藏文件。
1 import java.io.*; 2 class HiddenFile 3 { 4 public static void main(String[] args) throws Exception 5 { 6 File file=new File("C:"); 7 File[] dir=file.listFiles(new FilenameFilter(){ 8 public boolean accept(File dir,String name){ 9 return dir.isHidden();10 }11 });12 for(File name:dir){13 System.out.println(name);14 }15 }16 }2、遞歸
遞歸就是:函數(shù)自身調(diào)用自身。
什么時候用遞歸呢?
當一個功能被重復(fù)使用,而每一次使用該功能時的參數(shù)不確定,都由上次的功能元素結(jié)果來確定。
簡單說:功能內(nèi)部又用到該功能,但是傳遞的參數(shù)值不確定。(每次功能參與運算的未知內(nèi)容不確定)。
遞歸的注意事項:
1:一定要定義遞歸的條件。
2:遞歸的次數(shù)不要過多。容易出現(xiàn) StackOverflowError 棧內(nèi)存溢出錯誤。
其實遞歸就是在棧內(nèi)存中不斷的加載同一個函數(shù)。
需求:對指定目錄進行所有內(nèi)容的列出(包含子目錄中的內(nèi)容)
1 import java.io.*; 2 class FileListDemo 3 { 4 public static void main(String[] args)throws Exception 5 { 6 File file=new File("D://mystudy//java"); 7 show(file); 8 } 9 public static void show(File file){10 System.out.println("........"+file);11 //獲取指定目錄下當前的所有文件夾或者文件對象12 File[] name=file.listFiles();13 for(File dir:name){14 if(dir.isDirectory())//如果是文件夾在進去遞歸遍歷15 show(dir);16 else17 System.out.println(dir);18 }19 }20 }需求:利用遞歸求6的二進制值。
1 public class Demo{ 2 public static void main(String[] args){ 3 toBin(6); 4 } 5 6 public static void toBin(int num){ 7 if(num > 0){ 8 toBin(num/2); 9 System.out.print(num%2);10 }11 }12 }需求:利用遞歸求1到10的和。
1 public class Demo{ 2 public static void main(String[] args){ 3 int sum = getSum(10); 4 System.out.println(sum); 5 } 6 7 public static int getSum(int num){ 8 if(num == 1) 9 return 1;10 return num + getSum(num - 1);11 }12 }需求:刪除一個帶內(nèi)容的目錄。
1 import java.io.*; 2 class DeleteFile 3 { 4 public static void main(String[] args) throws Exception 5 { 6 File file=new File("E://javatest"); 7 removeDir(file); 8 } 9 public static void removeDir(File file){10 File[] dir=file.listFiles();11 for(File name:dir){12 if(name.isDirectory()){//判斷是否是路徑,如果是進入遞歸的遍歷13 removeDir(name); 14 }15 else16 System.out.println(name+"... "+name.delete()); 17 }18 System.out.println(file+"::"+file.delete());//最后把文件夾刪掉19 }20 }需求:將一個指定目錄下的java文件的絕對路徑,存儲到一個文本文件中。建立一個java文件列表文件。
思路:
1,對指定的目錄進行遞歸。
2,獲取遞歸過程所以的java文件的路徑。
3,將這些路徑存儲到集合中。
4,將集合中的數(shù)據(jù)寫入到一個文件中。
1 import java.io.*; 2 import java.util.*; 3 class JavaFileList 4 { 5 public static void main(String[] args) throws Exception 6 { 7 File file=new File("E://javatest"); 8 List<File> list=new ArrayList<File>(); 9 fileToList(file,list);10 listToFile(list);11 }12 //把符合條件的目錄存放到List集合中13 public static void fileToList(File dir,List<File> list){14 File[] file=dir.listFiles();15 for(File name:file){16 if(name.isDirectory())17 fileToList(name,list);18 else{19 if(name.getName().endsWith(".java"))//文件名為.java的添加進集合中20 list.add(name);21 }22 }23 }24 25 //集合中存放的數(shù)據(jù)寫到指定文件內(nèi)26 public static void listToFile(List<File> list)throws IOException{27 BufferedWriter bfw=new BufferedWriter(new FileWriter("E://黑馬.txt"));28 for(File name:list){29 bfw.write(name.getAbsolutePath());//獲取文件的絕對路徑名30 bfw.newLine();31 bfw.flush();32 }33 bfw.close();34 }35 }需求:將指定目錄下所有.java文件拷貝到另一個目的中,并將擴展名改為.txt
1 //編寫程序,將指定目錄下所有.java文件拷貝到另一個目的中,并將擴展名改為.txt 2 import java.io.*; 3 class CopyFile 4 { 5 public static void main(String[] args)throws Exception 6 { 7 FileInputStream fis=null; 8 FileOutputStream fos=null; 9 File src=new File("E://javatest//12");10 File des=new File("E://安卓");11 if(!des.exists())12 des.mkdir();13 String[] dir=src.list(new FilenameFilter(){14 public boolean accept(File dir,String name){15 return name.endsWith(".java");16 }17 });18 19 for(String name:dir){20 System.out.println(name);21 fis=new FileInputStream(new File(src,name));22 fos=new FileOutputStream(new File(des,name.replace(".java",".txt")));23 int len=0;24 byte[] buf=new byte[1024];25 while ((len=fis.read(buf))!=-1)26 {27 fos.write(buf,0,len);28 }29 }30 fis.close();31 fos.close();32 } 33 }二、Properties類
繼承體系:
Map集合
|--Hashtable
|--Properties
用于屬性配置文件,鍵和值都是字符串類型。
Properties值Hashtable的子類。也就是說它具備map集合的特點。而且它里面存儲的鍵值對都是字符串,沒有泛型定義。是集合中和IO技術(shù)相結(jié)合的結(jié)合容器。該對象的特點就是:可以用于鍵值對形式的配置文件。那么在加載數(shù)據(jù)時需要數(shù)據(jù)有固定格式:鍵=值。
特點:1:可以持久化存儲數(shù)據(jù)。2:鍵值都是字符串。3:一般用于配置文件。
1、Properties類中常用方法
(1)、設(shè)置鍵和值。相當與Map集合中的put方法
1 Object setProperty(String key,String value);//添加元素
(2)、獲取
1 String getProperty(String key);//根據(jù)鍵獲取值2 Set<String> stringPropertyNames();//返回屬性列表鍵集,存入Set集合
(3)、加載和存入流
1 void load(InputStream in);//將字節(jié)讀取流中的數(shù)據(jù)加載進集合中2 void load(Reader reader);//JDK1.6才有,將字符讀取流加載進集合3 void store(OutputStream out,String comments);//將屬性列表(鍵值對)寫入輸出流。comments屬性列表的描述。可以不寫。4 void store(Writer writer,String comments);//JDK1.6才有。對應(yīng)load(Reader)將屬性列表(鍵值對)寫入輸出流。comments屬性列表的描述。5 void list(PrintStream out);//將屬性輸出到輸出流中6 void list(PrintWriter);//將屬性輸出到輸出流中
代碼演示:
1 import java.util.*; 2 import java.io.*; 3 class PropertiesDemo 4 { 5 public static void main(String[] args)throws Exception 6 { 7 Properties pro=new Properties(); 8 pro.setProperty("6","小明"); 9 pro.setProperty("2","老王");10 pro.setProperty("3","趙四");11 pro.setProperty("5","黑馬");12 method_1(pro);13 method_2();14 method_3();15 }16 public static void method_1(Properties pro){17 System.out.println(pro.getProperty("3"));18 //返回Set集合中存放的是Properties的鍵集19 Set<String> set=pro.stringPropertyNames();20 for(String key:set){21 System.out.println(key+"::"+pro.getProperty(key));22 }23 }24 //模擬load方法25 public static void method_2()throws Exception{26 Properties pro=new Properties();27 BufferedReader br=new BufferedReader(new FileReader("info.txt"));28 String line=null;29 while ((line=br.readLine())!=null)30 {31 String[] arr=line.split("="); 32 pro.setProperty(arr[0],arr[1]);33 34 }35 System.out.println(pro);36 }37 //對已有的配置文件中的信息進行修改38 //讀取這個文件。并將這個文件中的鍵值數(shù)據(jù)存儲到集合中。再通過集合對數(shù)據(jù)進行修改。load方法39 //再通過流將修改后的數(shù)據(jù)存儲到文件中stroe方法40 public static void method_3()throws Exception{41 Properties pro=new Properties();42 FileReader fr=new FileReader("info.txt"); 43 pro.load(fr);44 pro.setProperty("1","會更好");45 FileWriter fw=new FileWriter("info.txt");46 pro.store(fw,"");47 System.out.println(pro);48 }49 }需求:限制程序運行次數(shù)。當運行次數(shù)到達5次時,給出,請您注冊的提示。并不再讓該程序執(zhí)行。
思路:
1、應(yīng)該有計數(shù)器。每次程序啟動都需要計數(shù)一次,并且是在原有的次數(shù)上進行計數(shù)。
2、計數(shù)器就是一個變量。突然冒出一想法,程序啟動時進行計數(shù),計數(shù)器必須存在于內(nèi)存并進行運算。可是程序一結(jié)束,計數(shù)器消失了。那么再次啟動該程序,計數(shù)器又重新被初始化了。 而我們需要多次啟動同一個應(yīng)用程序,使用的是同一個計數(shù)器。這就需要計數(shù)器的生命周期邊長,從內(nèi)存存儲到硬盤文件中。
3、如何使用這個計數(shù)器呢?首先,程序啟動時,應(yīng)該先讀取這個用于記錄計數(shù)器信息的配置文件。獲取上一次計數(shù)器次數(shù)。并進行使用次數(shù)的判斷。其次,對該次數(shù)進行自增,并自增后的次數(shù)重新存儲到配置文件中。
4、文件中的信息該如何進行存儲并體現(xiàn)。直接存儲次數(shù)值可以,但是不明確該數(shù)據(jù)的含義。所以起名字就變得很重要。這就有了名字和值的對應(yīng),所以可以使用鍵值對。可是映射關(guān)系map集合搞定,又需要讀取硬盤上的數(shù)據(jù),所以map+io=properties。
1 import java.io.*; 2 import java.util.*; 3 class RunCount{ 4 public static void main(String[] args)throws IOException{ 5 File file=new File(“count.ini”); 6 if(!file.exists()) 7 file.createNewFile(); 8 FileReader fr=new FileReader(file); 9 Properties pro=new Properties();10 pro.load(fr);11 int count=0;12 String value=pro.getProperty(“time”);13 if(value!=null){14 count=Integet.parseInt(value);15 if(count>=5)16 throw new RuntimeException(“使用次數(shù)已到”);17 }18 count++;19 pro.setProperty(“time”,Integer.toString(count));//String.valueOf(count) 把int型轉(zhuǎn)成字符串20 FileWriter fw=new FileWriter(file);21 pro.store(fw,””);22 fr.close();23 fw.close();24 }25 }三、IO包中其他類
1、PrintStream、PrintWriter打印流
打印流最厲害的地方就是有很多打印方法可供我們選擇。
PrintStream繼承體系
OutputStream
|--FilterOutputStream
|--PrintStream
PrintWriter繼承體系
Writer
|--PrintWriter
PrintWriter與PrintStream:可以直接操作輸入流和文件。
(1)、PrintStream字節(jié)打印流
PrintStream為其他輸出流添加了功能,使它們能夠方便地打印各種數(shù)據(jù)值并保持數(shù)據(jù)的表示形式。與其他輸出流不同,PrintStream永遠不會拋出IOException。
PrintStream打印的所有字符都使用平臺的默認字符編碼轉(zhuǎn)換為字節(jié)。在需要寫入字符而不是寫入字節(jié)的情況下,應(yīng)該使用PrintWriter類。
PrintStream構(gòu)造函數(shù),接收三種類型的值:無空參構(gòu)造函數(shù)
1. 字符串路徑
2. File對象
3. 字節(jié)輸出流
前兩個都JDK1.5版本才出現(xiàn)。而且在操作文本文件時,可指定字符編碼了。
構(gòu)造函數(shù):
1 new PrintStream(File file);//創(chuàng)建具有指定文件且不帶自動行刷新的新打印流2 new PrintStream(File file,String csn);//創(chuàng)建具有指定文件名稱和字符集且不帶自動行刷新的新打印流3 new PrintStream(OutputStream out);//創(chuàng)建新的打印流4 new PrintStream(OutputStream out,boolean autoFlush);//創(chuàng)建新的打印流,并且可以自帶自動刷新5 new PrintStream(OutputStream out,boolean autoFlush,String encoding);//創(chuàng)建新的打印流,既能自動刷新又能指定編碼表6 new PrintStream(String fileName);//創(chuàng)建具有指定文件名稱且不帶自動行刷新的新打印流7 new PrintStream(String fileName, String csn) ;//創(chuàng)建具有指定文件名稱且能指定編碼表的新打印流
代碼演示:
1 import java.io.*; 2 class PrintStreamDemo 3 { 4 public static void main(String[] args) throws IOException 5 { 6 File file=new File("安卓.txt"); 7 if(!file.exists()) 8 file.createNewFile(); 9 PrintStream out=new PrintStream(new FileOutputStream(file),true);10 //write(int b)方法只寫最低8位11 //print方法將7878先變成字符串保持原樣將數(shù)據(jù)打印到目的地12 out.println(7878);//運行結(jié)果:787813 }14 }(2)、PrintWriter字符打印流
PrintWriter構(gòu)造函數(shù),接收四種類型的值:(重點)無空參
1.字符串路徑
2.File對象
3.字節(jié)輸出流
4.字符輸出流
構(gòu)造方法:
1 new PrintWriter(File file);//使用指定文件創(chuàng)建不具有自動行刷新的新 PrintWriter.2 new PrintWriter(File file,String csn);//創(chuàng)建具有指定文件和字符集且不帶自動刷行新的新 PrintWriter.3 new PrintWriter(OutputStream out);// 創(chuàng)建不帶自動行刷新的新 PrintWriter。4 new PrintWriter(OutputStream out, boolean autoFlush)// 創(chuàng)建打印流,并且可以自動刷新。5 new PrintWriter(Writer out);// 創(chuàng)建不帶自動行刷新的新 PrintWriter6 PrintWriter(Writer out, boolean autoFlush)//創(chuàng)建自動行刷新的新 PrintWriter7 new PrintWriter(String fileName, String csn) ;//創(chuàng)建具有指定文件名稱和字符集且不帶自動行刷新的新 PrintWriter
方法中直接操作文件的第二參數(shù)是編碼表。
直接操作輸出流的,第二參數(shù)是自動刷新。
1 import java.io.*; 2 class PrintWriterDemo 3 { 4 public static void main(String[] args) throws IOException 5 { 6 File file=new File("安卓.txt"); 7 if(!file.exists()) 8 file.createNewFile(); 9 PrintWriter out=new PrintWriter(new FileWriter(file),true);10 //write(int b)方法只寫最低8位11 //print方法將7878先變成字符串保持原樣將數(shù)據(jù)打印到目的地12 out.println(78);//運行結(jié)果:7813 }14 }需求:將鍵盤錄入的數(shù)據(jù)寫入到指定的文件中。
1 import java.io.*; 2 class PrintWriterDemo 3 { 4 public static void main(String[] args)throws IOException 5 { 6 BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); 7 // PrintWriter out=new PrintWriter(new FileOutputStream("黑馬.ini",true)); 8 PrintWriter out=new PrintWriter(new FileWriter("黑馬.txt"),true);//true代表的是自動刷新 9 String line=null;10 while ((line=br.readLine())!=null)11 {12 if("over".equals(line))13 break;14 out.println(line);//Println方法代表是是輸出并且自動換行15 }16 out.close();17 }18 }2、SequenceInputStream 序列流
將多個讀取流合并成一個讀取流,實現(xiàn)數(shù)據(jù)合并。
表示其他輸入流的邏輯串聯(lián)。它從輸入流的有序集合開始,并從第一個輸入流開始讀取,直到到達文件末尾,接著從第二個輸入流讀取,依次類推,直到到達包含的最后一個輸入流的文件末尾為止。這樣做,可以更方便的操作多個讀取流,其實這個序列流內(nèi)部會有一個有序的集合容器,用于存儲多個讀取流對象。
該對象的構(gòu)造函數(shù)參數(shù)是Enumeration,想要獲取Enumeration,需要有Vector集合。但是Vector集合效率太低,已經(jīng)被ArrayList所取代。這時候可以用Collections工具類中的Collections.enumeration()該方法返回的就是Enumeration接口。這樣會大大提高效率的。
構(gòu)造函數(shù):
1 new SequenceInputStream(Enumeration<? extends InputStream> e);//該構(gòu)造函數(shù)適合多個讀取字節(jié)流對象操作2 new SequenceInputStream(InputStream s1, InputStream s2);//該構(gòu)造函數(shù)適合兩個讀取字節(jié)流對象操作
需求:將1.txt、2.txt、3.txt文件中的數(shù)據(jù)合并到一個文件中。
1 import java.io.*; 2 import java.util.*; 3 class SequenceInputStreamDemo 4 { 5 public static void main(String[] args)throws IOException 6 { 7 method_1(); 8 } 9 public static void method_1()throws IOException{10 //定義Vector對象用來存儲字節(jié)讀取流對象11 Vector<FileInputStream> v=new Vector<FileInputStream>();12 v.add(new FileInputStream("E://1.txt"));13 v.add(new FileInputStream("E://2.txt"));14 v.add(new FileInputStream("E://3.txt"));15 16 //用Vector對象中的elements方法獲取Enumeration17 Enumeration<FileInputStream> en=v.elements();18 19 //創(chuàng)建SequenceInputStream對象,和流關(guān)聯(lián)20 SequenceInputStream sis=new SequenceInputStream(en);21 FileOutputStream fw=new FileOutputStream("E://4.txt");22 int len=0;23 byte[] buf=new byte[1024];24 while ((len=sis.read(buf))!=-1)25 {26 fw.write(buf,0,len);27 }28 sis.close();29 fw.close();30 }31 //上面用的Vector對象。這個對象比較低效,已經(jīng)被ArrayList所替代了。所以下面我們用ArrayList集合來操作。32 public static void method_2()throws IOException{33 //創(chuàng)建ArrayList集合容器用來存放字節(jié)讀取流對象,該容器效率比Vector集合效率高34 Collection<FileInputStream> coll=new ArrayList<FileInputStream>();35 //循環(huán)獲取FileInputStream對象,添加進ArrayList集合中。36 for (int x=1;x<4 ;x++ )37 {38 coll.add(new FileInputStream("E://"+x+".txt"));39 }40 //用Collections工具類中的enumeration方法獲取Enumeration接口41 Enumeration<FileInputStream> en=Collections.enumeration(coll);42 //創(chuàng)建SequenceInputStream對象,和流關(guān)聯(lián)43 SequenceInputStream sis=new SequenceInputStream(en);44 FileOutputStream fos=new FileOutputStream("E://4.txt");45 int len=0;46 byte[] buf=new byte[1024];47 while ((len=sis.read(buf))!=-1)48 {49 fos.write(buf,0,len);50 }51 fos.close();52 sis.close();53 }54 }需求:對文件的切割。
1 import java.io.*; 2 import java.util.*; 3 class SplitDemo 4 { 5 public static void main(String[] args) throws IOException 6 { 7 File file=new File("D://年輪.mp3"); 8 //用讀取流關(guān)聯(lián)源文件 9 FileInputStream fis=new FileInputStream(file);10 FileOutputStream fos=null;11 //創(chuàng)建目標文件12 File dir=new File("E://年輪");13 if(!dir.exists())14 dir.mkdir();15 int len=0;16 //定義一個計數(shù)器用來記錄切割后碎片的文件名17 int count=1;18 //定義一個1M的緩沖區(qū)19 byte[] buf=new byte[1024*1024];20 while ((len=fis.read(buf))!=-1)21 {22 fos=new FileOutputStream(new File(dir,(count++)+".part"));23 fos.write(buf,0,len);24 }25 //切割文件時,必須記錄住被切割文件的名稱,以及切割出來碎片文件的個數(shù),以方便于合并。26 //這個信息為了進行描述,使用鍵值對的方式,用到了properties對象。27 Properties pro=new Properties();28 //將被切割文件的信息保存到pro集合中29 pro.setProperty("Count",Integer.toString(count));30 pro.setProperty("Name",file.getName());31 fos=new FileOutputStream(new File(dir,count+".properties"));32 //將pro集合中的數(shù)據(jù)存儲到文件中33 pro.store(fos,"");34 fos.close();35 fis.close();36 }37 }需求:從上例讀取配置信息,并合并文件
1 import java.io.*; 2 import java.util.*; 3 class HeBingFile 4 { 5 public static void main(String[] args)throws IOException 6 { 7 FileInputStream fis=new FileInputStream("E://年輪//6.properties"); 8 Properties pro=new Properties(); 9 pro.load(fis);10 //獲取配置信息中切割的個數(shù)11 int count=Integer.parseInt(pro.getProperty("Count"));12 //獲取配置信息中別切割的文件名13 String name=pro.getProperty("Name");14 // System.out.println(name); 15 File file=new File("E://年輪");16 //將碎片文件和流對象關(guān)聯(lián)并存儲到集合中17 ArrayList<FileInputStream> al=new ArrayList<FileInputStream>();18 //獲取該目錄下的所有碎片文件,并添加到集合中19 for (int x=1;x<count ; x++)20 {21 al.add(new FileInputStream(new File(file,x+".part")));22 }23 Enumeration<FileInputStream> en=Collections.enumeration(al);24 SequenceInputStream sis=new SequenceInputStream(en); 25 FileOutputStream fos=new FileOutputStream("E://"+name);26 int len=0;27 byte[] buf=new byte[1024];28 while ((len=sis.read(buf))!=-1)29 {30 fos.write(buf,0,len);31 }32 33 }34 }3、ObjectInputStream、ObjectOutputStream 操作對象的流
被操作的對象需要實現(xiàn)Serializable接口。類通過實現(xiàn)java.io.Serializable接口以啟用序列化功能,Serializable只是一個標記接口。
Serializable:用于啟動對象的序列化功能,可以強制讓指定類具備序列化功能,該接口中沒有成員,這是一個標記接口。這個標記接口用于給序列化類提供UID。這個uid是依據(jù)類中的成員的數(shù)字簽名進行運行獲取的。如果不需要自動獲取一個uid,可以在類中,手動指定一個名稱為serialVersionUID id號。依據(jù)編譯器的不同,或者對信息的高度敏感性。最好每一個序列化的類都進行手動顯示的UID的指定。
注意:靜態(tài)數(shù)據(jù)不能被序列化,因為靜態(tài)數(shù)據(jù)不在堆內(nèi)存中,是存儲在靜態(tài)方法區(qū)中。
如何將非靜態(tài)的數(shù)據(jù)不進行序列化?用transient 關(guān)鍵字修飾此變量即可。
ObjectInputStream類中方法:
1 new ObjectInputStream(InputStream in);// 創(chuàng)建從指定 InputStream 讀取的 ObjectInputStream 2 int available();//返回可以不受阻塞地讀取的字節(jié)數(shù)。 3 boolean readBoolean();//讀取一個 boolean 值 4 byte readByte();//讀取一個 8 位的字節(jié) 5 char readChar();//讀取一個 16 位的 char 值 6 double readDouble();//讀取一個 64 位的 double 值 7 float readFloat();//讀取一個 32 位的 float 值 8 int readInt();//讀取一個 32 位的 int 值 9 long readLong();//讀取一個 64 位的 long 值10 short readShort();//讀取一個 16 位的 short 值11 Object readObject();// 從 ObjectInputStream 讀取對象12 String readUTF();//讀取 UTF-8 修改版格式的 String
ObjectOutputStream類中的方法:
1 new ObjectOutputStream(OutputStream Out);// 創(chuàng)建寫入指定 OutputStream 的 ObjectOutputStream 2 void writeBoolean(boolean val);//寫入一個 boolean 值 3 void writeByte(int val);// 寫入一個 8 位字節(jié) 4 void writeBytes(String str);//以字節(jié)序列形式寫入一個 String 5 void writeChar(int val);//寫入一個 16 位的 char 值 6 void writeDouble(double val);//讀取一個 64 位的 double 值 7 void writeFloat(float val);//寫入一個 32 位的 float 值 8 void writeInt(int val);// 寫入一個 32 位的 int 值 9 void writeLong(long val);//寫入一個 64 位的 long 值10 void writeObject(Object obj);//將指定的對象寫入 ObjectOutputStream11 void writeShort(int val);//寫入一個 16 位的 short 值12 void writeUTF(String str);// 以 UTF-8 修改版格式寫入此 String 的基本數(shù)據(jù)
代碼演示:
Person.java文件
1 import java.io.*; 2 //實現(xiàn)Serializable接口以啟用序列化功能 3 class Person implements Serializable 4 { 5 //用于給被序列化的類加入ID號,用于判斷類和對象是否是同一個版本 6 //此時,再將Person類中屬性修飾符修改為public,也不會出現(xiàn)任何異常 7 private static final long serialVersionUID = 2332; 8 private String name; 9 // private transient String name;//用transient修飾后name將不會進行序列化10 private int age;11 Person(String name,int age){12 this.name=name;13 this.age=age;14 }15 public void setName(String name){16 this.name=name;17 }18 public String getName(){19 return name;20 }21 public void setAge(int age){22 this.age=age;23 }24 public int getAge(){25 return age;26 }27 public String toString(){28 return name+"::"+age;29 }30 }ObjectOutputStreamDemo.java文件
1 import java.io.*; 2 class ObjectOutputStreamDemo 3 { 4 public static void main(String[] args)throws Exception 5 { 6 // writeObj(); 7 readObj(); 8 } 9 public static void writeObj()throws IOException{10 ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("obj.object"));11 oos.writeObject(new Person("黑馬",120));12 oos.close();13 }14 public static void readObj()throws Exception{15 ObjectInputStream ois=new ObjectInputStream(new FileInputStream("obj.object"));16 Person p=(Person)ois.readObject();17 System.out.println(p);//運行結(jié)果:黑馬::12018 ois.close();19 }20 }4、管道流
PipedInputStream和PipedOutputStream:輸入輸出可以直接進行連接,通過結(jié)合線程使用。
1 import java.io.*; 2 class Read implements Runnable 3 { 4 private PipedInputStream in; 5 Read(PipedInputStream in){ 6 this.in=in; 7 } 8 public void run(){ 9 byte[] buf=new byte[1024];10 try11 {12 System.out.println("讀取前。。沒有數(shù)據(jù)阻塞");13 int len=in.read(buf);//read方法是阻塞式方法,沒有收到數(shù)據(jù)前就是等待14 System.out.println("讀到數(shù)據(jù)。。阻塞結(jié)束");15 System.out.println(new String(buf,0,len));16 17 }18 catch (IOException e)19 {20 System.out.println(e);21 }22 finally{23 try24 {25 in.close();26 }27 catch (IOException e)28 {29 System.out.println("關(guān)閉失敗");30 }31 }32 33 }34 }35 class Write implements Runnable36 {37 private PipedOutputStream out;38 Write(PipedOutputStream out){39 this.out=out;40 }41 public void run(){42 try43 {44 System.out.println("開始寫入數(shù)據(jù),等待6秒后。");45 Thread.sleep(6000);//讓線程等待6秒后繼續(xù)執(zhí)行46 out.write("我是管道流".getBytes());47 }48 catch (Exception e)49 {50 System.out.println(e);51 }52 finally53 {54 try55 {56 out.close();57 }58 catch (IOException e)59 {60 System.out.println("關(guān)閉失敗");61 }62 } 63 64 }65 }66 67 class PipedStreamDemo 68 {69 public static void main(String[] args) throws IOException70 {71 PipedInputStream in=new PipedInputStream();72 PipedOutputStream out=new PipedOutputStream();73 in.connect(out);//管道輸入流連接到管道輸出流74 new Thread(new Read(in)).start();75 new Thread(new Write(out)).start();76 }77 }5、RandomaccessFile 隨機訪問文件
隨機訪問文件,自身已經(jīng)具備了讀和寫的方法。該類不算是IO體系中的子類,而是直接繼承自O(shè)bject。但是它是IO包中的成員,是因為它具備了讀寫功能,內(nèi)部其實封裝了一個數(shù)組,而且通過指針對數(shù)組的元素進行操作。可以通過getFilePointer獲取指針位置,同時也可以通過seek改變指針的位置。其實完成讀寫的原理就是內(nèi)部封裝了字節(jié)輸入流和輸出流。
通過構(gòu)造函數(shù)可以看出,該類只能操作文件,而且操作文件還有模式:只讀r,讀寫rw等。
如果模式為只讀r,則不會創(chuàng)建文件,會去讀取一個已經(jīng)存在文件。如果該文件不存在,則會出現(xiàn)異常。
如果模式為rw,操作的文件不存在,會自動創(chuàng)建。如果存在則不會覆蓋。
特點:
1.該對象即可讀取,又可寫入。
2.該對象中的定義了一個大型的byte數(shù)組,通過定義指針來操作這個數(shù)組。
3.可以通過該對象的getFilePointer()獲取指針的位置,通過seek()方法設(shè)置指針的位置。
4.該對象操作的源和目的必須是文件。
5.其實該對象內(nèi)部封裝了字節(jié)讀取流和字節(jié)寫入流。
注意:實現(xiàn)隨機訪問,最好是數(shù)據(jù)有規(guī)律。
1 import java.io.*; 2 class RandomAccessFileDemo 3 { 4 public static void main(String[] args) throws IOException 5 { 6 //writeFile_2(); 7 //readFile(); 8 } 9 public static void readFile()throws IOException10 {11 RandomAccessFile raf = new RandomAccessFile("ran.txt","r");12 //調(diào)整對象中指針。13 //raf.seek(8*1);14 //跳過指定的字節(jié)數(shù)15 raf.skipBytes(8);16 byte[] buf = new byte[4];17 raf.read(buf);18 String name = new String(buf);19 int age = raf.readInt();20 System.out.println("name="+name);21 System.out.println("age="+age);22 raf.close();23 }24 public static void writeFile_2()throws IOException25 {26 RandomAccessFile raf =new RandomAccessFile("ran.txt","rw");27 //往指定位置寫入數(shù)據(jù)28 raf.seek(8*0);29 raf.write("小明".getBytes());30 raf.writeInt(103);31 raf.close();32 }33 public static void writeFile()throws IOException34 {35 //如果文件不存在,則創(chuàng)建,如果文件存在,不創(chuàng)建36 RandomAccessFile raf = new RandomAccessFile("ran.txt","rw");37 raf.write("李四".getBytes());38 raf.writeInt(97);39 raf.write("王五".getBytes());40 raf.writeInt(99);41 raf.close();42 }43 }6、DataInputStream與DataOutputStream
可以用于操作基本數(shù)據(jù)類型的數(shù)據(jù)的流對象。
1 import java.io.*; 2 class DataStreamDemo 3 { 4 public static void main(String[] args)throws IOException 5 { 6 // write(); 7 read(); 8 } 9 public static void read()throws IOException{10 DataInputStream dis=new DataInputStream(new FileInputStream("data.txt"));11 //輸入流中讀取基本數(shù)據(jù)類型12 int num=dis.readInt();13 double d=dis.readDouble();14 boolean b=dis.readBoolean();15 //讀取一個UTF-8編碼的字符串16 String s=dis.readUTF();17 System.out.println("num="+num);18 System.out.println("d="+d);19 System.out.println("b="+b);20 System.out.println("s="+s);21 }22 public static
新聞熱點
疑難解答