從新開始學Java——File And Streams

注意:這裏僅僅描述了基本的使用方法,並無涉及到NIO中的東西,有關於NIO方面的東西,放到以後的博客中描述。RandomAccessFile放到以後再進行描述java

File

在文件系統中,文件名是用於定位存儲位置 元數據:描述數據的數據,在這裏咱們將一個文件看成一個數據,那麼文件的屬性就是元數據。mysql

java.io.File 類表明與當前系統平臺無關的文件和目錄sql

File 類的一個實例就表明一個文件或目錄數組

File 類提供了判斷 其實例是文件仍是目錄的方法app

File 類提供了能夠操做文件系統中的文件和目錄的方法dom

File 類僅表明文件或目錄,不支持對文件的內容進行修改ide

構造方法

File( String pathname )
經過將給定路徑名字符串轉換爲抽象路徑名來建立一個新 File 實例

File( String parent , String child )
根據 parent 路徑名字符串和 child 路徑名字符串建立一個新 File 實例

File( File parent , String child )
根據 parent 抽象路徑名和 child 路徑名字符串建立一個新 File 實例

File( URI uri )
經過將給定的 file: URI 轉換爲一個抽象路徑名來建立一個新的 File 實例

可是咱們在使用的時候,最常常使用的就是傳一個路徑的File構造方法。測試

常量

public static final char separatorChar
與系統有關的默認名稱分隔符(⽂文件系統中的不不同層次的路路徑之間的分隔符)

public static final String separator
與系統有關的默認名稱分隔符,爲了了⽅便,它被表示爲一個字符串

public static final char pathSeparatorChar
與系統有關的路路徑分隔符(環境變量量PATH的取值中不同部分之間的分隔符)

public static final String pathSeparator
與系統有關的路路徑分隔符,爲了了⽅便,它被表示爲一個字符串

方法測試

String path = "C:/Windows/notepad.exe" ;
	// 根據給定的目錄的路徑來建立一個對象 表示該目錄的Java對象
	File directory = new File(path) ; 
	System.out.println("File所表示的目錄或文件是否存在 :" + directory.exists() );
	System.out.println("是不是一個文件 : " + directory.isFile() );
	System.out.println( "是不是一個目錄 : " + directory.isDirectory() );
	System.out.println("是不是隱藏的:" + directory.isHidden() );
	System.out.println("是不是絕對路徑:" + directory.isAbsolute() );
	// length方法返回的字節數,若是須要轉成KB或其餘單位,須要進行換算(僅對文件有效,對目錄無效)
	System.out.println("文件的長度是:" + directory.length()/1024 );
	path = "C:\\JavaApplication\\mysql-5.7.17-winx64" ; 
	directory = new File( path ) ; 
	String[] names = directory.list() ;
	for (String s : names) {
		System.out.print(s + "\t");
	}
	System.out.println();
	File[] fileNames = directory.listFiles() ;
	for (File f : fileNames) {
		System.out.print(f.toString() + "\t");
	}
	System.out.println();
	
	path = "C:/Windows/notepad.exe" ;
	File f = new File(path) ; 
	System.out.println("文件名或目錄名: " + f.getName() );
	System.out.println("存放路徑 : " + f.getParent() );
	System.out.println("絕對路徑 :" + f.getAbsolutePath() );
	System.out.println("最後修改的毫秒 :" + f.lastModified() );
	System.out.println( "最後修改的時間 :" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date( f.lastModified() )));
	System.out.println("文件或目錄是否可讀 :" + f.canRead() );
	System.out.println("文件或目錄是否可寫 :" + f.canWrite() );
	System.out.println("文件或目錄是否能夠執行 :" + f.canExecute() );
		
	/**
	 * 在Eclipse環境下運行含有main方法的Java程序,默認的當前路徑是當前工程
	 * 注意路徑的規範化形式
	 */
	path = "." ;
	f = new File( path ) ; 
	System.out.println( f.getAbsolutePath() );
	path = "src" ;// 表示當前路徑下的src目錄
	f = new File( path ) ; 
	System.out.println( "獲取絕對路徑:" + f.getAbsolutePath() );
	f = new File("..");
	System.out.println( "獲取絕對路徑:" + f.getAbsolutePath() );
	System.out.println("獲取規範化形式的路徑:" + f.getCanonicalPath() );
	f = new File( "/" ) ;
	System.out.println(f.getAbsolutePath() );
	System.out.println(f.getCanonicalFile());
	/**
	 * 建立新文件、刪除新文件
	 */
	path = "." ;
	f = new File( path ) ; 
	if( f.canWrite() ) {
		// 在f對應的目錄中建立一個hello.txt文件
	    // 在內存中建立一個表示f下的hello.txt對應的文件的Java對象
		File file = new File( f , "hello.txt") ;
		if ( file.exists()) {
			file.delete() ; 
		}
		// 在磁盤上 建立一個file對象對應的新文件
		boolean b = file.createNewFile() ;
		System.out.println( b );// 若是已經存在或沒有權限則建立失敗
		
	}
	/**
	 * 建立目錄、刪除目錄( delete能夠刪除空目錄)
	 */
	if( f.canWrite() ) {
		File file = new File( f , "kaka") ; 
		if( file.exists() && file.isDirectory()  ) {
			boolean b = file.delete() ;
			System.out.println( b ? "目錄刪除成功" : "目錄刪除失敗" );
		}
		boolean b = file.mkdir() ; // 建立一個新目錄
		System.out.println( b ? "目錄建立成功" : "目錄建立失敗");
	}
	/**
	 * mkdir能夠建立一個子目錄
	 * mkdirs 能夠建立多層子目錄
	 */
	if( f.canWrite() ) {
		File file = new File( "kaka/kakaTM/kakTTMM");
		file.mkdirs() ;
		File dest = new File("kaka/kakaTM/kakTTMMMM") ; 
		// 將file的名稱重命名爲dest對應的名稱
		file.renameTo(dest) ; 
	}
	
	File s = new File("./hello.txt") ; 
	File d = new File("C:/abc.txt") ; 
	s.renameTo(d) ; // 剪切操做( 強烈不建議操做 )
	File kak = new File("kaka") ; 
	kak.deleteOnExit(); // 虛擬機退出以後再刪除
	Thread.sleep(30000 );// 能夠在這裏進行測試

