java IO 文件與數據流

java IO 文件與數據流

  • 如果返回char, 那麼無法表示流末尾.
  • char的取值範圍是從0到65535
  • 這個範圍內的所有字符, 都有可能在數據中出現
  • 我們需要使用一個不可能在數據中出現的值來表示流末尾
  • 那麼Java中就是用-1來表示這個末尾的, 因爲-1不會在數據中出現
  • 而爲了返回-1, 那麼只能用int
  • 當流中讀取到一個字符時, read()方法內部就會當作int返回, 如果讀到流末尾, 直接返回-1

輸入流與輸出流

  • 輸入流(抽象類 java.io.InputStream):從文件、網絡請求返回數據、標準輸入、或者其他輸入設備中加載到內存中。
  • 輸出流(抽象類 java.io.OutputStream):與輸入流相反,是從內存輸出到文件、顯示器、其它輸出設備。

InputStream(抽象類)

  • InputStream爲抽象類不能創建實例對象,但是InputStream定義了輸入流的基本操作,可以通過其子類獲得它的實例 。
public class Test {

	public static void echo(InputStream in) {
		try {
			while (true) { // 接受輸入並回顯
				int i = in.read( );//read()方法每次讀取一個字節,讀到輸入流末尾返回-1
				if (i == -1) // 輸入流結束
					break;
				char c = (char) i;
				System.out.print(c);
			}
		} catch (IOException e) {
		    System.err.println("發生異常:" + e);
			e.printStackTrace( );
		}
	}
	
	public static void main(String args[ ]) {
		echo(System.in);
	}
}
  • System.in是java.io.InputStream類型的變量,對應於標準輸入;
  • read()方法每次讀取一個字節,讀到輸入流末尾返回-1;
  • System.err.println();是java.io.PrintStream類型的變量,對應標準錯誤輸出流;

OutputStream(抽象類)

  • OutputStream也爲抽象類不能創建實例對象,但是OutputStream定義了輸入流的基本操作,也可以通過其子類獲得它的實例 。
public class Main {

    public static void write(OutputStream out) {
        String s = "輸出流例程";
        byte[] b = s.getBytes();
        try {
            out.write(b);
            out.flush();
        } catch (IOException e) {
            System.err.println("發生異常:" + e);
            e.printStackTrace();
        }
    }

    public static void main(String args[]) {
        write(System.out);
    }
}
  • System.out是java.io.OutputStream類型的變量,對應於標準輸出;
  • 在調用write()方法後,常常會調用flush()方法進行強制輸出,因爲目前的計算機爲了提高效率常常採用緩存機制,這樣調用write()方法之後,數據不會立即輸出,而是暫時保存在緩存中,等積累到一定的程度纔會真正輸出數據。而調用flush()方法之後是將數據立即輸出。

FileInputStream(從文件讀取數據)

public class Main {

    public static void main(String args[ ]) {
        try {
            FileInputStream f =new FileInputStream("ex3.txt"); //與文件建立關聯
            int i;
            int b = f.read();
            for (i=0; b!=-1; i++) {
                System.out.print((char)b);
                b=f.read();
            }
            System.out.println();
            System.out.println("文件\"test.txt\"字節數爲"+i);
            f.close();
        } catch (IOException e) {
            System.err.println("發生異常:" + e);
            e.printStackTrace();
        }
    }
}
  • 文件必須事先存在於項目的目錄下,否則會報錯;
  • 文件中如果包涵了中文字符的話,中文字符的顯示會出錯;
  • read()方法的返回值是int類型的。

FileOutputStream(將數據保存到文件中)

public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String str = scanner.nextLine();
        System.out.println(str);
        byte[] bytes = str.getBytes();
        try{
            FileOutputStream fileOutputStream = new FileOutputStream("ex3.txt",true);
            fileOutputStream.write(bytes);
            fileOutputStream.flush();
            fileOutputStream.close();
        }catch (IOException e){
            e.printStackTrace();
        }
        scanner.close();
    }
  • 文件可以事先存在,纔在則直接寫入;如果文件不存在的話則新創建文件後將數據寫入;
  • 在創建FileOutputStream實例的時候,第二個參數表示是否可追加(false-不可追加,每次寫入都是講原來的覆蓋之後再寫入,true-則是可以追加,每次寫入都是將內容寫到文件末尾),第二個參數可以缺省則默認爲false.

PrintStream

public static void main(String[] args) {
        try{
            PrintStream printStream = new PrintStream("ex3.txt");
            printStream.printf("%1$d+%2$d=%3$d",1,2,(1+2));//對輸出內容進行格式化
            printStream.close();
        }catch (FileNotFoundException e){
            e.printStackTrace();
        }
    }
  • Syetem.out是它的一個對象;
  • 文件不要求事先存在,要是文件存在且有內容,則會覆蓋內容,要是文件不存在的話,則新創建文件將內容寫進去。

