Java基礎之IO框架

 

一.流的分類java

1.java.io包中的類對應兩類流,一類流直接從指定的位置(如磁盤文件或內存區域)讀或寫,這類流稱爲結點流(node stream),其它的流則稱爲過濾器(filters)。過濾器輸入流每每是以其它輸入流做爲它的輸入源,通過過濾或處理後再以新的輸入流的形式提供給用戶,過濾器輸出流的原理也相似。node

2.Java的經常使用輸入、輸出流數組

java.io包中的stream類根據它們操做對象的類型是字符仍是字節可分爲兩大類:字符流和字節流。網絡

2.1Java的字節流:框架

InputStream是全部字節輸入流的祖先,而OutputStream是全部字節輸出流的祖先dom

2.2Java的字符流:jvm

Reader是全部讀取字符串輸入流的祖先,而writer是全部輸出字符串的祖先。函數

結合開始所說的輸入/輸出流 ,出現了個一小框架。性能

JAVA字節流:this

FileInputStream和FileOutputStream
這兩個類屬於結點流,第一個類的源端和第二個類的目的端都是磁盤文件,它們的構造方法容許經過文件的路徑名來構造相應的流。

FileInputStream infile = new FileInputStream("myfile.dat");
FileOutputStream outfile = new FileOutputStream("results.dat");

要注意的是:構造FileInputStream,,對應的文件必須存在而且是可讀的,而構造FileOutputStream時,如輸出文件已存在,則必須是可覆蓋的。

BufferedInputStream和BufferedOutputStream:
它們是過濾器流,其做用是提升輸入輸出的效率,對於FileInputStream當調用read()方法(每次讀取一個字節)時都要從硬盤中獲取數據,對性能有必定影響,因此就須要使用緩衝流:從本身內存中的字節數組中讀取數據,默認一次讀8192個字節

DataInputStream和DataOutputStream:
這兩個類建立的對象分別被稱爲數據輸入流和數據輸出流。這是頗有用的兩個流,它們容許程序按與機器無關的風格讀寫Java數據。因此比較適合於網絡上的數據傳輸。這兩個流也是過濾器流,常以其它流如InputStream或OutputStream做爲它們的輸入或輸出。這兩種流失對流的擴展,能夠更加方便的讀取int,long,字符等類型的數據,好比:DataOutputStram:中增長了writeInt()/writeDouble()/writeUTF()方法

public class Main {
    public static void main(String[] args) throws IOException {
        String file="a.txt";
        DataOutputStream dos=new DataOutputStream(new FileOutputStream(file));
        dos.writeInt(10);
        dos.writeLong(10l);
        dos.writeUTF("中國");//採用UTF-8編碼寫入
        dos.writeChars("中國");//採用utf-16be方式寫入
        dos.close();
    }
}

RandomAccessFile的基本介紹和操做:

RandomAccessFile是Java提供的對文件內容的訪問,既能夠讀文件,也能夠寫文件,而且能夠隨機訪問文件,便可以訪問文件的任意位置,它在訪問文件時會有一個文件指針,在訪問過程當中會向後移動

File demo=new File("demo");
if(demo.exists()){
    demo.mkdir();//若是文件夾不存在則建立
}

File file=new File(demo,"a.txt");//以demo爲目錄建立a.txt文件
if(file.exists()){
    file.createNewFile();//若是文件不存在則建立新的文件
}

RandomAccessFile raf=new RandomAccessFile(file,"rw");//rw是文件模式中的可讀寫模式
System.out.println(raf.getFilePointer());//獲得指針的位置爲0
raf.write('A');//寫入'A'的後八位(每次只寫一個字節),指針後移一位

int i=15;
raf.write(i>>>24);//寫入高八位
raf.write(i>>>16);.....每次寫一個字節,要寫四次

raf.writeInt(i);//直接寫入一個int類型數據

String s="中國";
byte[] gbk=s.getBytes("gbk");
raf.write(gbk);

raf.seek(0);//讀文件 ,必須把指針移到頭部
byte[] buf=new byte[(int)raf.length()];//一次性讀取,把文件中的內容都讀到字節數組中去
raf.read();
System.out.println(Arrays.toString(buf));

Java的字符流:

字符流主要是用來處理字符的,Java採用16位的Unicode來表示字符串和字符,對應的字符流按輸入和輸出分別稱爲Reader和writer(一次處理一個字符,字符的底層仍然是基本的字節序列)

FileReader和FileWriter:

FileReader(讀文件類):其直接父類就是InputStreamReader類

FileReader a=new FileReader("C:\\Users\\admin\\Desktop\1.txt");//注意:不能修改編碼集,即便用默認編碼集

FileWriter:其直接父類爲OutputStreamWriter類

FileWriter a=new FileWrite("C:\\Users\\admin\\Desktop\1.txt",true);//加true參數表示在第二次寫入文件時是追加內容

InputStreamReader和OutputStreamWriter:

1.將字節流轉化爲字符流(解碼):

FileInputStream f==new FileInputStream("D:\\test.txt");;
InputStreamReader f1=f1=new InputStreamReader(f,"UTF-8");//設置字符編碼爲UTF-8,默認項目的編碼爲gbk

//讀取數據(一個字符一個字符的讀取):
int c;
while((c=f1.read())!=-1){
    System.out.println((char)c);
}

//批量讀取(放入buffer這個字符數組,從0開始放置,最多放buffer.length個,返回的是讀到的字符個數):
char[] buffer=new char[8*1024];
while((c==f1.read(buffer,0,buffer.length))!=-1){
    String s=new String(buffer,0,c);
}

2.將字符流轉化爲字節流(編碼):

FileOutputStream fos=new FileOutputStream("D:\\test.txt");
OutputStreamWriter osw=new OutputStreamWriter(fos,"UTF-8");

BufferedReader和BufferedWriter:

這兩個類對應的流使用了緩衝,能大大提升輸入輸出的效率,這兩個也是過濾器流,經常使用來對InputStreamReader和OutputStreamWriter進行處理,如:

public class Echo {
   public static void main(String[] args) throws IOException{
     BufferedReader in =new BufferedReader(new InputStreamReader(System.in));
     BufferedWriter bw=new BufferedWriter(mew FileOutputStream("d:\\test.txt"));
     String s;
     while((s = in.readLine()).length() != 0){
         System.out.println(s);//一次讀一行,並不能識別換行
         bw.write(s);
         bw.newLine();//換行操做
         bw.flush();//注意必定要添加這行代碼,才能寫入緩衝區中
     } 
     bf.close();       
     bw.close();
}

BuffferedReader和BufferedWriter之mark()(方法標記流中的當前位置,調用reset()將從新定位流)的使用:

public class Test{
  public static void main(String[] args) throws IOException{
        FileReader fr=new FileReader("D:\\test.txt");
        BufferedReader br=new BufferedReader(fr,1000);//1000爲緩衝區大小
        br.mark(1000);//參數要不小於緩衝區大小,字符流須要設置,而字節流的mark會默認在起始位置
第一種方式讀取:
        int c=0;
        c=br.read();
        while(c!=-1){
          System.out.println((char)c);
          c=br.read();
        }
第二種方式讀取: 
        br.reset();//再讀一次須要重置
        String str=br.readLine();
        while(str!=null) {
          System.out.println(str);
          str=br.readLine();
        }
   }//注意關閉流最好在finally中進行
}

Java序列化和反序列化問題

transient和ArrayList源碼解析:

private transient int age;//該元素不會進行jvm的默認序列化,但也能夠本身完成這個元素的序列化

ObjectOutputStream s;
s.defaultWriteObject();//把jvm默認能序列化的元素進行序列化操做
s.writeInt(age);//本身完成age的序列化

ObjectInputStream s;
s.defaultReadObject();//把jvm中默認能進行反序列化的元素進行反序列化
this.age=s.readInt();//本身完成age的反序列化操做

經過對ArrayList源碼列表的分析能夠知道,ArrayList中會對其中的有效元素進行序列化和反序列化以提升性能

序列化中子父類構造函數問題:

在序列化中若父類是實現了序列化接口,子類能夠不用實現序列化接口,能夠直接進行序列化,子類在序列化過程當中會遞歸的調用父類的構造方法

注意:對子類對象進行反序列化操做時,若是其父類沒有實現序列化接口,那麼其父類的構造函數會被顯示調用,不然就不會調用

相關文章
相關標籤/搜索