文件過濾器this

能夠根據條件(最後修改時間、長度、名字等)進行過濾。編碼

File dof = new File("C:/test") ; 
	if( dof.exists() && dof.isDirectory() ) {
		FilenameFilter fnf = new FilenameFilter() {
			[@Override](https://my.oschina.net/u/1162528)
			public boolean accept(File dir, String name) {
				if( name.endsWith("java")) {
					return true ; 
				}
				return false;
			}
		};
		String[] fileList = dof.list(fnf) ;
		System.out.println( fileList.length );
		for (String s : fileList) {
			System.out.println( s );
		}
	}
File dof = new File("C:/test") ; 
	if( dof.exists() && dof.isDirectory() ) {
		FileFilter fnf = new FileFilter() {
			
			[@Override](https://my.oschina.net/u/1162528)
			public boolean accept(File pathname) {
				if( pathname.isFile() && pathname.getName().endsWith(".java")) {
					return true ; 
				}
				return false;
			}
		};
		File[] fileList = dof.listFiles(fnf);
		System.out.println( fileList.length );
		for (File s : fileList) {
			System.out.println( s );
		}
	}

練習:能夠經過遍歷獲取C盤下的全部文件的名字。

字節輸入輸出流

InputStream是全部字節輸入流的父類。

注意看構造

咱們能夠利用FileInputStream來測試InputStream中的方法

File file = new File("out.txt") ; 
	InputStream inStream = null ; 
	System.out.println( inStream );
	if( file.exists() && file.isFile() ) {
		inStream = new FileInputStream(file) ; 
		System.out.println( inStream );
//		int b = inStream.read() ; // 範圍0~255,將byte數字進行"翻譯"成int值
//		System.out.println( b );
		int b ; 
		do {
			// read方法負責讀取一個字節,
			// 若是沒有到達流的末尾,則返回讀取到的數據
			// 若是到達流的末尾,則返回-1
			b = inStream.read() ; // 一次讀取一個字節
			System.out.println( b );
		}while( b!=-1 );
		
	}
	inStream.close();

這裏一次讀取一個字節,解析出來的全是數字,若是轉成char類型,看不懂。因此可使用數組,表示一次多讀取幾個字節的方式來操做。

File file = new File("out.txt") ; 
    InputStream inStream = null ; 
	System.out.println( inStream );
	if( file.exists() && file.isFile() ) {
		inStream = new FileInputStream(file) ; 
		System.out.println( inStream );
		// 得到下一次調用方法以前能夠不受阻塞的今後輸入流中讀取估計字節數
		int size = inStream.available() ; 
		byte[] bytes = new byte[size] ; 
		int n ; 
		/*do {
			// read( byte[] bytes )方法負責讀取n個字節,
			// 若是沒有到達流的末尾,則返回讀取到的字節數(讀取到幾個字節就返回幾)
			// 若是讀取到內容了,則將讀取到的字節放入到數組中(讀取到幾個,就放入幾個)
			// 若是到達流的末尾,則返回-1
			n = inStream.read(bytes ) ; // 一次讀取一個字節
			System.out.println( "讀取到的字節數:"+n );
			String s = new String(bytes , 0 , n ) ; 
			System.out.println( s );
		}while( n!=-1 );
		*/
		while( (n = inStream.read(bytes)) != -1 ) {
			String s = new String( bytes , 0 , n) ; 
			System.out.println( s );
		}
	}
	System.out.println( inStream.markSupported() );
	inStream.close();

咱們能夠看到FileInputStream是不支持作標記的,咱們後續再說。那麼咱們的FileInputStream就看完了。

FileOutputStream

此抽象類是表示輸出字節流的全部類的超類。輸出流接受輸出字節並將這些字節發送到某個接收器。

須要定義 OutputStream 子類的應用程序必須始終提供至少一種可寫入一個輸出字節的方法。

public static void main(String[] args) throws Exception {
		File file = new File("file.txt") ;// 第一個參數指示輸出到哪裏去 
		boolean append = false ; // 若是第二個參數是true表示追加,若是是false表示覆蓋
		OutputStream os = new FileOutputStream(file, append) ;
		// 輸出單個字節(若是是int類型的整數,則忽略高24位,只留低8位)
		os.write(97);
		os.write(378);
		byte[] bytes = "卡卡他媽".getBytes() ;
		System.out.println( bytes.length );
		// 將這個字節數組經過輸出流 輸出到文件中
		os.write(bytes);
		// 將字節數組中的一部分輸出到文件中 write( bytes , start, n)[start , start+n)
		os.write(bytes,3 , 3);
		os.close();
	}

這樣咱們就會使用了OutputStream這個類中的方法。

複製文件

public static void main(String[] args) throws Exception {
		File source = new File("G:\\一禪壁紙\\電腦壁紙\\桌面背景03.jpg") ; 
		File target = new File( source.getName() ) ; 
		FileInputStream in = new FileInputStream(source) ; 
		FileOutputStream out = new FileOutputStream( target ) ;
		int n ; // 聲明一個變量,用來記錄讀取到的字節數
		byte[] bytes = new byte[128] ; 
		while( (n = in.read(bytes ) ) != -1 ) {
//			out.write(bytes);
			out.write(bytes, 0, n);
		}
		out.close();
		in.close();
	}

固然,咱們能夠看一下複製時間。

BufferedInputStream

BufferedInputStream 爲另外一個輸入流添加一些功能,即緩衝輸入以及支持 mark 和 reset 方法的能力。在建立 BufferedInputStream 時,會建立一個內部緩衝區數組。

public static void main(String[] args) throws Exception {
		InputStream in = new FileInputStream("src/bufferedStream/TestBufferedStream1.java") ; 
		// super(in)--->this.in = in ; 
		// this.buf = new byte[8192] ; // 內部有一個字節數組
		BufferedInputStream bis = new BufferedInputStream(in) ;
		byte[] bytes = new byte[100] ; 
		int n;
		while((n=bis.read(bytes))!=-1 ) {
			String s = new String( bytes , 0 , n );
			System.out.print(s);
		}
		bis.close();
		in.close();
	}
public static void main(String[] args) throws Exception {
		InputStream in = new FileInputStream("bufferIn.txt") ; 
		BufferedInputStream bis = new BufferedInputStream(in) ;
		int n;
		while((n=bis.read())!=-1 ) {
			char ch = (char)n;
			System.out.print( ch );
			if( bis.markSupported() ) {// 判斷是否支持mark和reset操做
				if(ch=='s') {
					// this.marklimit = readlimit;// this.maklimit =250 
			        // this.markpos = pos;
					bis.mark(250);
				}
			}
		}
		System.out.println();
		if(bis.markSupported() ) {
			bis.reset();
			int b;
			while((b=bis.read())!=-1 ) {
				char ch = (char)b;
				System.out.print( ch );
				
			}
		}
		bis.close();
		in.close();
	}
/**
 * 向緩衝字節輸出流中輸出數據,若是沒有close和flush方法,可能致使數據不被輸出
 */
public class TestBufferedStream3 {
	public static void main(String[] args) throws Exception {
		OutputStream out = new FileOutputStream("buffer.txt") ; 
		BufferedOutputStream bos = new BufferedOutputStream(out) ;
		bos.write(97);
		bos.write('b');
		bos.write(100);
		// 調用flush方法將緩衝區的內容進行刷出
		// bos.flush();
		bos.close();// close方法中調用了flush方法
	}
}

字符輸入輸出流

Reader

用於讀取字符流的抽象類。子類必須實現的方法只有 read(char[], int, int) 和 close()。 由於是抽象類,因此不能new對象,能夠找它的子類:FileReader

public class TestReader {
	public static void main(String[] args) throws Exception {
		String file = "src/reader/TestReader.java" ;
		// 建立一個字符輸入流,一次能夠讀取一個字符
		Reader reader = new FileReader(file) ; 
		int ch ; 
		// Reader中的read()能夠返回一個字符(以整數形式返回)
		// 若是讀到流的末尾,返回-1
		while( (ch = reader.read() ) != -1 ) {
			// 將獲得的整數形式的字符強制轉成char類型
			char c = (char)ch ; 
			System.out.print(c);
		}
	}
}
public static void main(String[] args) throws Exception {
		String file = "src/reader/TestReader2.java" ;
		Reader reader = new FileReader(file) ; 
		char[] chars = new char[100] ;// 表示100個字
		int ch ; 
		// Reader中的read(char[] charArray)能夠從流中讀取n個字節到數組中
		while( (ch = reader.read( chars ) ) != -1 ) {
			// 將本次讀取到的字符構造稱字符串
			String s = new String(chars, 0, ch) ; 
			System.out.print(s);
		}
		reader.close();
	}

Writer

public static void main(String[] args) throws Exception {
		String filename = "writer.txt" ; 
		boolean append = false ; 
		Writer w = new FileWriter(filename , append ) ; 
		w.write(97);
		w.write('\n');
		w.write("helloworld");
		w.write('\n');
		char[] chars = {'k','k','T','M'} ; 
		w.write(chars);
		w.write(chars, 2,1 );
		w.close();
	}
public static void main(String[] args) throws Exception {
		String filename = "writer.txt" ; 
		boolean append = false ; 
		Writer w = new FileWriter(filename , append ) ; 
		w.append("hello") ; 
		w.append('k') ; 
		w.write("TM");
		w.close();
	}

BufferedReader&&BufferedWriter

public static void main(String[] args) throws Exception {
		// 建立一個能夠讀取文件內容的字符輸入流( 節點流 )
		Reader r = new FileReader("buffer.txt") ;
		// 建立一個帶有緩衝功能的字符輸入流( 它提供了額外的功能)
		// BufferedReader實例內部一個能夠容納8192個字符的char數組
		BufferedReader br = new BufferedReader( r ) ; 
		String s ; 
		while( (s = br.readLine() ) != null ) {
			System.out.println( s );
		}
		br.close();
		r.close();
	}
public static void main(String[] args) throws Exception {
		Writer w = new FileWriter("buffer.txt");
		// BufferedWriter內部有一個能夠容納8192個字符的char數組
		BufferedWriter bw = new BufferedWriter(w) ;
		bw.write("hello,kaka");// 向緩衝區中寫入內容
		// 刷出緩衝區的內容到目標輸出流
		bw.flush();
		bw.close();
		w.close();
		System.out.println( w.toString() );
	}

InputStreamReader && OutputStreamWriter

這兩個流就是對應的轉換流,是字節流和字符流之間的轉換。

/**
 *轉換流(InputStreamReader)將字節輸入流轉換成字符輸入流 
 */
public class TestInputStreamReader1 {
	public static void main(String[] args) throws Exception {
		String fileName = "src/conver/TestInputStreamReader1.java";
		// 建立一個字節輸入流
		InputStream in = new FileInputStream(fileName) ;
		// 將字節輸入流轉換稱字符輸入流
		InputStreamReader isr = new InputStreamReader(in) ; 
//		byte[] bytes = new byte[8] ; 
//		int b ; 
//		while( (b = in.read(bytes)) != -1 ) {
//			String s = new String( bytes , 0 , b );
//			System.out.print(s);
//		}
		int n ; 
		// 一次讀取一個字符(以整數形式返回),保存到ch變量中,而後比較是否等於-1(若是是-1,表示結束)
		while( (n = isr.read()) != -1 ) {
			System.out.print( (char)n );
		}
		in.close();
	}
}
public static void main(String[] args) throws Exception {
		// 將標準輸入流存儲到變量in中
		InputStream in = System.in ; 
//		int n ;
//		while( (n = in.read() ) != -1 ) {
//			System.out.println((char)n);
//		}
		// 將字節輸入流轉換成字符輸入流
		InputStreamReader r = new InputStreamReader(in ) ; 
		int ch ;
		while( (ch = r.read() ) != -1 ) {
			System.out.print((char)ch);
		}
		r.close();
		in.close();
		
	}
public static void main(String[] args) throws Exception {
		// 將標準輸入流存儲到變量in中
		InputStream in = System.in ; 
		// 將字節輸入流轉換成字符輸入流
		InputStreamReader r = new InputStreamReader(in ) ; 
		// 包裝一個字符緩衝流
		BufferedReader br =new BufferedReader(r) ;
		String ch ; 
		while( (ch =  br.readLine() ) != null ) {
			
			System.out.print(ch);
			if( "byebye".equalsIgnoreCase(ch)) {
				System.exit(0);
			}
		}
		r.close();
		in.close();
	}

OutputStreamWriter

/**
 * 將字符輸出流轉換成字節輸出流
 */
public class TestOutputStreamWriter {
	public static void main(String[] args) throws IOException {
		// 建立一個字節輸出流,輸出到文本文件中
		OutputStream o = new FileOutputStream("convert.txt");
		// 將字符輸出流轉成字節輸出流
		OutputStreamWriter osw = new OutputStreamWriter( o ) ; 
		osw.write("哈哈哈哈哈");
		osw.write('k');
		osw.write('\n');
		osw.close();
		o.close();
	}
}
/**
 *讀取一個UTF-8編碼的文件,將它轉成GBK編碼後從新輸出到另一個文件中
 */
public class TestOutputStreamWriter2 {
	public static void main(String[] args) throws IOException {
		// 讀取一個文本文件
		InputStream inStream = new FileInputStream("convert.txt") ;
		// 建立一個轉換流,並指定相應的字節輸入流和編碼名稱
		// 在將字節轉換成字符時,採用編碼名稱指定的編碼完成
		InputStreamReader isr = new InputStreamReader( inStream ,"UTF-8" ) ;
		// 建立一個能夠輸出字節到指定文件的字節輸出流
		OutputStream outputStream = new FileOutputStream("convert-gbk.txt");
		// 建立一個以指定字節流爲輸出目標的轉換流( 字節轉字符 )
		// 並指定將字符轉換成字節時,使用的編碼名稱
		OutputStreamWriter osw = new OutputStreamWriter(outputStream, "GBK") ; 
		int ch ;
		// 從字符輸入流中一次讀取一個字符
		while( ( ch = isr.read() ) != -1 ) {
			// 經過字符輸出流將讀取到的字符從新輸出
			osw.write(ch); // 將單個字符寫出到Writer流
		}
		osw.close();
		outputStream.close();
		isr.close();
		inStream.close();
	}
}

對象序列化

/**
 * 若是但願完成序列化操做,須要實現java.io.Serializable接口
 */
public class Student implements Serializable{
	/**
	 * serialVersionUID 至關於一個類的身份證編號
	 * 在序列化時,會將該編號一塊兒輸出到相應的流中
	 * 等到反序列化時(讀取流還原對象),會檢查相應的類是否存在(會檢查該編號)
	 */
	private static final long serialVersionUID = -3227384916215757351L;
	private Integer id ; 
	private String name ;
	private char gender ; 
	private Date bithdate ;
	// getter and setter
	}
/**
 * 序列化( Serialization)
 * 將一個Java對象以特定的字節序列輸出到某個流中
 * 經過 ObjectOutputStream類的writeObject(obj)來實現
 * 被寫出的那個對象對應的類須要實現java.io.Serialization接口
 */
public class ObjectSerialization1 {
	public static void main(String[] args) throws IOException {
		final Calendar c = Calendar.getInstance() ;
		Student s = new Student() ; 
		s.setId(9527);
		s.setName("華安");
		s.setGender('男');
		c.set(1888, 8, 8, 8, 8, 8);
		s.setBithdate(c.getTime());
		OutputStream out = new FileOutputStream("student.obj") ; 
		ObjectOutputStream oos = new ObjectOutputStream(out) ; 
		// 保存學生對象
		oos.writeObject(s);
		oos.close();
		out.close();
	}
}
/**
 * 反序列化
 * 就是讀取一個流中的數據,將它還原(重構)成相應的對象
 * 重構時,就會檢查該對象對應的類的serialVersionUID
 * 反序列化經過ObjectInputStream來實現
 */
public class ObjectDeserialization1 {
	public static void main(String[] args) throws IOException, ClassNotFoundException {
		InputStream in = new FileInputStream("student.obj") ; 
		ObjectInputStream ois = new ObjectInputStream(in) ; 
		// 從已知的字節流中讀取某個對象對應的數據
		Object o = ois.readObject() ;
		System.out.println( o );
		if( o instanceof Student) {
			Student s = (Student) o ; 
			System.out.println( s.getName() );
		}
		ois.close();
		in.close();
	}
}
相關文章
相關標籤/搜索