一、流概述 & InputStream、OutputStream
流包括輸入流和輸出流,即I/O(Input和Output),具體結構如下:
I/O類都被放在java.io包中,所有的輸入流類都是InputStream(針對字節)和Reader(針對字符)兩個抽象類的子類,而所有輸出流都是OutputStream(針對字節)和Writer(針對字符)的子類。
InputStream是一個抽象類,它的架構如下:
兩個InputStream類的框架圖。
InputStream類包含的API如下:
int available() void close() void mark(int readlimit) boolean markSupported() int read(byte[] buffer) abstract int read() int read(byte[] buffer, int offset, int length) synchronized void reset() long skip(long byteCount)
兩個OutputStream類的框架圖。
OutputStream類包含的API如下:
void close() void flush() void write(byte[] buffer, int offset, int count) void write(byte[] buffer) abstract void write(int oneByte)
一段程序,但有一點不太懂:
package stream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; public class isos { public static void inecho(InputStream is) { try { while(true) { int i=is.read(); if(i==-1) { break; } char c=(char) i; System.out.print(c); } } catch(IOException e) { e.printStackTrace(); } System.out.println(); } public static void outecho(OutputStream os) { try { String s="JAVAIO"; byte []b=s.getBytes(); os.write(b); os.flush(); } catch(IOException e) { e.printStackTrace(); } } public static void main(String []args) { inecho(System.in); //輸入一行之后回顯 // outecho(System.out); //輸出字符串s } }
System.in和System.out究竟是什么類型?InputStream和OutputStream?InputStream和OutputStream不是抽象類嗎?關於InputStream、OutputStream、ByteArrayInputStream和ByteArrayOutputStream先留在這里,以后再看一次看有什么新的收獲沒。主要重點還是放在FileInputStream和FileInputStream及其他一些知識上。
二、File類
File類創建文件對象,但是不能讀寫文件內容。
1.首先來看目錄的創建mkdir()方法:
public class file { public static void main(String []args) { File dir=new File("D:/dir"); dir.mkdir(); } }
我的電腦並沒有D盤,但是這個並不會報錯,沒有任何變化,待挖!
如果將D盤改為E盤,則會在E盤根目錄下建立名為dir的目錄,再運行一次,不會有什么變化。使用mkdir之后,在使用createNewFile也不報錯,但都會無效:
public class file { public static void main(String []args) { File dir=new File("E:/dir"); dir.mkdir(); try { dir.createNewFile(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
mkdir之后的代碼無效了,但是不報錯。
2.之后是建立多級目錄的方法mkdirs(),例如:
public class file { public static void main(String []args) { File dir=new File("/tmp/one/two/three"); dir.mkdirs(); } }
有幾個注意的點,第一如果不加盤符,我的默認是G盤,可能是之前設置的部分,加盤符就在前面加,例如E://tmp/one/two/three。第二多級目錄使用mkdir()那就無反應,兩個一起用是會建立的目錄。三是使用錯誤的盤符,例如D盤,可以運行,但是沒有建立任何目錄。
3.建立子目錄方法
可以直接使用建立多級目錄的方法來建立子目錄,例如想要建立dir的子目錄aaa,可以使用
File sub1=new File("/dir/aaa"); sub1.mkdirs();
建立dir的子目錄aaa,無論dir存在與否,沒有就建立dir,有直接建立子目錄aaa。
還可以使用
File sub1 = new File("dir", "aaa"); sub1.mkdir();
但是實驗結果不是那樣,失敗了,以下是網上說性質,與上一種方法不同,必須要有子目錄。(已解決,原因是第一個參數少加’/‘,改為File sub1 = new File("/dir", "aaa");即可)
4.新建文件方法
File f=new File("E:/test.txt");
try { f.createNewFile(); } catch (IOException e) { e.printStackTrace(); }
Windows必須要使用絕對路徑?像建立目錄那樣的使用相對路徑,運行完也不報錯,但是沒有文件(已解決,但原因尚未清楚!)。還有創建文件必須要使用try-catch語句,而且必須是要存在的路徑,否則報警告路徑不存在。
File f=new File("/dir","test.txt");
也可改為絕對路徑,不過要保證該路徑存在,否則直接拋出異常。
最后運行結果:
File aa = new File("/dir"); File f=new File(aa,"/test.txt");
這兩句和前面效果一樣,不過也是要保證路徑存在,否則拋出異常。
最后還有一種使用URI的方法,再此只標注一下,無需詳細了解:
try { URI uri = new URI("file:/home/dir"); File file4 = new File(uri); file4.mkdirs(); URI uri2 = new URI("file:/home/dir/test.txt"); File f2=new File(uri2); f2.createNewFile(); } catch (URISyntaxException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }
5.File的一些API使用
boolean canExecute() // 測試應用程序是否可以執行此抽象路徑名表示的文件。
boolean canRead() // 測試應用程序是否可以讀取此抽象路徑名表示的文件。
boolean canWrite() // 測試應用程序是否可以修改此抽象路徑名表示的文件。
boolean delete() // 刪除此抽象路徑名表示的文件或目錄。
boolean equals(Object obj) // 測試此抽象路徑名與給定對象是否相等。
boolean exists() // 測試此抽象路徑名表示的文件或目錄是否存在。
File getAbsoluteFile() // 返回此抽象路徑名的絕對路徑名形式。
String getAbsolutePath() // 返回此抽象路徑名的絕對路徑名字符串。
File getCanonicalFile() // 返回此抽象路徑名的規范形式。
String getCanonicalPath() // 返回此抽象路徑名的規范路徑名字符串。
long getFreeSpace() // 返回此抽象路徑名指定的分區中未分配的字節數。
String getName() // 返回由此抽象路徑名表示的文件或目錄的名稱。
String getParent() // 返回此抽象路徑名父目錄的路徑名字符串;如果此路徑名沒有指定父目錄,則返回 null。
File getParentFile() // 返回此抽象路徑名父目錄的抽象路徑名;如果此路徑名沒有指定父目錄,則返回 null。
String getPath() // 將此抽象路徑名轉換為一個路徑名字符串。
long getTotalSpace() // 返回此抽象路徑名指定的分區大小。
long getUsableSpace() // 返回此抽象路徑名指定的分區上可用於此虛擬機的字節數。
int hashCode() // 計算此抽象路徑名的哈希碼。
boolean isAbsolute() // 測試此抽象路徑名是否為絕對路徑名。
boolean isDirectory() // 測試此抽象路徑名表示的文件是否是一個目錄。
boolean isFile() // 測試此抽象路徑名表示的文件是否是一個標准文件。
boolean isHidden() // 測試此抽象路徑名指定的文件是否是一個隱藏文件。
long lastModified() // 返回此抽象路徑名表示的文件最后一次被修改的時間。
long length() // 返回由此抽象路徑名表示的文件的長度。
String[] list() // 返回一個字符串數組,這些字符串指定此抽象路徑名表示的目錄中的文件和目錄。
String[] list(FilenameFilter filter) // 返回一個字符串數組,這些字符串指定此抽象路徑名表示的目錄中滿足指定過濾器的文件和目錄。
File[] listFiles() // 返回一個抽象路徑名數組,這些路徑名表示此抽象路徑名表示的目錄中的文件。
File[] listFiles(FileFilter filter) // 返回抽象路徑名數組,這些路徑名表示此抽象路徑名表示的目錄中滿足指定過濾器的文件和目錄。
File[] listFiles(FilenameFilter filter) // 返回抽象路徑名數組,這些路徑名表示此抽象路徑名表示的目錄中滿足指定過濾器的文件和目錄。
static File[] listRoots() // 列出可用的文件系統根。
boolean renameTo(File dest) // 重新命名此抽象路徑名表示的文件。
boolean setReadOnly() // 標記此抽象路徑名指定的文件或目錄,從而只能對其進行讀操作。
String toString() // 返回此抽象路徑名的路徑名字符串。
String name=f2.getName(); long length=f2.length(); String path=f2.getPath(); String parent=f2.getParent(); String p2=f2.getAbsolutePath(); String p3=f2.getCanonicalPath(); long fs=f2.getFreeSpace(); long ts=f2.getTotalSpace(); long us=f2.getUsableSpace(); boolean b1=f2.exists(); boolean b2=f2.canWrite(); boolean b3=f2.canExecute(); boolean b4=f2.canRead(); System.out.print(name+" "+length+" "+b1+" "+b2+" "+b3+" "+b4); System.out.println(); System.out.print(path+" "+parent+" "+p2+" "+p3+" "+fs+" "+ts+" "+us); System.out.println(); long time=f2.lastModified(); boolean b5=f2.isDirectory(); boolean b6=f2.isFile(); boolean b7=f2.isHidden(); boolean b8=f2.isAbsolute(); // for(String s:f2.list()) // System.out.println(s); System.out.print(b5+" "+b6+" "+b7+" "+b8+" "+time);
結果:
test.txt 7 true true true true
\home\dir\test.txt \home\dir G:\home\dir\test.txt G:\home\dir\test.txt 89270075392 107666731008 89270075392
false true false false 1545665029004
注:經過簡單測試,漢字length為2,回車length為2。
而之前對f2使用list方法出現錯誤,一直拋出空指針的異常,后來發現這個方法會返回該目錄下的所有目錄和文件的名稱,但是你的對象是一個文件的話,那就會拋出異常了,也就是說你的對象要首先是一個目錄,才能調用該方法:
String []list=file4.list(); for(String s:list) System.out.println(s);
結果:
sub(目錄)
test.txt(文件)
三、FileInputStream & FileInputStream
FileInputStream輸入,對應文件的讀操作(Read)。
FileOutputStream輸出,對應文件的寫操作(Write)
package stream; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; public class FileStream { public static void main(String []args) { try { FileOutputStream fos=new FileOutputStream("G:\\home\\dir\\test.txt"); byte[] bb="武一鳴".getBytes(); fos.write(bb);
fos.write(33); //FileInputStream寫入write參數可以是byte[]或者int,但是int也會變成byte 33變為!,但經過實測char好像也可以 fos.close(); FileInputStream fis=new FileInputStream("G:\\home\\dir\\test.txt"); int i=fis.read(); while(i!=-1) { byte b=(byte) i; System.out.print((char)b); i=fis.read(); //注意不要忘記,剛開始寫代碼這句忘了,一直無限循環。 } fis.close(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
結果分析:FileOutputStream寫入會使之前的文件信息全部消失。
其實這里應該詳細講解InputStream和OutpStream的方法的,例如write()、flush()、read()、mark()等等,但是由於種種原因已到了BufferedInpuStream后面講了,移步到Java I/O(二)。