Java之IO流 FileInputStream FileOputStream
位元組流(能夠處理任何型別的資料 因為計算機儲存都是以位元組為單位 byte 一個位元組八位) 總類為 位元組輸入流 InputStream 連線硬碟和記憶體之間的管道 讀取位元組 位元組輸出流 OutputStream 從記憶體輸出到硬碟中 下面講些常用的類
FileInputStream
注意在輸入的時候 方法中要丟擲 IOException 異常(因為可能讀入的過程中硬碟中可能沒有此檔案) 1.read() 方法 返回是個int值 其含義是檔案資料中的碼錶值 如a為97 b為98 。。 2.read(byte[ ])返回也是int值 其含義是讀入byte中的有效資料個數 3.read(byte[ ] ,int off ,int len)其中off表示起始偏移量 然後len表示 有效資料個數
一套典型的io流讀入程式碼
FileInputStream fis = new FileInputStream("xxx.txt"); //建立流物件
int b;
while((b = fis.read()) != -1) {
System.out.println(b);
}
fis.close();
下面說說 為什麼read 和 write 的返回值是int 而不是byte 按道理說檔案不都是以byte為基本單位儲存的嗎?幹嘛用int呢? 彆著急 在此之前你要明白 io流中有一個機制 那就是當檔案讀入完的時候 指標將會指向-1 來表示檔案讀入或輸出結束 假設 : 我用byte來作為返回值的話 讀入的過程中 可能會出現 11111111 這也是-1的補碼(計算機儲存的二進位制都是補碼格式 原碼取反加1) -1 的原碼 10000001 -1的反碼(第一位表示為符號位) 11111110 -1的補碼(反碼加1) 11111111 那麼就會出現自動返回的情況 導致檔案沒有完全讀入或輸出
那麼用int 的話 會預設給byte的數 自動新增 24個0 來消除這種情況 而結束的時候在用 int的-1來指向結束就好了 同時也不用擔心在java中輸出的時候前面的24個0會自動給刪掉 保證都是以原來的形式輸出
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(); //關流釋放資源
}
}
FileOutputStream
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.從demo1中可以看出來 輸入輸出的效率特別低 就好像我買100個雞蛋 我一次買一個回來 這麼一次次的來來回回 2.從demo3中可以看出來 使用大陣列的話 就好像我買100個雞蛋 我拿個容器(陣列)一次裝100個 拿回來就行 注意其中的 int len = fis.available(); 表示檔案的位元組個數 可是有個問題 那我位元組個數100萬呢? 我容器是不是得炸掉了?所以這種方法也不行
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();
}
}