數據的輸入流和輸出流

  • java.io.DataInputStream和java.io.DataOutputStream主要用來讀取和存儲基本數據類型的數據而且每個基本數據類型數據存儲的字節數與他在內存中所佔的字節數是相同的;
  • java.io.DataIutputStream的對象通常是由java.io.FireInputStream的實例對象創建的;
  • java.io.DataOutputStream的對象通常是由java.io.FireOutputStream的實例對象創建的;
  • java.io.DataOutputStream的實例其中的方法 write()可以直接將基本數據類型寫進指定的文件中,並且字節數與基本數據類型所佔字節數相等。例如writeInt()方法用於將int類型的數據寫進文件,其他數據類型對應相應的方法。
  • java.io.DataOutputStream的實例其中的方法 reader()可以直接將基本數據類型從文件中讀取出來,並且字節數與基本數據類型所佔字節數相等。例如readInt()方法用於將int類型的數據從相應文件中讀取出來,其他數據類型對應相應的方法。

public static void main(String args[ ]){
        try {
            FileOutputStream fout = new FileOutputStream("out.txt");
            DataOutputStream dfout =new DataOutputStream(fout);
            int i;
            for (i=0; i< 10; i++){
                dfout.writeInt('0' + i);//事先將1-10存入out.txt文件中
            }
            fout.close( );

            FileInputStream fin= new FileInputStream("out.txt");//建立與out.txt關聯
            DataInputStream dfin= new DataInputStream(fin);
            for (i=0; i< 10; i++){
                System.out.print(dfin.readInt( ) + ", ");//將out.txt文件中的內容進行輸出
            }
            dfin.close( );
        }
        catch (Exception e) {
            System.err.println("發生異常:" + e);
            e.printStackTrace( );
        }
    }

  • java.io.DataOutputStream的writeInt()等方法文件不必事先存在,如果原來文件存在則輸出時直接覆蓋其中的內容;
  • java.io.DataOutputStream的readInt()等方法如果文件不存在的話,則會拋出異常;

帶緩存的輸入流輸出流

  • 帶緩存的輸入流輸出流所對應的類是:java.io.BufferdInputStream 和 java.io.BufferdOutputStream
  • java.io.BufferedInputStream的對象通常是由java.io.FireInputStream的實例對象創建的,其中size是大於0的整數;
public BufferedInputStream(FileInputStream in);//沒有size的話有系統自己指定
public BufferedInputStream(FileInputStream in, int size);
  • java.io.BufferedOutputStream的對象通常是由java.io.FireOutputStream的實例對象創建的,其中size是大於0的整數;
public BufferedOutputStream(FileOutputStream in);//沒有size的話有系統自己指定
public BufferedOutputStream(FileOutputStream in, int size);
  • 帶緩存的輸入輸出流兼容抽象類輸入輸出流的read(),write(),flush()方法。
/**
*對帯與不帶緩存在讀取數據的效率進行對比
*/
public static void main(String[ ] args) {
        try {
            int i, ch;
            i = 0;
            Date d1= new Date( );
            FileInputStream f = new FileInputStream("J_BufferedInputStream.class");
            while ((ch=f.read( )) != -1){
                i++;
            }
            f.close( );
            Date d2= new Date( );

            long t = d2.getTime( ) - d1.getTime( );
            System.out.printf("讀取文件%1$s(共%2$d字節)%n", "J_BufferedInputStream.class", i);
            System.out.printf("不帶緩存的方法需要%1$d毫秒%n", t);

            i = 0;
            d1= new Date( );
            f = new FileInputStream("J_BufferedInputStream.class");
            BufferedInputStream fb = new BufferedInputStream(f);
            while ((ch=fb.read( )) != -1){
                i++;
            }
            fb.close( );
            d2= new Date( );

            t = d2.getTime( ) - d1.getTime( );
            System.out.printf("帶緩存的方法需要%1$d毫秒%n", t);
        } catch (Exception e) {
            System.err.println("發生異常:" + e);
            e.printStackTrace();
        }
    }
    
    /*運行結果:
    讀取文件J_BufferedInputStream.class(共1856字節)
    不帶緩存的方法需要4毫秒
    帶緩存的方法需要1毫秒*/
  • 使用帶緩存的時候讀取的效率大大提高。

標準輸入輸出流的重定向

  • java.lang.System含有三個靜態成員域:
    in(標準輸入流,java.io.InputStream抽象類的對象),主要是接受鍵盤輸入,System.in所指向的對象實際上是java.io.BufferedInputStream的實例對象;
    out(標準輸出流,java.io.Print的對象),控制檯輸出;
    err(標準錯誤輸出流,java.io.Print的對象),控制檯輸出;
  • 重定向即將以上三種輸入輸出位置進行重置
  • java.lang.System有一下三個方法進行重置爲傳進去的參數類型的流
public static void setIn(InputStream in);
public static void setOut(PrintStream in);
public static void setErr(InputStream err);

public static void setIn(new FireInputStream("test.txt"));將輸出文件test.txt中的內容,文件必須事先存在否則拋出異常
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章