1? ? ? IONo18
【
IO:Input??? Output
在程序運行的過程中,可能需要對一些設備進行數據的讀取操作,比如:對磁盤進行讀寫操作。
IO框架就是用于對設備進行讀寫操作,在學習對象之前,我們首先要學習一個非常重要的類:File類
IO框架
File類
概述:用于描述存在或不存在的文件或文件夾
絕對路徑:完整的路徑名
相對路徑:相對于當前所在的路徑
IO流:
主要用于實現設備之間的數據傳輸
設備:內存、磁盤、網絡、鍵盤、鼠標…….
?《在Java中,IO流的方向是相對內存而言的》
設備之間的數據傳輸通過流來實現
流的分類,按照流向、功能可以分為以下三種:
1:按方向分類:輸入流、輸出流
在java中,IO流的方向是相對內存而言的
2:按單位分類:字節流、字符流
1)在磁盤上存儲數據都是以二進制的形式來保存,但是每一位只能保存兩個狀態,為了能夠表示足夠多的狀態,所以我們以8位為一個單位,叫做字節,所以在內存中保存數據的最小單位是字節
在程序中數據存儲的最小單位是字節(byte)
2)磁盤上保存數據都是以二進制形式,如果需要在磁盤上保存一些字符(a,b),就需要使用編碼表先將子符進行編碼,再將對應的編碼保存在磁盤上,不同的編碼表保存數據所用的字節數是不同的,通過是在1~3個字節來保存,如果以字節為單位處理數據,那么就有可能出現數據不完整和亂碼的情況,所以在處理文本數據的時候建議使用字符流。
總結:如果處理的數據是文本數據,一般就用字符流,其他數據一般使用字節流(字節流也能操作文本數據)。
3:按功能分為:節點符、過濾流(處理流)
在IO框架中有四個頂層基類:
1:字符流:Reader?? Writer
2:字節流:InputStream??OutputStream
】
自譯:【1:三種文件表示形式:
File f = new File("g:/day18.txt")
File f2 = new File("g:\\prop.txt");
File f3 = new File("g:"+File.separator+"file.txt");
f3.exists():判斷文件是否存在f3.createNewFile();//創建這個對象所表示的文件f.delete();//用于刪除指定的文件
】
【2:創建實際的目錄
File f2 = new File("g:/practice2");??? f2.mkdir();
3:生成一個生層次的目錄結構:Filefolder = new File("g:/a/b/d/c/d/e/f/g");?? folder.mkdirs();
】
【4:返回目錄下所有的文件
File[] files = folder.listFiles();
for (File file : files) {//循環遍歷這個文件數組
System.out.println(file.getPath());? //打印出每個文件的路徑
Date d=newDate();
d.setTime(file.lastModified());??? //最后一次修改的時間
System.out.println(file.getName()+","+d.toString());//打印每個文件的名字
}
】
5過濾某文件夾下的文件:
【
//后綴過濾器(文件過濾器)
class SuffixFilter implements FileFilter {
@Override
//是一個回調方法,在listFiles時回調
publicboolean accept(File file) {
//如果文件以.zip結尾并且不是目錄
if(file.getName().endsWith(".zip") && file.isFile()) {
returntrue; //返回true,表示接受這個文件,保留下來
}
returnfalse; //返回false,表示不接受,過濾掉
}
}
調用:
File folder = new File("g:/" + File.separator +"千鋒課堂軟件");
//列出....下文件,過濾標準是從參數傳入的后綴過濾器對象
File[]files = folder.listFiles(new SuffixFilter());
for(File f : files) { //遍歷過濾后的文件數組
System.out.println(f.getName());
}
使用匿名內部類實現文件過濾:
File folder = newFile("g:"+File.separator+"手頭查詢文檔");
File[]files = folder.listFiles(new FileFilter() {
//這個方法會在listFiles時被回調,來判斷每個文件是保留還是丟棄
@Override
publicboolean accept(File file) {
//如果以"張"開頭并且是文件
if(file.getName().startsWith("大話")&&file.isFile()){
returntrue;?? //保留
}
returnfalse;?? //否則過濾掉
}
});
for(File file : files) {
System.out.println(file.getName());
}
】
6:遞歸調用遍歷文件,區分文件和目錄
【
Filefolder = new File("g:"+File.separator+"a");
showAll(folder);
}
//如果是目錄,顯示目錄中所有文件,如果是一個文件,直接打印名字
privatestatic void showAll(File file) {
if(file.isFile()){? //如果是文件
System.out.println(file.getName());//打印出名字
}else{//如果是目錄
File[]files = file.listFiles();?? //列出所有文件、目錄
for(File f : files) {//遍歷每個文件、目錄
showAll(f);?????? //對每個文件、目錄再進行遞歸調用
}
}
}
】
7:文件的復制
【
FileInputStream fis = newFileInputStream("G:/杜維瀚-我就喜歡你這樣的丫頭.zip");
FileOutputStreamfos = new FileOutputStream("G:/徐杜維瀚-我就喜歡你這樣的丫頭.zip");
intn = 0;
while((n = fis.read()) != -1) { //每次讀一個字節//從a文件中讀,寫到b文件中
fos.write(n);//寫到另一個文件中
System.out.println("復制完成!");
fos.close();
fis.close();
}
帶緩存形式復制文件
FileInputStream fis = newFileInputStream("g:/韓紅-一個人.zip");
FileOutputStreamfos = new FileOutputStream("g:/有韓紅-一個人.zip");
byte[]buf = new byte[1024];??? //緩沖
intn= 0;?? //保存返回信息
//這種方式拷貝1024個字節只操作一次磁盤,效率較高
while((n=fis.read(buf))!=-1){//循環讀數據到緩存中
fos.write(buf,0, n);??? //將緩存中有效數據寫到文件中
}
fos.close();
fis.close();
】
【
//方式一
File file = newFile("g:\\demo.txt");
方式二
Filefile2 = new File("g:\\", "demo.txt");
//方式三
File dir = newFile("g:\\filetest");
File file3 = new File(dir,"demo.txt");
//File的成員字段
//路徑分隔符,不同系統的路徑分隔符可能不同,通過該靜態常量可以獲取到和系統相關的路徑分隔符
System.out.println(File.pathSeparator);
System.out.println(File.pathSeparatorChar);
//名稱分隔符,不同的系統名稱分隔符不同
//注意:在windows下,應該使用“\”(反斜杠),但實際正反都支持
System.out.println(File.separator);
System.out.println(File.separatorChar);
Filefile = new File("G:\\filetest");
/*???? //獲取指定文件夾下的所有子文件(夾)的名稱
String[] fileNames =file.list();
for (String fileName :fileNames) {
System.out.println(fileName);
}
//獲取指定文件夾下所有的子文件(夾)的File對象
File[] files =file.listFiles();
for (File f : files) {
System.out.println(f.getAbsolutePath());
}*/
】
【
getName()獲取文件名
listRoots()獲取所有磁盤的根目錄(靜態方法)
getTotalSpace()獲取當前所在磁盤的總大小(單位:字節)
《//磁盤的總大小
System.out.println(file3.getTotalSpace()/1024/1024/1024+"GB");》
getFreeSpace()獲取當前所在磁盤的剩余空間(單位:字節)
lastModified()獲取最后修改時間(1970到現在所經過的毫秒值)
《SimpleDateFormatsdf = new SimpleDateFormat("yyyy年MM月dd日HH:mm:ss");
System.out.println(sdf.format(file3.lastModified()));》
length()獲取文件的大小(單位:字節)
getParent()獲取父目錄的路徑
getPath()獲取相對路徑
getAbsolutePath()獲取絕對路徑
】
【
delete()刪除文件或文件夾
mkdirs()創建多級目錄
mkdir()創建文件夾(創建成功,返回true,否則返回false)
createNewFile()創建文件(如果文件不存在,就創建,如果存在,就不創建并返回false
】
【
isHidden()判斷是否是隱藏文件
isFile()判斷是否是文件
isDirectory()判斷是否是目錄
exists()判斷是否存在
】
【
renameTo(Filedest)移動并改名
】
【
listFiles(FileFilterfilter)
listFiles(FilenameFilterfilter)
list(FilenameFilterfilter)
FilenameFilter:文件名過濾器接口
FileFilter:文件過濾器接口
《
文件名過濾器,實現接口
classMyFileNameFilter implements FilenameFilter{
/**
*文件過濾的規則
*返回值得意思就是判斷指定的文件是否通過過濾
*如果是true代表通過過濾
*/
@Override
public boolean accept(File dir, Stringname) {
System.out.println(dir.getAbsolutePath());
returnname.endsWith(".txt");
}
}
File[] files =file.listFiles(new MyFileNameFilter());
System.out.println("數組內容");
for (File f : files) {
System.out.println(f.getAbsolutePath());
}
匿名內部類文件過濾器
File[] files =file.listFiles(new FileFilter() {
@Override
public booleanaccept(File file) {
System.out.println(file.getAbsolutePath());
return file.getName().endsWith(".txt");
}
});
System.out.println("數組內容");
for (File f : files) {
System.out.println(f.getAbsolutePath());
}
》
】
【
//2.輸出一個文件夾(包括子目錄)中的所有文件的名稱(使用File和遞歸來實現)
public class Ex1 {
public static void main(String[] args){
File dir = newFile("g:\\anjavaworkspaseTest");
bianLi(dir);
}
/**
*遍歷輸出指定文件中的文件(夾)的名稱
* @param dir
*/
private static void bianLi(File dir){
System.out.println(dir.getName());
//獲取文件夾中的所有子文件(夾)
File[] files = dir.listFiles();
for (File f : files) {
if(f.isFile()){
System.out.println(f.getName());
}else{
bianLi(f);
}
}
}
}
遞歸刪除文件
//????? 3.使用file類的delete方法和遞歸算法刪除一個文件夾(帶有內容)
public static void main(String[] args){
// TODO Auto-generated methodstub
File dir= new File("g:\\testDirFile");
deleterDir(dir);
}
//刪除指定的文件(包含內容)
privatestatic void deleterDir(File dir) {
//寫代碼需要保證代碼的健壯性
//入參檢測
//刪除文件中的所有內容
//如果File對象描述的是文件,調用listFiles方法后返回的是null
if(dir== null ||!dir.isDirectory()){
thrownew IllegalArgumentException("File對象不能為空,并且只能是文件");
}
File[]file = dir.listFiles();
for(File f : file) {
if(f.isFile()){
f.delete();
}else{
//如果是文件夾,就需要先刪除文件中的內容,在刪除文件
deleterDir(f);
}
}
//刪除文件夾本身(空文件夾)
dir.delete();
}
】
【
?? 對文件的操作:
?publicbooleancreateNewFile()//不存在時創建此文件對象所代表的空文件
?publicbooleandelete()//刪除文件。如果是目錄必須是空才能刪除
?publicbooleanmkdir()//創建此抽象路徑名指定的目錄
?publicbooleanmkdirs()//創建此抽象路徑名指定的目錄,包括所有必需但不存在的父目錄
?publicbooleanrenameTo(File?dest)//重新命名此抽象路徑名表示的文件
?? 瀏覽目錄中的文件和子目錄
?publicString[]list()//返回此目錄中的文件名和目錄名的數組
?publicFile[]listFiles()//返回此目錄中的文件和目錄的File實例數組
?publicFile[]listFiles(FilenameFilter?filter)//返回此目錄中滿足指定過濾器的文件和目錄
●java.io.FilenameFilter接口:實現此接口的類實例可用于過濾文件名
】
將數據存儲在磁盤上,斷電不消失、程序執行完不消失(之前的大部分練習都將數據存在內存中,斷電消失,程序執行完也會消失)
File 表示、描述文件、文件夾的類
構造方法: File(Stringpath)參數是文件的路徑
如: "d:\\file.txt"、"d:/folder/file1.txt"
(如果要使用反斜杠,必須用轉義符\\來表示;在高級的JDK版本中也可以直接用/來表示;另外File.separator可以自動根據運行的平臺轉換為"\\"或者"/")
注意:new一個File對象只會在內存中產生一個描述、表示某一個文件的對象,并不會創建這個文件本身
主要方法:
boolean exists()告訴我們這個對象所描述的文件究竟存不存在,存在返回true,不存在返回false
createNewFile()創建新的文件
boolean isFile()如果這個對象表示文件,返回true,否則返回false
boolean isDirectory()如果這個對象表示文件夾,返回true,否則返回false
mkdir()生成一個文件夾、目錄
mkdirs()生成一個目錄,如果要生成的目錄的父目錄不存在,會自動創建
File[] listFiles()返回一個目錄中的所有文件,以文件數組的形式返回
getPath()獲取文件路徑
getName()獲取文件名
delete()刪除文件
boolean canExecute()是否可執行
boolean canRead()是否可讀
boolean isHidden()是否是隱藏文件
File[]listFiles(FileFilter filter)返回目錄下所有符合過濾器要求的文件的數組
FileFilter是一個接口,要使用它,就用一個類實現它并實現boolean accept(File file)方法,在這個方法里寫上過濾的邏輯,符合條件要保留的就返回true,不符合條件要過濾掉的返回 false,參數里的file是要進行判斷保留還是不保留的文件
然后實例化這個過濾器類,并傳入listFiles()的參數,這樣listFiles在列出文件時會依據這個過濾器的邏輯、標準去過濾文件
listFiles只能列一層目錄
IO Input輸入 Output輸出
1、輸入流、輸出流
2、字節流、字符流
3、節點流、處理流
字節文件讀取:
【
FileInputStream fis = newFileInputStream("g:/output.txt");
while(true){
intn = fis.read();??? //讀一個字節
if(n== -1){//如果達到文件底部
break;
}
System.out.println((char)n);?? //打印字節對應的字符
}
fis.close();
fis = new FileInputStream("g:/output.txt");
byte[]buf = new byte[4];? //創建長度為4的字節數組緩存
while(true){
//每次從文件中讀取4個字節放入緩沖中
intn = fis.read(buf);
if(n== -1){???? //讀取到文件末尾了
break;?????? //退出
}//遍歷緩沖區字節數組,循環條件用n,可以將最后一次的無效數據排除
for(int i=0;i
System.out.println((char)buf[i]);?? //打印
}
FileInputStream fis = newFileInputStream("g:/output.txt");
byte[]buf = new byte[4];???? //創建長度為4的字節數組緩沖
intn = 0;
while((n=fis.read(buf))!=-1){
for(inti=0;i
System.out.println((char)buf[i]);
}
}
fis.close();
】
InputStream抽象類,往里讀信息、數據,以字節的形式
int read():讀取單個字節(返回的是int類型)
int read(byte[] buf):讀取多個字節,返回的是讀取的字節的個數
public intread(byte[] b, int off, int len) throws IOException
public void close()throws IOException
public intavailable() throws IOException
public skip(long n)throws IOException
字節文件輸出:
【
FileOutputStream fos = newFileOutputStream("g:/output.txt");//覆蓋輸出
FileOutputStreamfos = new FileOutputStream("g:/output.txt",true);//追加輸出
fos.write(97);
fos.write(98);
fos.write(99);
fos.write(100);
fos.write(101);
fos.close();?? //文件流操作結束后,一定要關閉
byte[] buffer ={65,66,67,68,69};? //數據源
try{
FileOutputStreamfos = new FileOutputStream("g:/output.txt");
//從buffer數組中截取下標1開始的3個字節,寫到文件中
fos.write(buffer,1, 3);//相比下面的,這種只有寫一次磁盤
/*fos.write(66);
fos.write(67);??????? //這種方式要寫三次磁盤,要慢一點
fos.write(68);*/
fos.close();
】
OutputStream抽象類,往外寫信息、數據,以字節的形式
write(int n)將指定的字節寫入此輸出流(寫出單個字節)
write(byte[] buf,intoff,int len)將b.length個字節從指定的byte數組寫入此輸出流
public voidwrite(byte[] b, int off, int len) throws IOException將指定byte數組中從偏移量off開始的len個字節寫入此輸出流
public void flush()throws IOException刷新此輸出流并強制寫出所有緩沖的輸出字節
刷新流的緩存
pulbic void close()throws IOException關閉此輸出流并釋放與此流有關的所有系統資源
FileInputStream文件輸入流、FileOutputStream文件輸出流,分別繼承了InputStream和OutputStream,分別用來從文件中讀數據和寫數據
這里的輸入和輸出,參照物是程序、虛擬機
兩個read()和兩個write()是他們最重要的方法了。
構造方法FileOutputStream(String path)表示對參數路徑的文件創建一個輸出流,這個輸出流可以用來對這個文件寫數據
(如果這個文件不存在,會自動創建)
(最后一定要關閉文件流)
(FileOutputStream(Stringpath,boolean append)可以向原文件追加輸出數據,不覆蓋原來的信息)
write(int n)表示向輸出流中寫一個字節的數據
write(byte[] buf,intoff,int len)表示將buf數組中的字節從off位置開始,截取長度len的字節數據寫到文件中
(buf是buffer緩沖,off是offset起點,len是length長度)
構造方法FileInputStream(String path)表示對參數路徑的文件創建一個輸入流,可以用這個輸入流讀取這個文件的信息
int read()從輸入流中一個一個字節讀入,如果讀到了文件底部,返回-1,否則返回那個讀入的字節
int read(byte[] buf)從輸入流中幾個幾個字節讀入,每次讀取的字節數,由參數中的字節數組長度決定;每次讀取出來的這些字節也都按順序存放在這個字節數組中
如果讀到文件底部,返回-1;否則返回實際讀的有效字節數
相比無參read(),單參read()每次操作磁盤讀多個字節,效率更高
在文件流處理中,關閉流的操作原則上要放在finally中,以確保執行;但是在學習過程中可以先關注重點,把這個問題暫時忽略
文件輸入流讀取文件:Reader
【
FileReader reader = new FileReader("g:/output.txt");
intn = 0;
while((n= reader.read())!=-1){
System.out.println((char)n);
}
reader.close();
】
文件輸出流,從程序中對外寫出文件:
【
FileWriter writer = newFileWriter("g:/output.txt);?????????//覆蓋的形式
FileWriterwriter = new FileWriter("g:/output.txt",true);??? //追加的形式
writer.write("敢做敢當,敢拼才會贏!");
writer.write("1000phone");
writer.write("1000phone".toCharArray(),0, "1000phone".toCharArray().length);
writer.close();
for (int i= 1; i <= 10; i++) {
FileInputStreamfis = new FileInputStream("G:/fos.txt");
FileOutputStreamfos = new FileOutputStream("g:/home1" + i + ".txt");
intn = 0;
byte[]buf = new byte[1024];
while((n = fis.read(buf)) != -1) {
fos.write(buf,0, n);
}
fos.close();
fis.close();
}
File folder = new File("g:/home1");
File[]files = folder.listFiles();
byte[]bytes = new byte[16];
for(File file : files) {
System.out.println(file.getName());
FileInputStreamfis = new FileInputStream(file);
intn = fis.read(bytes);
for(inti=0;i
System.out.println(bytes[i]+ " ");
}
System.out.println();
fis.close();
}
】
字符流Reader?? Writer
FileReader???? FileWriter
FileReader文件字符輸入流
構造方法FileReader(String path)在path路徑對應的文件上創建一個文件字符輸入流
int read()讀一個字符,返回-1表示讀到尾部
int read(char[] cbuf)讀若干個字符到字符數組緩沖中,返回-1表示讀到尾部,否則返回實
際讀的字符個數
Close();
FileWriter文件字符輸出流
構造方法FileWriter(String path)在path路徑對應的文件上創建一個文件字符輸出流
write(String s)
write(String s , intoff,int len)
writer(char[] crs)
close();//關閉流,自動刷新緩存注意:一旦流被關閉后就不能再使用,會拋出異常
flush();
write(int c)寫一個字符
write(char[] cbuf,intoff,int len)將參數字符緩沖從off開始截取,截取長度len的字符,寫到字符輸出流中
IO異常處理的注意事項
1、先創建的資源后釋放
1、? 釋放資源的操作必須放在flnally代碼塊中執行
2、
【
publicint read() throws IOException讀取單個字符,返回作為整數讀取的字符,如果已到達流的末尾返回-1
publicint read(char[]?cbuf) throws IOException 將字符讀入數組,返回讀取的字符數
publicabstract int read(char[]?cbuf, int?off, int?len) throwsIOException
publicabstract void close() throws IOException 關閉該流并釋放與之關聯的所有資源
publiclong skip(long?n) throws IOException?跳過n個字符。
】
【
public voidwrite(int?c) throws IOException寫入單個字符
public voidwrite(char[]?cbuf) throws IOException寫入字符數組
public abstract voidwrite(char[]?cbuf, int?off, int?len) throws IOException寫入字符數組的某一部分
public voidwrite(String?str) throws IOException寫入字符串
public voidwrite(String?str, int?off, int?len) throws IOException寫字符串的某一部分
public abstract voidclose() throws IOException關閉此流,但要先刷新它
public abstract voidflush() throws IOException刷新該流的緩沖,將緩沖的數據全寫到目的地
還提供了一個FileWriter(String?fileName,boolean?append)構造方法來指定是否使用追加模式
】
總結:
【
?? File類
?? Java流類的分類
???????輸入流和輸出流、字節流和字符流、節點流和過濾(處理)流
?? 文件流
???????FileInputStream/FileOutputStream
???????FileReader/FileWriter
?? 緩沖流
???????BufferedInputStream/BufferedOutputStream
???????BufferedReader/BufferedWriter
?? 轉換流:InputStreamReader/OutputStreamWriter
?? 數據流:DataInputStream/DataOutputStream
?? 壓縮流:
】