天天看點

IO常用流及檔案總結

一、 java.io.File類的使用

二、 IO原理及流的分類

三、 節點流(或檔案流)

FileInputStream  /  FileOutputStream  /  FileReader  /  FileWriter

四、 處理流之一:緩沖流

BufferedInputStream / BufferedOutputStream

BufferedReader / BufferedWriter

五、 處理流之二:轉換流

InputStreamReader  /  OutputStreamWriter

六、 處理流之三:标準輸入/輸出流

System.in / System.out

七、處理流之:四列印流

PrintStream  /  PrintWriter

八、處理流之:五資料流

DataInputStream  /  DataOutputStream

九、處理流之六對象流 (涉及序列化、反序列化)

ObjectInputStream  /  ObjectOutputStream

十、 随機存取檔案流

RandomAccessFile

一、File類的使用

  •  java.io.File類:檔案和目錄路徑名的抽象表示形式,與平台無關
  •  File 能建立、删除、重命名檔案和目錄,但 File 不能通路檔案内容本身。如果需要通路檔案内容本身,則需要使用輸入/輸出流。(一般我們都會将File作為參數傳入到IO流對象的構造器中。)
  •  File對象可以作為參數傳遞給流的構造器

1)、通路檔案名

getName()

getPath()

getAbsoluteFile()

getAbsolutePath()

getParent()

toPath()

renameTo(File newName)

2) 、檔案檢測

exists()

canWrite()

canRead()

isFile()

isDirectory()

3) 、擷取正常檔案資訊

lastModified()

length()

4) 、檔案操作相關

createNewFile()

delete()

5) 、目錄操作相關

mkdir()

mkdirs()

delete()

list()

listFiles()

注1):

絕對路徑 :包含盤符在内的完整路徑

相對路徑 :相對某個項目的路徑

renameTo(File newName) : 在同一個目錄下:進行操作 - 可以重命名

不同的目錄下:将目前檔案移動到新的目錄下然後重命名為   newName

注3):

lastModified() //擷取最後一次修改的時間

length() //檔案大小

注5):

mkdir() //建立目錄,如果父目錄存在則建立成功,否則建立失敗

mkdirs() //建立目錄,無論是否是父目錄都會建立成功

delete() //删除目錄

list() //以String類型傳回  目錄下的  所有檔案和目錄名

listFiles() //以File類型的方式傳回 目錄下 所有的檔案和目錄。

@Test

public void test(){

File file = new File("D:\\io\\io\\a\\a");

File file2 = new File("D:\\io\\io\\b\\b");

File file3 = new File("D:\\io");

String[] list = file3.list();

for (String string : list) {

System.out.println(string);

}

System.out.println("--------------------------");

File[] listFiles = file3.listFiles();

for (File file4 : listFiles) {

System.out.println(file4);

}

}
           

二、 IO流原理及流的分類

IO常用流及檔案總結

1、IO流的原理

輸入input:讀取外部資料(磁盤、CD光牒等儲存設備的資料)到程式(記憶體)中。

輸出output:将程式(記憶體)資料輸出到磁盤、CD光牒等儲存設備中

注:IO流是以程式為中心

IO常用流及檔案總結

2、流的分類

l 按操作資料機關不同分為:位元組流(8 bit),字元流(16 bit)  

l 按資料流的流向不同分為:輸入流,輸出流

l 按流的角色的不同分為:節點流,處理流

Java的IO流共涉及40多個類,實際上非正常則,都是從如下4個抽象基類派生的。由這四個類派生出來的子類名稱都是以其父類名作為子類名字尾。

IO常用流及檔案總結

節點流和處理流

l 節點流可以從一個特定的資料源讀寫資料

l 處理流是“連接配接”在已存在的流(節點流或處理流)之上,通過對資料的處理為程式提供更為強大的讀寫功能

注:處理流/過濾流 有:緩沖流,轉換流

IO常用流及檔案總結

InputStream & Reader

1)、InputStream 和 Reader 是所有輸入流的基類。

2)、InputStream:位元組流(典型實作:FileInputStream)

(1) int read()

(2) int read(byte[] c)

(3) int read(byte[] c, int off, int len)

3)、Reader:字元流(典型實作:FileReader)

(4) int read()

(5) int read(char [] c)

(6) int read(char [] c, int off, int len)

