目錄
寫入數據
FileoutputStram
class FileStream
{
public static void writeFile() throws IOException
{
FileOutputStream fos = new FileOutputStream("fos.txt")
//寫入需要轉化爲字節
fos.write("abc".getBytes());
//
fos.close()
}
}
讀數據
//一個字節一個字節的讀
class FileStream
{
public static void ReadFile_1() throws IOException
{
FileInputStream fos = new FileInputStream(fos.txt);
int ch=0;
while((ch=fis.read())!=-1)
{
System.out.println((char)ch);
}
}
}
//一個數組的讀
class FileStream
{
public static void ReadFile_1() throws IOException
{
FileInputStream fos = new FileInputStream(fos.txt);
byte[] buf =new byte[1024];
int len=0;
while((len=fis.read(buf))!=-1)
{
System.out.println(new String(buf,0,len));
}
fis.close();
}
}
拿到文件大小
class FileStream
{
public static void ReadFile_3() throws IOException
{
FileInputStream fos = new FileInputStream(fos.txt);
//available返回了文件中數據的個數(回車符算2個,/r/n)
byte[] buf =new byte[fis.available()]; //定義一個剛剛好的緩衝區,不用在循環了
fis.read(buf);
System.out.println(new String(buf));
fis.close();
}
}
1,字符流在底層調用了字節流的緩衝區,所以需要刷新動作;而字節流在操作時則不需要刷新
2,available()方法要慎用,虛擬機內存默認爲64M,如果只用一個大小剛好的緩衝數組,在copy較大的文件時顯然是無法承受的,數據太大容易發生內存溢出,
建議用byte[] buf =new byte[1024];
1.因爲現代操作系統的內存管理都具有分頁機制,而內存頁的大小都是1024的整數倍,定義1024整數倍大小的緩衝區在分配內存時將不會形成碎片。
2.讀和寫都是放在while循環中的,每次讀取1024個字節,也就是1kb,如果最後一次讀取和寫入可能不夠1024個字節,所以寫入的時候加了fos.write(buf,0,len);意思是還剩多少就寫多少。
示例:
複製一個圖片
/*
思路:
1.用字節讀取流對象和圖片關聯
2.用字節寫入流對象創建一個圖片文件,用於存儲獲取到的圖片數據
3.通過循環讀寫,完成數據的存儲
4.關閉資源
*/
class CopyPic
{
public static void main(Stirng[] args)
{
FileOutputStream fos =null;
FileInputStream fis=null;
try
{
fos = new FileOutputStream("C:\\2.bmp");
fis = new FileInputStream("C:\\1.bmp");
byte[] buf = new byte[1024];
int len=0;
while(len=fis.read(buf)!=-1)
{
fos.write(buf,0,len);
}
}
catch(IOException e)
{
throw new RuntimeException("複製文件失敗");
}
finally
{
try
{
if(fis!=null)
fis.close();
}
catch(IOException e)
{
throw new RuntimeException("讀取關閉失敗");
}
try
{
if(fos!=null)
fos.close();
}
catch(IOException e)
{
throw new RuntimeException("寫入關閉失敗");
}
}
}
}
字節流的緩衝區
class Copy
{
public static void main(String[] args) throws IOException
{
//計算運行copy方法需要多長時間
long start = System.currentTimeMillis();
copy();
long end = System.currentTimeMillis();
System.out.println((end-start)+"毫秒")
}
//通過字節流的緩衝區完成複製
public static void copy throws IOException
{
BufferedInputStream bufis =new BufferedInputStream(new FileInputStream("C:\\0.mp3"));
BufferedOutputStream bufis =new BufferedOutputStream(new FileOutputStream("C:\\1.mp3"));
int by =0;
while(by =bufis.read()!=-1)
{
bufos.writer(by);
}
bufos.close();
bufis.close();
}
}
自定義字節流緩衝區
import java.io.*;
class MyBufferedIOStream
{
private InputStream in;//裝飾模式,私有化成員變量
private byte[] buf = new byte[1024]; //1,定義數組
private int pos = 0, count = 0; //2,定義指針pos、3,定義計數器count表示數組中剩餘元素個數
MyBufferedInputStream(InputStream in){ //裝飾類構造函數
this.in = in;
}
public int myRead() throws IOException //自定義字節流緩衝區read方法,一次讀取一個字節,
{
if (count == 0) //計數器爲0,則讀取一個數組,開始計數
{ //通過in對象讀取硬盤上數據,存儲到buf數組中
count = in.read(buf);//read返回該數組中有效元素個數,到末尾返回-1
if (count<0) //健壯性判斷、read到達文件末尾返回爲-1
return -1;
pos = 0; //執行到這一步說明有一個新的數組,初始化指針
byte b = buf[pos];//通過指針獲取字節數組元素
count--; //執行一次,元素有效個數-1
pos++; //指針位置右移
return b&255; //該數組字節爲byte,通過&與運算將其提升爲int型並補上24個0返回
}
else if (count>0) //計數器大於0,對數組繼續讀取就可以了
{
byte b = buf[pos];
count--;
pos++;
return b&0xff; //16進制的255
}
}
public static void main(String[] args)
{
System.out.println("Hello World!");
}
}
緩衝區中read和write的特點
在計算機中數據都是以二進制存取的,而字節是以byte型存取的
如果剛好有連續的8個1,直接轉成int型就還是-1,而在緩衝區中的read時,就意外滿足了-1的控制條件
從而導致讀寫操作無法進行,所以字節流緩衝區的read方法必須避免這種情況的發生生
byte: -1 ---> int : -1;
00000000 00000000 00000000 11111111 255
11111111 11111111 11111111 11111111
11111111 -->提升了一個int類型 那不還是-1嗎?是-1的原因是因爲在8個1前面補的是1導致的。
那麼我只要在前面補0,即可以保留原字節數據不變,又可以避免-1的出現。
怎麼補0呢?
通過&運算補0
11111111 11111111 11111111 11111111
&00000000 00000000 00000000 11111111
------------------------------------
00000000 00000000 00000000 11111111
結論:
字節流的讀一個字節的read方法爲什麼返回值類型不是byte,而是int。
因爲有可能會讀到連續8個二進制1的情況,8個二進制1對應的十進制是-1;那麼就會數據還沒有讀完,就結束的情況。因爲我們判斷讀取結束是通過結尾標記-1來確定的。
所以,爲了避免這種情況將讀到的字節進行int類型的提升。並在保留原字節數據的情況前面了補了24個0,變成了int類型的數值。
而在write寫入數據時,只寫該int類型數據的最低8位,write有強制轉換爲byte,保證了數據的原樣性