【java】I/O流
參考:https://blog.csdn.net/qq_32451699/article/details/52230963 ——基本理解
進階理解:
FilterInputStream 與 裝飾者模式:https://blog.csdn.net/zhao123h/article/details/52826306
FilterInputStream 與 裝飾者模式:https://blog.csdn.net/zhao123h/article/details/52826682
一、概念
* IO流用來處理裝置之間的資料傳輸
* Java對資料的操作是通過流的方式
* Java用於操作流的類都在IO包中
* 流按流向分為兩種:輸入流,輸出流。
* 流按操作型別分為兩種:
* 位元組流 :位元組流可以操作任何資料,因為在計算機中任何資料都是以位元組的形式儲存的
* 字元流 :字元流只能操作純字元資料,比較方便。
二、IO流常用父類
* 位元組流的抽象父類:
*InputStream
*OutputStream
* 字元流的抽象父類:
* Reader
* Writer
三、IO程式書寫
* 使用前,匯入IO包中的類
* 使用時,進行IO異常處理
* 使用後,釋放資源
四、FileInputStream
* read()一次讀取一個位元組
*
FileInputStreamfis = new FileInputStream("aaa.txt"); //建立一個檔案輸入流物件,並關聯aaa.txt
int b; //定義變數,記錄每次讀到的位元組
while((b= fis.read()) != -1) { //將每次讀到的位元組賦值給b並判斷是否是-1
System.out.println(b); //列印每一個位元組
}
fis.close(); //關閉流釋放資源
* read()方法返回值為什麼是int
* read()方法讀取的是一個位元組,為什麼返回是int,而不是byte
*
因為位元組輸入流可以操作任意型別的檔案,比如圖片音訊等,這些檔案底層都是以二進位制形式的儲存的,如果每次讀取都返回byte,有可能在讀到中間的時候遇到111111111
那麼這11111111是byte型別的-1,我們的程式是遇到-1就會停止不讀了,後面的資料就讀不到了,所以在讀取的時候用int型別接收,如果11111111會在其前面補上
24個0湊足4個位元組,那麼byte型別的-1就變成int型別的255了這樣可以保證整個資料讀完,而結束標記的-1就是int型別
五、FileOutputStream
* write()一次寫出一個位元組
*
FileOutputStreamfos = new FileOutputStream("bbb.txt"); //如果沒有bbb.txt,會建立出一個
//fos.write(97); //雖然寫出的是一個int數,但是在寫出的時候會將前面的24個0去掉,所以寫出的一個byte
fos.write(98);
fos.write(99);
fos.close();
* FileOutputStream追加
* A:案例演示
*FileOutputStream的構造方法寫出資料如何實現資料的追加寫入
*
FileOutputStreamfos = new FileOutputStream("bbb.txt",true); //如果沒有bbb.txt,會建立出一個
//fos.write(97); //雖然寫出的是一個int數,但是在寫出的時候會將前面的24個0去掉,所以寫出的一個byte
fos.write(98);
fos.write(99);
fos.close();
* 拷貝圖片
* FileInputStream讀取
* FileOutputStream寫出
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class Demo1_FileInputStream {
/**
* @param args
* @throws IOException
* read()方法讀取的是一個位元組,為什麼返回是int,而不是byte
*
* 00010100 00100100 01000001 11111111 0000000
*
* 10000001 byte型別-1的原碼
* 11111110 -1的反碼
* 11111111 -1的補碼
*
* 00000000 00000000 00000000 11111111
*/
public static void main(String[] args) throws IOException {
//demo1();
FileInputStream fis = new FileInputStream("xxx.txt"); //建立流物件
int b;
while((b = fis.read()) != -1) {
System.out.println(b);
}
fis.close(); //標準格式
}
public static void demo1() throws FileNotFoundException, IOException {
FileInputStream fis = new FileInputStream("xxx.txt"); //建立流物件
int x = fis.read(); //從硬碟上讀取一個位元組
System.out.println(x);
int y = fis.read();
System.out.println(y);
int z = fis.read();
System.out.println(z);
int a = fis.read();
System.out.println(a);
int b = fis.read();
System.out.println(b);
fis.close(); //關流釋放資源
}
}
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class Demo2_FileOutputStream {
/**
* @param args
* @throws IOException
* FileOutputStream在建立物件的時候是如果沒有這個檔案會幫我建立出來,如果有這個檔案就會先將檔案清空
*/
public static void main(String[] args) throws IOException {
//demo1();
FileOutputStream fos = new FileOutputStream("yyy.txt",true); //如果想續寫就在第二個引數傳true
fos.write(97);
fos.write(98);
fos.close(); //標準格式
}
public static void demo1() throws FileNotFoundException, IOException {
FileOutputStream fos = new FileOutputStream("yyy.txt"); //建立位元組輸出流物件,如果沒有就自動建立一個
//fos.write(97); //雖然寫出的是一個int數,但是到檔案上的是一個位元組,會自動去除前三個8位
//fos.write(98);
//fos.write(99);
fos.write(100);
fos.close();
}
}
拷貝檔案的四種方式:
1、一個位元組一個位元組讀寫--效率低(不推薦)
2、大陣列讀寫--記憶體溢位(不推薦)
3、小陣列讀寫--推薦
4、緩衝區
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class Demo3_Copy {
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
//demo1();
//demo2();
//demo3();
}
public static void demo3() throws FileNotFoundException, IOException {
//第二種拷貝,不推薦使用,因為有可能會導致記憶體溢位
FileInputStream fis = new FileInputStream("致青春.mp3"); //建立輸入流物件,關聯致青春.mp3
FileOutputStream fos = new FileOutputStream("copy.mp3"); //建立輸出流物件,關聯copy.mp3
//int len = fis.available();
//System.out.println(len);
byte[] arr = new byte[fis.available()]; //建立與檔案一樣大小的位元組陣列
fis.read(arr); //將檔案上的位元組讀取到記憶體中
fos.write(arr); //將位元組陣列中的位元組資料寫到檔案上
fis.close();
fos.close();
}
public static void demo2() throws FileNotFoundException, IOException {
FileInputStream fis = new FileInputStream("致青春.mp3"); //建立輸入流物件,關聯致青春.mp3
FileOutputStream fos = new FileOutputStream("copy.mp3"); //建立輸出流物件,關聯copy.mp3
int b;
while((b = fis.read()) != -1) { //在不斷的讀取每一個位元組
fos.write(b); //將每一個位元組寫出
}
fis.close(); //關流釋放資源
fos.close();
}
public static void demo1() throws FileNotFoundException, IOException {
FileInputStream fis = new FileInputStream("雙元.jpg"); //建立輸入流物件,關聯雙元.jpg
FileOutputStream fos = new FileOutputStream("copy.jpg"); //建立輸出流物件,關聯copy.jpg
int b;
while((b = fis.read()) != -1) { //在不斷的讀取每一個位元組
fos.write(b); //將每一個位元組寫出
}
fis.close(); //關流釋放資源
fos.close();
}
}
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class Demo4_ArrayCopy {
/**
* @param args
* 第三種拷貝: 定義小陣列,標準格式
* @throws IOException
*/
public static void main(String[] args) throws IOException {
//demo1();
//demo2();
FileInputStream fis = new FileInputStream("致青春.mp3");
FileOutputStream fos = new FileOutputStream("copy.mp3");
byte[] arr = new byte[1024 * 8];
int len;
while((len = fis.read(arr)) != -1) { //如果忘記加arr,返回的就不是讀取的位元組個數,而是位元組的碼錶值
fos.write(arr,0,len);
}
fis.close();
fos.close();
}
public static void demo2() throws FileNotFoundException, IOException {
FileInputStream fis = new FileInputStream("xxx.txt");
FileOutputStream fos = new FileOutputStream("yyy.txt");
byte[] arr = new byte[2];
int len;
while((len = fis.read(arr)) != -1) {
fos.write(arr,0,len);
}
fis.close();
fos.close();
}
public static void demo1() throws FileNotFoundException, IOException {
FileInputStream fis = new FileInputStream("xxx.txt");
byte[] arr = new byte[2];
int a = fis.read(arr); //將檔案上的位元組讀取到位元組陣列中
System.out.println(a); //讀到的有效位元組個數
for (byte b : arr) { //第一次獲取到檔案上的a和b
System.out.println(b);
}
System.out.println("-----------------------");
int c = fis.read(arr);
System.out.println(c);
for (byte b : arr) {
System.out.println(b);
}
fis.close();
}
}
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class Demo5_BufferCopy {
/**
* @param args
* @throws IOException
* close方法: 具備重新整理的功能,在關閉流之前,就會先重新整理一次緩衝區,將緩衝區的位元組全都重新整理到檔案上,再關閉,close方法刷完之後就能寫了
* flush方法:具備重新整理的功能,刷完之後還可以繼續寫
*/
public static void main(String[] args) throws IOException {
//demo1();
//flush和close方法的區別
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("致青春.mp3"));
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.mp3"));
int b;
while((b = bis.read()) != -1) {
bos.write(b);
}
bis.close();
bos.close();
}
public static void demo1() throws FileNotFoundException, IOException {
FileInputStream fis = new FileInputStream("致青春.mp3"); //建立輸入流物件,關聯致青春.mp3
FileOutputStream fos = new FileOutputStream("copy.mp3"); //建立輸出流物件,關聯copy.mp3
BufferedInputStream bis = new BufferedInputStream(fis); //建立緩衝區物件,對輸入流進行包裝讓其變得更加強大
BufferedOutputStream bos = new BufferedOutputStream(fos);
int b;
while((b = bis.read()) != -1) {
bos.write(b);
}
bis.close(); //只關閉裝飾後的物件即可
bos.close();
}
}
小陣列的讀寫和帶Buffered的讀取哪個更快?
* 定義小陣列如果是8192個位元組大小和Buffered比較的話
* 定義小陣列會略勝一籌,因為讀和寫操作的是同一個陣列
* 而Buffered操作的是兩個陣列
flush和close方法的區別
* flush()方法
* 用來重新整理緩衝區的,重新整理後可以再次寫出
* close()方法
* 用來關閉流釋放資源的的,如果是帶緩衝區的流物件的close()方法,不但會關閉流,還會再關閉流之前重新整理緩衝區,關閉後不能再寫出
六、字元流
位元組流讀寫中文)
* 位元組流讀取中文的問題
* 位元組流在讀中文的時候有可能會讀到半個中文,造成亂碼
* 位元組流寫出中文的問題
* 位元組流直接操作的位元組,所以寫出中文必須將字串轉換成位元組陣列
* 寫出回車換行 write("\r\n".getBytes());
相關文章
- I/O流
- 《Java 高階篇》六:I/O 流Java
- Java I/OJava
- 流?I/O 操作?阻塞?epoll?
- Java中I/O流:阻塞和非阻塞範例Java
- Java I/O流 複製檔案速度對比Java
- Java(8)I/OJava
- C++:標準I/O流C++
- JAVA I/O系統Java
- Java 非同步 I/OJava非同步
- Java™ 教程(命令列I/O)Java命令列
- I/O流中的BufferedXXXStream與DataXXXStream、ObjectXXStreamObject
- I/O流以及檔案的基本操作
- 深入理解Java I/O模型Java模型
- "萬字" Java I/O 詳解Java
- Java I/O模型及其底層原理Java模型
- 計算機I/O與I/O模型計算機模型
- Java NIO學習系列五:I/O模型Java模型
- 【雜談】Java I/O的底層實現Java
- Java非阻塞I/O模型之NIO說明Java模型
- Netty權威指南:Java的I/O演進NettyJava
- Python教程:精簡概述I/O模型與I/O操作Python模型
- 關於I/O
- c++ I/OC++
- 五種I/O模型和Java NIO原始碼分析模型Java原始碼
- “挑三揀四”地學一學Java I/OJava
- C#中常用I/O流介紹、 FileStream類及FileMode、FileAccess、FileShareC#
- 系統級 I/O
- Google I/O Extend 2018Go
- 網路I/O模型模型
- NodeJs 非同步 I/ONodeJS非同步
- 理解I/O Completion Port
- python 非同步 I/OPython非同步
- 02. I/O 操作
- Hadoop的I/O操作Hadoop
- Java I/O系統學習系列一:File和RandomAccessFileJavarandomMac
- Linux下的5種I/O模型與3組I/O複用Linux模型
- 服務端 I/O 效能:Node、PHP、Java、Go 的對比服務端PHPJavaGo