4)、程式中打開的檔案 IO 資源不屬于記憶體裡的資源,垃圾回收機制無法回收該資源,是以應該顯式關閉檔案 IO 資源

OutputStream & Writer

OutputStream 和 Writer 也非常相似:

void write(int b/int c);

void write(byte[] b/char[] cbuf);

void write(byte[] b/char[] buff, int off, int len);

void flush();

void close(); 需要先重新整理,再關閉此流

注:因為字元流直接以字元作為操作機關,是以 Writer 可以用字元串來替換字元數組,即以 String 對象作為參數

void write(String str);

void write(String str, int off, int len);

三、節點流(檔案流)

    所有的檔案在硬碟或在傳輸時都是以位元組的方式進行的,包括圖檔等都是按位元組的方式存儲的,而字元是隻有在記憶體中才會形成,是以在開發中,位元組流使用較為廣泛。

   而且注意緩沖區是指在記憶體中,是以位元組流可以位元組操作文本而不需要經過緩存,即不用考慮關流也可以輸出内容,但字元流需要在記憶體中緩存,當關閉字元流時緩存區裡的内容才會輸出,否則不會輸出結果,即字元流使用了緩沖區,而位元組流沒有使用緩沖區。

另:如果是音頻檔案、圖檔、歌曲,就用位元組流好點,如果是關系到中文(文本)的,用字元流好點

1)、讀取檔案步驟:

1.建立一個流對象,将已存在的一個檔案加載進流。

FileReader fr = new FileReader(“Test.txt”);

2.建立一個臨時存放資料的數組。

char[] ch = new char[1024];

3.調用流對象的讀取方法将流中的資料讀入到數組中。

fr.read(ch);

2)、寫入檔案

1.建立流對象,建立資料存放檔案

FileWriter fw = new FileWriter(“Test.txt”);

2.調用流對象的寫入方法,将資料寫入流

fw.write(“text”); 

3.關閉流資源,并将流中的資料清空到檔案中。

fw.close();

注:

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

注:位元組流和字元流的使用:

  1.字元流常用來展示一些文本資訊

  2.位元組流一般用來複制檔案,複制中文文本是不會出現亂碼的

IOTest.java

public class IOTest {
	/*
	 * 位元組流和字元流的使用:
	 * 1.字元流用來展示一些文本資訊
	 * 2.位元組流一般用來複制檔案,複制中文文本是不會出現亂碼的
	 */
	/*
	 * 字元流
	 */
	@SuppressWarnings("resource")
	@Test
	public void test() throws IOException{
		
		//第一步建立File對象
		//第二步建立流的對象
		//建立一個輸入流
		FileReader fr = new FileReader(new File("aaa.txt"));
		//建立一個輸出流
		FileWriter fw = new FileWriter(new File("bbb.txt"));
		//第三步讀取資料
		char[] c = new char[100];
		int len = 0;
		while((len = fr.read(c))!= -1){
//		輸出1、	System.out.println(new String(c,0,len));
//		輸出2、	for (int i = 0; i < len; i++) {
//					System.out.print(c[i]);
//				}
			
			fw.write(c, 0, len);
		}		
		//第四步關流
		fr.close();
		fw.close();
	}
	/*
	 * 位元組流
	 */
	@Test
	public void test2() throws Exception{
		FileInputStream fis = new FileInputStream(new File("char8.txt"));
		FileOutputStream fos = new FileOutputStream(new File("char9.txt"));
		
		byte[] b = new byte[1024];
		int len = 0;
		while((len = fis.read(b)) != -1){
//		輸出1、	System.out.println(new String(b,0,len));
//		輸出2、	for (int i = 0; i < len ; i++) {
//				System.out.print((char)b[i]);			
//			}
	
			fos.write(b, 0, len);
		}
		
		fis.close();
		fos.close();
		
	}
	
}
           

四、處理流之一 :緩沖流

1、為了提高資料讀寫的速度,Java API提供了帶緩沖功能的流類,在使用這些流類時,會建立一個内部緩沖區數組

2、對于輸出的緩沖流,寫出的資料會先在記憶體中緩存,使用flush()将會使記憶體中的資料立刻寫出

3、根據資料操作機關可以把緩沖流分為:

BufferedInputStream 和 BufferedOutputStream

BufferedReader 和 BufferedWriter

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

注意:1)、關閉過濾流時,會自動關閉它所包裝的底層節點流。但是我們最好還是要手動關閉位元組流,應該如果位元組流發生異常,我們需要處理,而包裝在過濾流中可能就找不到包錯的地方了。

