Java學習之I/O流

今天我給大家分享一下Java的I/O流的學習總結。

I/O流:指的是對文件的數據進行讀取和寫出操作,分別爲InputStream(輸入)和OutputStream(輸出)。

  • InputStream輸入:指的是將文件中的數據,從外部的存儲設備中的數據,通過程序操作,將數據讀取到內存中進行數據信息的處理。
  • OutputStream輸出:指的是將程序執行過程中的數據信息,進行持久化。將數據保存下來,用文件進行記錄,從內存到外部去輸出。

I/O流的分類

I/O{{InputStream{InputStreamReaderByteArrayInputStreamDataInputStreamObjectInputStreamOutputStream{OutputStreamReaderByteArrayOutputStreamDataOutputStreamObjectOutputStreamPrintStream{Reader{BufferedReaderInputStreamReaderWriter{BufferedWriterOutputStreamWriterPrintWriter I/O流 \begin{cases} 字節流 \begin{cases} \bf{InputStream} \begin{cases} \bf{InputStreamReader} \\ \bf{ByteArrayInputStream} \\ \bf{DataInputStream} \\ \bf{ObjectInputStream} \\ \end{cases} \\ \bf{OutputStream} \begin{cases} \bf{OutputStreamReader} \\ \bf{ByteArrayOutputStream} \\ \bf{DataOutputStream} \\ \bf{ObjectOutputStream} \\ \bf{PrintStream} \\ \end{cases} \\ \end{cases} \\ 字符流 \begin{cases} \bf{Reader} \begin{cases} \bf{BufferedReader} \\ \bf{InputStreamReader} \\ \end{cases}\\ \bf{Writer} \begin{cases} \bf{BufferedWriter} \\ \bf{OutputStreamWriter} \\ \bf{PrintWriter} \\ \end{cases}\\ \end{cases} \\ \end{cases}

I/O流的具體分類

字節流:字節輸入流、字節輸出流

  • 字節輸入流:InputStream    實現類:FileInputStream
  • 字節輸出流:OutputStream   實現類:FileOutputStream
File file = new File("./log.txt");
//流對象創建之後,該流就已經處於打開狀態。數據讀完後要關閉流。
//意義:釋放流對象所佔用的資源、文件
InputStream stream = new FileInputStream(file);
byte[] bts = new byte[3];
stream.read(bts);
System.out.println(new String(bts));	//log.txt文件的內容爲:你abc,此時輸出爲:你

OutputStream stream = new FileOutputStream(file);
//沒有追加,表示數據會覆蓋原有的數據
byte[] bts = {99,100,101,102};
stream.write(bts);
stream.close();		//log.txt文件的內容爲:你abc,修改後文件內容爲:cdef

OutputStream stream1 = new FileOutputStream(file1, true);
stream1.write(bts);
stream1.close();		//log.txt文件的內容爲:cdef,修改後文件內容爲:cdefcdef

字節流一般用於處理哪種文件呢?
只要不是文本文件,其他的像圖片、視頻、音頻、特殊格式的文件都可處理。

字符流:字符輸入流、字符輸出流

  • 字符輸入流:Reader   實現類:FileReader
  • 字符輸出流:Writer     實現類:FileWriter
File file = new File("./log.txt");
Reader reader = new FileReader(file);
char[] chs = new char[10];
int length = 0;
while((length=reader.read(chs)) > 0) {
	System.out.print(new String(chs, 0, length));
}
reader.close();		//log.txt文件的內容爲:cdef,最後輸出結果爲:cdef

Writer writer = new Writer(file);
char[] chs = {'你', '好'};
writer.write(chs);
writer.close();		//log.txt文件的內容爲:cdef,最後輸出結果爲:你好

Writer writer = new Writer(file, true);
writer.write("我很好");
writer.close();		//log.txt文件的內容爲:你好,最後輸出結果爲:你好我很好

總結:如果處理文本文件,不管是讀還是寫,儘量採用字符流,除此之外的格式,都採用字節流。

包裝流

就是將底層的字符流或者字節流在其基礎之上進行二次封裝,包成一個使用更爲方便的二次流。

緩衝流:BufferedReader、BufferedWriter

  • 緩衝輸入流:BufferedReader
  • 緩衝輸出流:BufferedWriter
      讀或者寫,並不直接對文件操作,爲了提高性能,而是採用了對內存操作的方式。提供了8192個字符的緩衝器,在創建這兩個流對象時就需要在內存劃分出來了。
      緩衝輸入流在對象創建完成之後,就會立刻進行讀取操作,讀取文件中的信息,將文件中的數據信息讀取到內存中的緩衝區中,真正使用流讀取操作時,讀的數據是來源於內存的緩衝區。如果緩存區中的數據讀取完了,緩存流會立刻從文件中再次讀取數據,覆蓋之前的內容,直到文件讀取完畢。
      寫也同樣不是直接寫入到文件,而是寫入到緩衝區。緩衝區寫滿了,緩衝輸出流會進行flush清空操作,將緩衝區的數據清空,把數據寫入到文件目的地。
      因爲程序是直接對內存進行操作,而不是對硬盤或外部存儲介質操作,所以提高了性能。
File file = new File("./log.txt");
BufferedReader reader = new BufferedReader(new FileReader(file));
String line = null;
while((line=reader.readLine()) != null) {	
	System.out.println(line);	//循環輸出文件中每一行的信息
}
reader.close();		

File file = new File("./log.txt");
BufferedWriter writer = new BufferedWriter(new FileWriter(file, true));
for(int i=0; i<4; i++) {
	writer.newLine();
	writer.write(String.valueOf(i)+i+i+i+i+i);
}
writer.close();
//緩衝的輸出流在關閉操作時會檢查緩衝區中是否存在數據,如果發現有,將會把數據寫到文件中去。
//也可以使用writer.flush()進行輸出

轉換流:InputStreamReader、OutputStreamWriter

  • 轉換輸入流:InputStreamReader
  • 轉換輸出流:OutputStreamWriter
      將一個字節流轉換成一個字符流
File file = new File("./log.txt");
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(file, true));
BufferedWriter bw = new BufferedWriter(osw);	//把字節流轉換成字符流
bw.write("112233");
bw.close();

File file = new File("./log.txt");
InputStreamReader isr = new InputStreamReader(new FileInputStream(file));
char[] data = new char[1024];
int length = isr.read(data);
System.out.println(new String(data, 0, length));
isr.close();

打印流:PrintStream、PrintWriter

  • 字節打印流:PrintStream
  • 字符打印流:PrintWriter
//爲什麼要使用打印流?打印流和普通的字節或字符流輸出有什麼區別?我們看一下下面這兩個例子:
File file = new File("./log.txt");
OutputStream os = new FileOutputStream(file);
os.write(97);
os.close();		//寫入到文件中的爲字母a

File file = new File("./log.txt");
PrintStream ps = new PrintStream(new FileOutputStream(file));
ps.print(97);
ps.close();		//寫入到文件中的爲數字97

總結:字節輸出流、字符輸出流輸出數字到文件中時,會變成相應的字母
   採用打印流往文件中輸入數據時,數據就不會再進行轉換了

內存流:ByteArrayInputStream、ByteArrayOutputStream

  • 內存輸入流:ByteArrayInputStream
  • 內存輸出流:ByteArrayOutputStream
ByteArrayOutputStream baos = new ByteArrayOutputStream();
String value = "你好啊";
baos.write(value.getBytes());	//數據寫入到了內存中的一個字節數組中
byte[] data = baos.toByteArray();	//toByteArray()方法:創建一個新分配的字節數組。數組的大小是當前輸出流的大小,內容是當前輸出流的拷貝。
System.out.println(new String(data));
baos.close();	//輸出結果爲 你好啊

ByteArrayInputStream bais = new ByteArrayInputStream(data);
byte[] data1 = new byte[20];
int length = bais.read(data1);
System.out.println(new String(data1, 0, length));
bais.close();	//輸出結果爲 你好啊		

數據流:DataInputStream、DataOutputStream

  • 數據輸入流:DataInputStream
  • 數據輸出流:DataOutputStream
ByteArrayOutputStream baos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(baos);
//數據流可以進行網絡間的數據傳輸
dos.writeFloat(12.4f);
dos.writeDouble(20.45);
dos.writeInt(10);
//數據最終寫入到一塊內存中
byte[] data = baos.toByteArray();
baos.close();
		
ByteArrayInputStream bais = new ByteArrayInputStream(data);
DataInputStream dis = new DataInputStream(bais);
//讀要跟寫保持一致,要規定好讀的格式,定義好協議,按照協議的格式去讀或者寫
System.out.println(dis.readFloat());
System.out.println(dis.readDouble());
System.out.println(dis.readInt());
bais.close();

對象流:ObjectInputStream、ObjectOutputStream

  • 對象輸入流:ObjectInputStream
  • 對象輸出流:ObjectOutputStream
Student stu = new Student();
stu.setStuName("張三");
Teacher tea = new Teacher();
tea.setTeaName("李四");
stu.setTeacher(tea);

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("./obj.txt"));
oos.writeObject(stu);	//把對象stu保存到文件當中,並且使用深克隆進行拷貝
oos.close();

ObjectInputStream ois = new ObjectInputStream(new FileInputStream("./obj.txt"));
Student stuObj = (Student)ois.readObject();
System.out.println(stuObj.getStuName());
System.out.println(stuObj.getTeacher().getTeaName());
ois.close();

讀寫流:RandomAccessFile

RandomAccessFile raf = new RandomAccessFile("./log.txt", "rw");
//在進行讀取操作時,該對象包含一個記錄指針,記錄當前操作到哪個字節位置了
raf.seek(3);	//控制指針從開頭移動幾個字節
int length = raf,getFilePointer();	//length即是指針的當前位置
raf.write("abc".getBytes());
raf.close();
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章