JAVASE(十六) IO流 :File類、節點流、緩衝流、轉換流、編碼集、對象流

1、File類型

1.1.File類的理解

  1. File類是在java.io包下
  2. File可以理解成一個文件(.mp3  .mp4 .txt)或者一個目錄
  3. File沒向文件寫入數據的功能。只創建,刪除,文件大小等方法。
  4. File可以理解成流的終端。
  5. 我們經常將File的對象作爲實參傳入到流的構造器中
  6. File 能新建、刪除、重命名文件和目錄,但 File 不能訪問文件內容本身。如果需要訪問文件內容本身,則需要使用輸入/輸出流。

1.2. 如何實例化

File file = new File("H:\\aaa\\abc.txt");
File file = new File("H:/aaa/abc.txt");
new File("H:\\aaa", "abc.txt"); //H:\\aaa\\abc.txt

絕對路徑:包含盤符在內的完整路徑
相對路徑:相對於當前的項目的路徑。

1.3 File 類的常見構造器:

注意:File的靜態屬性String separator存儲了當前系統的路徑分隔符。

            在UNIX中,此字段爲‘/’,在Windows中,爲‘\\’

1.4.常用方法

             

1.5 案例

         

2、IO流概述

2.1概念:

  • I/O是Input/Output的縮寫, I/O技術是非常實用的技術,用於處理設備之間的數據傳輸。如讀/寫文件,網絡通訊等。
  • Java程序中,對於數據的輸入/輸出操作以”流(stream)” 的方式進行。
  • java.io包下提供了各種“流”類和接口,用以獲取不同種類的數據,並通過標準的方法輸入或輸出數據。

2.2 Java IO原理

                                                              

2.3.流的分類

  • 按操作數據單位不同分爲:字節流(8 bit),字符流(16 bit)  
  • 按數據流的流向不同分爲:輸入流,輸出流
  • 按流的角色的不同分爲:節點流,處理流

        

  1. Java的IO流共涉及40多個類,實際上非常規則,都是從如下4個抽象基類派生的。
  2. 由這四個類派生出來的子類名稱都是以其父類名作爲子類名後綴。

圖示:

2.4.流的體系結構(藍色的部分是重點

2.5 輸入流、輸出流

  • 節點流可以從一個特定的數據源讀寫數據

       

  • 處理流是“連接”在已存在的流(節點流或處理流)之上,通過對數據的處理爲程序提供更爲強大的讀寫功能。

        

    

(1)InputStream & Reader

       

(2)OutputStream & Writer

     

3、節點流(文件流)

文件流(1)

           

        FileReader fr = null;
	try{
		fr = new FileReader("c:\\test.txt");
		char[] buf = new char[1024];
		int len= 0;
		while((len=fr.read(buf))!=-1){
			System.out.println(new String(buf ,0,len));}
	}catch (IOException e){
		System.out.println("read-Exception :"+e.toString());}
	finally{
		if(fr!=null){
			try{
				fr.close();
			}catch (IOException e){
		System.out.println("close-Exception :"+e.toString());
			} } }

文件流 (2)

          

        FileWriter fw = null;
	try{
		fw = new FileWriter("Test.txt");
		fw.write("text");
	}
	catch (IOException e){
		System.out.println(e.toString());
	}
	finally{
		If(fw!=null)
		try{
		 fw.close();
		}
		catch (IOException e){
			System.out.println(e.toString());
            }	
        }

注意:

  • 定義文件路徑時,注意:可以用“/”或者“\\”。
  • 在寫入一個文件時,如果目錄下有同名文件將被覆蓋。
  • 在讀取文件時,必須保證該文件已存在,否則出異常。

字節流:

FileInputStream fis = null;
        FileOutputStream fos = null;
        try {
            //1.創建File對象
            File file = new File("char8.txt");
            File file2 = new File("char9.txt");
            //2.創建流的對象
            fis = new FileInputStream(file);
            fos = new FileOutputStream(file2);
            //3.讀內容和寫內容
            byte[] b = new byte[1024];
            int len = 0;
            while ((len = fis.read(b)) != -1) {
                //將數組中的內容寫到目標文件中
                fos.write(b, 0, len);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            //4.關流
            try {
                if(fos != null){
                    fos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(fis != null){
                    fis.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

字符流:

/*
	 * FileWriter
	 */
	@Test
	public void test3() throws Exception{
		
		FileWriter writer = new FileWriter("jjj.txt");
		
		writer.write("中國你好我愛你麼麼噠".toCharArray());
		
		writer.close();
	}
	
	/*
	 * FileReader : 讀取中文不會發生亂碼的問題
	 */
	@Test
	public void test() throws Exception{
		
		FileReader reader = new FileReader("aaa.txt");
		
		char[] c = new char[500];
		int len = 0;
		while((len = reader.read(c)) != -1){
//			System.out.println(new String(c, 0, len));
			for (int i = 0; i < len; i++) {
				System.out.println(c[i]);
			}
		}
		
		reader.close();
	}

4、緩衝流的使用

爲了提高數據讀寫的速度,Java API提供了帶緩衝功能的流類,在使用這些流類時,會創建一個內部緩衝區數組

 

根據數據操作單位可以把緩衝流分爲:

  • BufferedInputStream 和 BufferedOutputStream
  • BufferedReader 和 BufferedWriter

緩衝流要“套接”在相應的節點流之上,對讀寫的數據提供了緩衝的功能,提高了讀寫的效率,同時增加了一些新的方法

對於輸出的緩衝流,寫出的數據會先在內存中緩存,使用flush()將會使內存中的數據立刻寫出

        

4.1 處理流之一:緩衝流

                File descFile = new File(desc);
		File srcFile = new File(src);
		
		FileInputStream fis = new FileInputStream(srcFile);
		BufferedInputStream bis = new BufferedInputStream(fis);
		
		
		FileOutputStream fos = new FileOutputStream(descFile);
		BufferedOutputStream bos = new BufferedOutputStream(fos);
		
		
		byte[] b = new byte[1024];
		int len = 0;
		while((len = bis.read(b)) != -1){
			bos.write(b, 0, len);
		}
		
		
		bos.close();
		bis.close();
		fis.close();
		fos.close();

 

        /*
	 * BufferedWriter
	 */
	@Test
	public void test2() throws Exception{
		FileWriter writer = new FileWriter("cdf.txt");
		
		BufferedWriter bw = new BufferedWriter(writer);
		
		bw.write("圓圓麼麼噠");
		
		bw.close();
		writer.close();
	}

	
	/*
	 * BufferedReader
	 */
	@Test
	public void test() throws Exception{
		
		FileReader reader = new FileReader("aaa.txt");
		//創建緩衝字符流
		BufferedReader br = new BufferedReader(reader);
		
		/*
		 * 第一種讀取文件內容
		 */
//		char[] c = new char[100];
//		int len = 0;
//		while((len = br.read(c)) != -1){
//			System.out.println(new String(c,0,len));
//		}
		
		/*
		 * 第二種讀取文件內容
		 * readLine() : 讀取一行
		 */
		String str="";
		while((str = br.readLine()) != null){
			System.out.println(str);
		}
		
		br.close();
		reader.close();
	}

5、轉換流的使用

作用:

  1. 將讀取文件的字節流轉換成字符流,將寫入文件內容的字符流轉成字節流
  2. 轉換編碼集 (讀入的文件比如是UTF-8,寫入的文件的可以變成GBK
  3. 注意:InputStreamReader設置的編碼集必須和讀取文件的編碼集是一致的。

         

         

           

代碼:

                // 讀取的文件
		File file = new File("demo.txt");
		// 創建一個字節流,對接在demo.txt上
		FileInputStream fis = new FileInputStream(file);
		// 創建一個轉換流 - 字節轉字符
		InputStreamReader isr = new InputStreamReader(fis);

		// 寫入的文件
		File file2 = new File("demo2.txt");
		// 創建一個字節流,對接在demo2.txt上
		FileOutputStream fos = new FileOutputStream(file2);
		// 創建一個轉換流 - 字符轉字節
		OutputStreamWriter osw = new OutputStreamWriter(fos);

		char[] c = new char[1024];
		int len = 0;
		while ((len = isr.read(c)) != -1) {
			osw.write(c, 0, len);
		}

		osw.close();
		isr.close();
		fos.close();
		fis.close();

圖示:

                

6、字符編碼集

        

         

7、其他流的使用:標準輸入輸出流、打印流

7.1 標準輸入輸出流

  • System.in和System.out分別代表了系統標準的輸入和輸出設備
  • 默認輸入設備是鍵盤,輸出設備是顯示器
  • System.in的類型是InputStream
  • System.out的類型是PrintStream,其是OutputStream的子類FilterOutputStream 的子類
  • 通過System類的setIn,setOut方法對默認設備進行改變。    
            public static void setIn(InputStream in)
            public static void setOut(PrintStream out)

代碼示例:

    /*
     * 從鍵盤輸入字符串,要求將讀取到的整行字符串轉成大寫輸出。然後繼續進行輸入操作,
     * 直至當輸入“e”或者“exit”時,退出程序。
     */
    @Test
    public void test2() throws Exception{
        /*
         * 1.從控制檯讀取數據
         * 2.將字節流轉成字符流
         * 3.使用緩衝流
         */
         //將字節流轉換成字符流
        InputStreamReader isr = new InputStreamReader(System.in);
        //創建字符緩衝流
        BufferedReader br = new BufferedReader(isr);
        while(true){
            //讀取控制檯上的數據
            String str = br.readLine();
            //判斷如果是"e"/"exit"那麼就退出程序,否則全部轉成大寫並輸出
            if("e".equalsIgnoreCase(str) || "exit".equalsIgnoreCase(str)){
                //關流
                br.close();
                isr.close();
                return;
            }else{
                System.out.println(str.toUpperCase());
            }
        }
    }

7.2 打印流

      

代碼:

@Test
    public void test() {
        /*
         * 第一步 創建一個連接text.txt的管道
         * 第二步  將輸入到控制檯的管道改成輸入到text.txt
         * 第步  輸入內容
         */
        FileOutputStream fos = null;
        try {
            //創建一個輸出流
            fos = new FileOutputStream(new File("text.txt"));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        
        // 創建打印輸出流,設置爲自動刷新模式(寫入換行符或字節 '\n' 時都會刷新輸出緩衝區)
        PrintStream ps = new PrintStream(fos, true);
        
        
        
        /*
         * 第二步  將輸入到控制檯的管道改成輸入到text.txt
         */
        // 把標準輸出流(控制檯輸出)改成文件
        System.setOut(ps);  //在程序運行時只能設置一次。

        
        /*
         *  第步  輸入內容
         */
        for (int i = 0; i <= 10; i++) {
            System.out.print("a");
        }
        
        ps.close();

    }

7.3 數據流

          

代碼:

    /*
     * 輸入流
     *
     * 注意 : 寫入數據的格式  和 讀取數據的格式必須一致
     */
    @Test
    public void test() throws Exception{
        
        FileInputStream fis = new FileInputStream("abc.txt");
        DataInputStream dis = new DataInputStream(fis);
        
        
        String readUTF = dis.readUTF();
        int readInt = dis.readInt();
        boolean boo = dis.readBoolean();
        
        System.out.println(readUTF);
        System.out.println(readInt);
        System.out.println(boo);
        
        dis.close();
        fis.close();
        
    }
    
    /*
     * 輸出流
     */
    @Test
    public void test2() throws Exception{
        FileOutputStream out = new FileOutputStream("abc.txt");
        DataOutputStream dos = new DataOutputStream(out);
        
        dos.writeUTF("abcde");
        dos.writeInt(10);
        dos.writeBoolean(true);
        
        
        dos.close();
        out.close();
    }

7.4 對象流的使用

序列化 :用ObjectOutputStream類保存基本類型數據或對象的機制 (保存對象,或者發送對象)
反序列化 用ObjectInputStream類讀取基本類型數據或對象的機制(讀取對象,接收對象)

* 注意:

  1. 序列化對象的類必須實現Serializable接口
  2. 序列化對象的類的屬性除基本類型外,也必須全部實現Serializable接口
  3. 需要聲明一個 serialVersionUID (如果不顯示聲明系統會默認填加一個)
  4. 不能序列化static和transient修飾的成員變量

代碼:

        /*
	 * ObjectInputStream
	 */
	@Test
	public void test() throws Exception{
		FileInputStream fis = new FileInputStream("aaa.txt");
		ObjectInputStream ois = new ObjectInputStream(fis);
		
		Person p = (Person) ois.readObject();
		p.show();
		Person p2 = (Person) ois.readObject();
		p2.show();
		
		
		
		ois.close();
		fis.close();
		
	}
	/*
	 * ObjectOutputStream
	 */
	@Test
	public void test2() throws Exception{
	
		FileOutputStream fos = new FileOutputStream("aaa.txt");
		ObjectOutputStream oos = new ObjectOutputStream(fos);
		
		//寫數據
		oos.writeObject(new Person("aa",18,new Address("aaaa",20)));
		oos.writeObject(new Person("bb",18,new Address("bbbb",20)));
		
		oos.close();
		
	}

9、RandomAccessFile類的使用

需求:
文件中的內容 : abcdefg   
需求:  在c的後面插入AAA

  1. 先將指針移動到c的後面
  2. 讀取c後面的所數據並保存到一個臨時變量中
  3. 指針回移,移動到c的後面
  4. 寫入需要插入的數據
  5. 寫入臨時變量中的數據

代碼

        @Test
	public void test4() throws Exception{
		RandomAccessFile accessFile = new RandomAccessFile("access.txt", "rw");
		//移動指針到c後面
		accessFile.seek(3);
		//將c後面的數據讀出並保存到一個臨時變量中。
//		String str = accessFile.readLine();
		String str = "";
		//讀取插入位置後面的所內容
		byte[] b = new byte[1024];
		int len = 0;
		while((len = accessFile.read(b)) != -1){
			str += new String(b,0,len);
		}
		//指針回移
		accessFile.seek(3);
		//插入數據
		accessFile.write("AAA".getBytes());
		accessFile.write(str.getBytes());
		//關流
		accessFile.close();
	}
發佈了224 篇原創文章 · 獲贊 60 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章