2)、這裡在讀取檔案時必須保證檔案已存在

IOTest2.java

public class IOTest2 {

	/*
	 * 緩沖流
	 */
	@SuppressWarnings("resource")
	@Test
	public void test() {
		BufferedReader br = null;
		FileReader fr = null;
		FileWriter fw = null;
		BufferedWriter bw = null;
	 

		try {
			File file = new File("aaa.txt");
			// 建立流
			fr = new FileReader(file);
			// 建立緩沖流
			br = new BufferedReader(fr);

			// 建立流
			fw = new FileWriter(new File("fff.txt"));
			// 建立緩沖流
			bw = new BufferedWriter(fw);

			// 一邊讀一邊寫
			char[] c = new char[100];
			int len = 0;
			while ((len = br.read(c)) != -1) {
				bw.write(c, 0, len);
			}
		} catch (Exception e) {
			// TODO: handle exception
		} finally {
			// 關流
			if (bw != null) {
				try {
					bw.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			if (br != null) {
				try {
					br.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			if (fw != null) {
				try {
					fw.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			if (fr != null) {
				try {
					fr.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}

		}

	}

	/*
	 * readLine() : 讀取一行字元
	 */
	@Test
	public void test2() throws Exception {
		BufferedReader br = null;
		FileReader fr = null;
		FileWriter fw = null;
		BufferedWriter bw = null;

		File file = new File("fff.txt");
		// 建立流
		fr = new FileReader(file);
		// 建立緩沖流
		br = new BufferedReader(fr);

		// 建立流
		fw = new FileWriter(new File("eee.txt"));
		// 建立緩沖流
		bw = new BufferedWriter(fw);

		// 一邊讀一邊寫
//		String string = br.readLine();
//		System.out.println(string);
//		System.out.println(br.readLine());
		
		String str = null;
		while((str = br.readLine()) != null){
			bw.write(str);
			bw.newLine();
		}
		//關流
		bw.close();
		br.close();
		fw.close();
		fr.close();

	}
}
           

 五、處理流之二:轉換流

轉換流提供了在位元組流和字元流之間的轉換

Java API提供了兩個轉換流:

InputStreamReader和OutputStreamWriter

位元組流中的資料都是字元時,轉成字元流操作更高效。

Reader和Writer最重要的子類是InputStreamReader和OutputStreamWriter類。

InputStreamReader類包含了一個底層輸入流,可以從中讀取原始位元組。它根據指定的編碼方式,将這些位元組轉換為Unicode字元。

OutputStreamWriter從運作的程式中接收Unicode字元,然後使用指定的編碼方式将這些字元轉換為位元組,再将這些位元組寫入底層輸出流中。

作用一

1)、InputStreamReader:用于将 位元組流中讀取到的位元組 按指定字元集解碼成字元。

2)、OutputStreamWriter:用于将 要寫入到位元組流中的字元 按指定字元集編碼成位元組。

 構造方法

public InputStreamReader(InputStream in)

public InputSreamReader(InputStream in, String charsetName)

 構造方法

public OutputStreamWriter(OutputStream out)

public OutputSreamWriter(OutputStream out,String charsetName)

作用二

 注意一下這個标紅的是可以在轉換的過程指定要轉化的編碼集

IO常用流及檔案總結

InputStreamTest.java

public class InputStreamTest {
	/*
	 * InputStreamReader
	 * 兩個作用:
	 * 1.可以将位元組流轉換成字元流
	 * 2.可以改變文本的編碼集- 比如讀取檔案是gbk那麼寫出的檔案可以轉成utf-8
	 */
	@Test
	public void test() throws Exception{
		
		File file = new File("fff.txt");
		FileInputStream fis = new FileInputStream(file);
		InputStreamReader isr = new InputStreamReader(fis);	
		//BufferedReader br = new BufferedReader(isr);	
		
		
		char[] c = new char[100];
		int len = 0;
		while((len = isr.read(c)) != -1){
			for (int i = 0; i < len; i++) {
				System.out.print(c[i]);
			}
		}
		
		isr.close();
		fis.close();
	}
	/*
	 * 一邊讀一邊寫
	 */
	@Test
	public void test2() throws Exception{
		
		File file = new File("char8.txt");
		FileInputStream fis = new FileInputStream(file);
		/*
		 * InputStreamReader(InputStream in, String charsetName)
		 * 
		 * charsetName :編碼集
		 * 
		 * 注意:讀取的檔案的編碼集必須和charsetName編碼集格式一緻
		 */
		InputStreamReader isr = new InputStreamReader(fis,"gbk");
		File file2 = new File("xiaocang2.txt");
		FileOutputStream fos = new FileOutputStream(file2);
		OutputStreamWriter osw = new OutputStreamWriter(fos,"utf-8");
		
		
		char[] c = new char[100];
		int len = 0;
		while((len = isr.read(c)) != -1){
			osw.write(c, 0, len);
		}
		
		osw.close();
		isr.close();
		fos.close();
		fis.close();
	}
}
           

什麼時候用轉化流?

1)、源裝置或目标裝置是位元組流,但是操作的卻是文本資料

2)、一旦操作文本涉及到具體的指定編碼表時,必須使用轉換流

另: 

常見的字元編碼表:

  • ASCII:美國标準資訊交換碼。

    用一個位元組的7位可以表示。

  • ISO8859-1:拉丁碼表。歐洲碼表

    用一個位元組的8位表示。

  • GB2312:中國的中文編碼表。
  • GBK:中國的中文編碼表更新,融合了更多的中文文字元号。
  • Unicode:國際标準碼,融合了多種文字。

    所有文字都用兩個位元組來表示,Java語言使用的就是unicode

  • UTF-8:最多用三個位元組來表示一個字元
  1. 編碼:字元串→位元組數組
  2. 解碼:位元組數組→字元串

六、處理流之三:标準輸入/輸出流

  • System.in和System.out分别代表了系統标準的輸入和輸出裝置

        預設輸入裝置是鍵盤,輸出裝置是顯示器

  • System.in的類型是InputStream,System.out的類型是PrintStream,其是FilterOutputStream 的子類、OutputStream的子類
  • 通過System類的setIn,setOut方法對預設裝置進行改變。

    public static void setIn(InputStream in)

    public static void setOut(PrintStream ou)

SystemTes.java

public class SystemTest {

	@Test
	public void test(){
		
		System.out.println("aaaa");
		
		new Scanner(System.in);
	}
	
	/*
	 * 從鍵盤輸入字元串,要求将讀取到的整行字元串轉成大寫輸出。
	 * 然後繼續進行輸入操作,直至當輸入“e”或者“exit”時,退出程式。
	 */
	@Test
	public void test2() throws Exception{
		//建立一個轉換流
		InputStreamReader isr = new InputStreamReader(System.in);
		//建立一個緩沖流
		BufferedReader br = new BufferedReader(isr);
		
		String str = null;
		
		while((str = br.readLine()) != null){
			if("e".equalsIgnoreCase(str) || "exit".equalsIgnoreCase(str)){
				//關流
				br.close();
				isr.close();
				return;
			}else{
				System.out.println(str.toUpperCase());
			}
		}
		
		br.close();
		isr.close();
	}
}
           

七、處理流之四:列印流

  • 實作将基本資料類型的資料格式轉化為字元串輸出
  • 列印流:PrintStream和PrintWriter提供了一系列重載的print和println方法,用于多種資料類型的輸出
  • PrintStream和PrintWriter的輸出不會抛出異常
  • PrintStream和PrintWriter有自動flush功能
  • System.out傳回的是PrintStream的執行個體

PrintStreamTest.java

public class PrintStreamTest {

	@Test
	public void test() {
		FileOutputStream fos = null;
		try {
			fos = new FileOutputStream(new File("text.txt"));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} 
		
		// 建立列印輸出流,設定為自動重新整理模式(寫入換行符或位元組 '\n' 時都會重新整理輸出緩沖區)
		PrintStream ps = new PrintStream(fos, true);
		if (ps != null) { 
			// 把标準輸出流(控制台輸出)改成檔案
			System.setOut(ps);
		}
		for (int i = 0; i <= 255; i++) { // 輸出ASCII字元
			System.out.print("A");
			if (i % 50 == 0) { // 每50個資料一行
				System.out.println(); // 換行
			}
		}
		ps.close();

	}
}
           

八、處理流之五:資料流

  • 為了友善地操作Java語言的基本資料類型的資料,可以使用資料流。
  • 資料流有兩個類:(用于讀取和寫出基本資料類型的資料)

        DataInputStream 和 DataOutputStream

        分别“套接”在 InputStream 和 OutputStream 節點流上

  • DataInputStream中的方法

     boolean readBoolean() byte readByte()

     char readChar()         float readFloat()

     double readDouble()         short readShort()

     long readLong()         int readInt()

     String readUTF()                         void readFully(byte[] b)

  • DataOutputStream中的方法

        将上述的方法的read改為相應的write即可。

DataTest.java

public class DataTest {

	@Test
	public void test() throws Exception{
		
		FileInputStream fis = new FileInputStream(new File("ccc.dat"));
		DataInputStream dis = new DataInputStream(fis);
		
		
		String string = dis.readUTF();
		double readDouble = dis.readDouble();
		boolean readBoolean = dis.readBoolean();
		int readInt = dis.readInt();
		
		System.out.println(readDouble);
		System.out.println(readBoolean);
		System.out.println(readInt);
		System.out.println(string);
		
		dis.close();
		fis.close();
		
	}

	@Test
	public void test2() throws Exception{
		
		FileOutputStream fos = new FileOutputStream(new File("ccc.dat"));
		DataOutputStream dos = new DataOutputStream(fos);
		
		dos.writeUTF("abcdef");
		dos.writeDouble(12.3);
		dos.writeBoolean(true);
		dos.writeInt(15);
		
		
		dos.close();
		fos.close();
	}
}
           

九、處理流之六:對象流

  • ObjectInputStream和OjbectOutputSteam

            用于存儲和讀取基本資料類型資料或對象的處理流。 它的強大之處就是可以把Java中的對象寫入到資料源中, 也能把對象從資料源中還原回來。

  • 序列化:用ObjectOutputStream類儲存基本類型資料或對象的機制
  • 反序列化:用ObjectInputStream類讀取基本類型資料或對象的機制
  • ObjectOutputStream和ObjectInputStream不能序列化static修飾的成員變量
  • 對象序列化機制允許把記憶體中的Java對象轉換成平台無關的二進制流,進而允許把這種二進制流持久地儲存在磁盤上,或通過網絡将這種二進制流傳輸到另一個網絡節點。當其它程式擷取了這種二進制流,就可以恢複成原來的Java對象
  • 序列化的好處在于可将任何實作了Serializable接口的對象轉化為位元組資料,使其在儲存和傳輸時可被還原
  • 序列化是 RMI(Remote Method Invoke – 遠端方法調用)過程的參數和傳回值都必須實作的機制,而 RMI 是 JavaEE 的基礎。是以序列化機制是 JavaEE 平台的基礎
  • 如果需要讓某個對象支援序列化機制,則必須讓其類是可序列化的,為了讓某個類是可序列化的,該類必須實作如下兩個接口之一:

            Serializable

            Externalizable

  • 凡是實作Serializable接口的類都有一個表示序列化版本辨別符的靜态變量:

    private static final long serialVersionUID;

    serialVersionUID用來表明類的不同版本間的相容性

  •     如果類沒有顯示定義這個靜态變量,它的值是Java運作時環境根據類的内部細節自動生成的。若類的源代碼作了修改,serialVersionUID 可能發生變化。故建議,顯示聲明
  • 顯示定義serialVersionUID的用途:

        希望類的不同版本對序列化相容,是以需確定類的不同版本具有相同的serialVersionUID

        不希望類的不同版本對序列化相容,是以需確定類的不同版本具有不同的serialVersionUID

    強調:如果某個類的字段不是基本資料類型或 String  類型,而是另一個引用類型,那麼這個引用類型必須是可序列化的,否則擁有該類型的 Field 的類也不能序列化

1)、序列化

若某個類實作了 Serializable 接口,該類的對象就是可序列化的:

建立一個 ObjectOutputStream

調用 ObjectOutputStream 對象的 writeObject(對象) 方法 輸出可序列化對象。 注意寫出一次,操作flush()

2)、反序列化

建立一個 ObjectInputStream

調用 readObject() 方法 讀取流中的對象

person.java

/*
 * 序列化:用ObjectOutputStream類儲存基本類型資料或對象的機制
 * 反序列化:用ObjectInputStream類讀取基本類型資料或對象的機制
 */
public class ObjectTest {
	@Test
	public void test2() throws Exception{
		
		FileInputStream fis = new FileInputStream("abc.txt");
		ObjectInputStream ois = new ObjectInputStream(fis);
		
		Person p = (Person) ois.readObject();
		System.out.println(p.toString());
		
		ois.close();
		fis.close();		
	}
	
	/*
	 * 要求:
	 * 1.需要被序列化對象的類,必須實作Serializable接口。
	 * 類中的屬性除基本類型外也需要實作Serializable接口
	 * 2.private static final long serialVersionUID;用來表明類的不同版本間的相容性
	 * 實體類中可以省略,系統會自動生成
	 */
	@Test
	public void test() throws Exception{
		FileOutputStream fos = new FileOutputStream("abc.txt");
		ObjectOutputStream oos = new ObjectOutputStream(fos);
		
		Person person = new Person(18, "小容" ,new Address("110"));
		oos.writeObject(person);
		
		oos.close();
		fos.close();
	}
}
           

注:test()中通過序列化寫入文本中一個對象,但文本中顯示的是亂碼,需要通過test2()反序列化輸出到控制台就可以看到完整内容了

十、随機存取檔案流

  • RandomAccessFile 類支援 “随機通路” 的方式,程式可以直接跳到檔案的任意地方來讀、寫檔案

    支援隻通路檔案的部分内容

    可以向已存在的檔案後追加内容

  • RandomAccessFile 對象包含一個記錄指針,用以标示目前讀寫處的位置。RandomAccessFile 類對象可以自由移動記錄指針:

    long getFilePointer():擷取檔案記錄指針的目前位置

    void seek(long pos):将檔案記錄指針定位到 pos 位置

  • RandomAccessFile 類支援 “随機通路” 的方式,程式可以直接跳到檔案的任意地方來讀、寫檔案

    支援隻通路檔案的部分内容

    可以向已存在的檔案後追加内容

  • RandomAccessFile 對象包含一個記錄指針,用以标示目前讀寫處的位置。RandomAccessFile 類對象可以自由移動記錄指針:

    long getFilePointer() :擷取檔案記錄指針的目前位置

    void seek(long pos) :将檔案記錄指針定位到 pos 位置

RandomAccessTest.java

/*
 * 随機存取檔案流 :即可以讀也可以寫
 * 
 * 
 */
public class RandomAccessTest {

	/*
	 * 讀
	 */
	@Test
	public void test() throws Exception{
		RandomAccessFile raf = new RandomAccessFile("AA.txt", "rw");
		byte[] b = new byte[100];
		int len = 0;
		while((len = raf.read(b)) != -1){
			System.out.println(new String(b,0,len));
		}
		raf.close();
	}
	
	/*
	 * 寫
	 */
	@Test
	public void test2() throws Exception{
		RandomAccessFile raf = new RandomAccessFile("AA.txt", "rw");
		raf.write("hello heng".getBytes());
		raf.close();
	}
	/*
	 * 實作檔案内容的插入
	 * 功能 :在abcdefg 的 b和c的位置插入AAA,在一行的插入文本
	 */
	@Test
	public void test3() throws Exception{
		RandomAccessFile raf = new RandomAccessFile("BB.txt", "rw");
		//第一步  移動指針到c的位置
		raf.seek(2);
		//第二步  讀取c到最後的資料。注意:指針會移到最後
		String str = raf.readLine();
		//第三步 指針回移
		raf.seek(2);
		//第四步 寫插入的内容
		raf.write("AAA".getBytes());
		//第五步 寫讀取的内容
		raf.write(str.getBytes());
		//第六步 關流
		raf.close();
	}
	
	/*
	 *  功能 :在
	 *  abcdefg
	 *  bbb
	 *  ccc
	 *  dd
	 *  的 b和c的位置插入AAA
	 *  在多行文本的插入
	 */
	@Test
	public void test4() throws Exception{
		RandomAccessFile raf = new RandomAccessFile("BB.txt", "rw");
		//第一步  移動指針到c的位置
		raf.seek(2);
		//第二步  讀取c到最後的資料。注意:指針會移到最後
		String str = "";
		byte[] b = new byte[100];
		int len = 0;
		while((len = raf.read(b)) != -1){
			str += new String(b,0,len);
		}
		
		//第三步 指針回移
		raf.seek(2);
		//第四步 寫插入的内容
		raf.write("AAA".getBytes());
		//第五步 寫讀取的内容
		raf.write(str.getBytes());
		//第六步 關流
		raf.close();
	}
}