1. 程式人生 > >JAVA基礎_Java IO流 控制檯到記事本、記事本到控制檯及詳解

JAVA基礎_Java IO流 控制檯到記事本、記事本到控制檯及詳解

Java IO流 控制檯到記事本、記事本到控制檯及詳解

1. 從記事本讀資料

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;

public class Fileopen {

    /**
     * @param args 
     * @throws
IOException */
public static void main(String[] args) throws IOException{ // TODO Auto-generated method stub FileInputStream fis = null ; try { fis = new FileInputStream("文字目錄"); //例如:D:\\T.txt InputStreamReader isr = new InputStreamReader(fis,"GBK"
); // BufferedReader br = new BufferedReader(isr); // String str =""; System.out.println(isr.getEncoding().toString()); while((str=br.readLine()) != null){ System.out.println(str); // } } catch (FileNotFoundException e) { e.printStackTrace(); } catch
(UnsupportedEncodingException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally{ if(fis != null){ try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } } }

2. 向記事本寫資料

import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;

public class FileWrite {


    public static void main(String[] args) throws IOException {

        FileWriter fileWriter=new FileWriter("輸出到檔案",true);
        /*
        例如:   D:\\Result.txt,true代表是在原有文字後直接新增
        ,如果為false則為擦除寫,清掉之前所有資料。Result.txt,如果
        原來就有則在原來的txt中寫,如果沒有則建立後書寫。
        Windows中回車為/r/n,Linux中為/n
        */
        osw.write("胡禮\r\n");
        osw.write("的\r\n");
           fileWriter.write("小程式\r\n");
           fileWriter.write("謝謝捧場,繼續關注。\r\n");
           fileWriter.flush();
           fileWriter.close();
           osw.flush();
           osw.close();

    }

}

說明一下:

記事本中的字元預設編碼為GBK,為保證讀寫資料產生亂碼,請注意下自己的編輯器預設編碼是什麼,需要輸出的編碼格式是什麼,以保證正確輸出。

下面是關於流的詳細敘述,幫助理解上述程式功能

實際上位元組流在操作的時候本身是不會用到緩衝區的,是檔案本身的直接操作的,但是字元流在操作的 時候下後是會用到緩衝區的,是通過緩衝區來操作檔案的。

讀者可以試著將上面的位元組流和字元流的程式的最後一行關閉檔案的程式碼註釋掉,然後執行程式看看。你就會發現使用位元組流的話,檔案中已經存在內容,但是使用字元流的時候,檔案中還是沒有內容的,這個時候就要重新整理緩衝區。

使用位元組流好還是字元流好呢?

答案是位元組流。首先因為硬碟上的所有檔案都是以位元組的形式進行傳輸或者儲存的,包括圖片等內容。但是字元只是在記憶體中才會形成的,所以在開發中,位元組流使用廣泛。

篇幅較長,耐心看可以助深入理解IO流

流:可以理解資料的流動,就是一個數據流。IO流最終要以物件來體現,物件都存在IO包中。
流也進行分類:
1:輸入流(讀)和輸出流(寫)。
2:因為處理的資料不同,分為位元組流和字元流。

位元組流:處理位元組資料的流物件。裝置上的資料無論是圖片或者dvd,文字,它們都以二進位制儲存的。二進位制的最終都是以一個8位為資料單元進行體現,所以計算機中的最小資料單元就是位元組。意味著,位元組流可以處理裝置上的所有資料,所以位元組流一樣可以處理字元資料。

那麼為什麼要有字元流呢?因為字元每個國家都不一樣,所以涉及到了字元編碼問題,那麼GBK編碼的中文用unicode編碼解析是有問題的,所以需要獲取中文位元組資料的同時+ 指定的編碼表才可以解析正確資料。為了方便於文字的解析,所以將位元組流和編碼表封裝成物件,這個物件就是字元流。只要操作字元資料,優先考慮使用字元流體系。

注意:流的操作只有兩種:讀和寫。

流的體系因為功能不同,但是有共性內容,不斷抽取,形成繼承體系。該體系一共有四個基類,而且都是抽象類。

位元組流:InputStream OutputStream
字元流:Reader Writer

在這四個系統中,它們的子類,都有一個共性特點:子類名字尾都是父類名,字首名都是這個子類的功能名稱。

public static void main(String[] args) throws IOException { //讀、寫都會發生IO異常
    /*
    1:建立一個字元輸出流物件,用於操作檔案。該物件一建立,就必須明確資料儲存位置,是一個檔案。
    2:物件產生後,會在堆記憶體中有一個實體,同時也呼叫了系統底層資源,在指定的位置建立了一個儲存資料的檔案。
    3:如果指定位置,出現了同名檔案,檔案會被覆蓋。
    */
    FileWriter fw = new FileWriter("demo.txt"); // FileNotFoundException
    /*
    呼叫Writer類中的write方法寫入字串。字串並未直接寫入到目的地中,而是寫入到了流中,(其實是寫入到記憶體緩衝區中)。怎麼把資料弄到檔案中?
    */
    fw.write("abcde");
    fw.flush(); // 重新整理緩衝區,將緩衝區中的資料刷到目的地檔案中。
    fw.close(); // 關閉流,其實關閉的就是java呼叫的系統底層資源。在關閉前,會先重新整理該流。
}

close()和flush()的區別:
flush():將緩衝區的資料刷到目的地中後,流可以使用。

close():將緩衝區的資料刷到目的地中後,流就關閉了,該方法主要用於結束呼叫的底層資源。這個動作一定做。

io異常的處理方式:io一定要寫finally;

FileWriter寫入資料的細節:
1:window中的換行符:\r\n兩個符號組成。 linux:\n。
2:續寫資料,只要在建構函式中傳入新的引數true。
3:目錄分割符:window \ /

public static void main(String[] args) {
        FileWriter fw = null;
        try {
            fw = new FileWriter("demo.txt",true);
            fw.write("abcde");
        }
        catch (IOException e ){
            System.out.println(e.toString()+"....");
        }
        finally{
            if(fw!=null)
                try{
                    fw.close();
                }
                catch (IOException e){
                    System.out.println("close:"+e.toString());
                }
        }
}

FileReader:使用Reader體系,讀取一個文字檔案中的資料。返回 -1 ,標誌讀到結尾。

import java.io.*;
class  FileReaderDemo {
    public static void main(String[] args) throws IOException {
        /*
        建立可以讀取文字檔案的流物件,FileReader讓建立好的流物件和指定的檔案相關聯。
        */
        FileReader fr = new FileReader("demo.txt");
        int ch = 0;
        while((ch = fr.read())!= -1) { //條件是沒有讀到結尾
            System.out.println((char)ch); //呼叫讀取流的read方法,讀取一個字元。
        }
        fr.close();
    }
}

讀取資料的第二種方式:第二種方式較為高效,自定義緩衝區。

import java.io.*;
class FileReaderDemo2 {
    public static void main(String[] args) throws IOException {
        FileReader fr = new FileReader("demo.txt");
        //建立讀取流物件和指定檔案關聯。
        //因為要使用read(char[])方法,將讀取到字元存入陣列。所以要建立一個字元陣列,一般陣列的長度都是1024的整數倍。
        char[] buf = new char[1024];
        int len = 0;
        while(( len=fr.read(buf)) != -1) {
            System.out.println(new String(buf,0,len));
        }
        fr.close();
    }
}

IO中的使用到了一個設計模式:裝飾設計模式。
裝飾設計模式解決:對一組類進行功能的增強。
包裝:寫一個類(包裝類)對被包裝物件進行包裝;
* 1、包裝類和被包裝物件要實現同樣的介面;
* 2、包裝類要持有一個被包裝物件;

* 3、包裝類在實現介面時,大部分方法是靠呼叫被包裝物件來實現的,對於需要修改的方法我們自己實現;

字元流:
Reader:用於讀取字元流的抽象類。子類必須實現的方法只有 read(char[], int, int) 和 close()。
|—BufferedReader:從字元輸入流中讀取文字,緩衝各個字元,從而實現字元、陣列和行的高效讀取。 可以指定緩衝區的大小,或者可使用預設的大小。大多數情況下,預設值就足夠大了。
|—LineNumberReader:跟蹤行號的緩衝字元輸入流。此類定義了方法 setLineNumber(int) 和 getLineNumber(),它們可分別用於設定和獲取當前行號。
|—InputStreamReader:是位元組流通向字元流的橋樑:它使用指定的 charset 讀取位元組並將其解碼為字元。它使用的字符集可以由名稱指定或顯式給定,或者可以接受平臺預設的字符集。
|—FileReader:用來讀取字元檔案的便捷類。此類的構造方法假定預設字元編碼和預設位元組緩衝區大小都是適當的。要自己指定這些值,可以先在 FileInputStream 上構造一個 InputStreamReader。
|—CharArrayReader:

|—StringReader:

Writer:寫入字元流的抽象類。子類必須實現的方法僅有 write(char[], int, int)、flush() 和 close()。
|—BufferedWriter:將文字寫入字元輸出流,緩衝各個字元,從而提供單個字元、陣列和字串的高效寫入。
|—OutputStreamWriter:是字元流通向位元組流的橋樑:可使用指定的 charset 將要寫入流中的字元編碼成位元組。它使用的字符集可以由名稱指定或顯式給定,否則將接受平臺預設的字符集。
|—FileWriter:用來寫入字元檔案的便捷類。此類的構造方法假定預設字元編碼和預設位元組緩衝區大小都是可接受的。要自己指定這些值,可以先在 FileOutputStream 上構造一個 OutputStreamWriter。
|—PrintWriter:
|—CharArrayWriter:

|—StringWriter:

位元組流:
InputStream:是表示位元組輸入流的所有類的超類。
|— FileInputStream:從檔案系統中的某個檔案中獲得輸入位元組。哪些檔案可用取決於主機環境。FileInputStream 用於讀取諸如影象資料之類的原始位元組流。要讀取字元流,請考慮使用 FileReader。
|— FilterInputStream:包含其他一些輸入流,它將這些流用作其基本資料來源,它可以直接傳輸資料或提供一些額外的功能。
|— BufferedInputStream:該類實現緩衝的輸入流。
|— Stream:
|— ObjectInputStream:

|— PipedInputStream:

OutputStream:此抽象類是表示輸出位元組流的所有類的超類。
|— FileOutputStream:檔案輸出流是用於將資料寫入 File 或 FileDescriptor 的輸出流。
|— FilterOutputStream:此類是過濾輸出流的所有類的超類。
|— BufferedOutputStream:該類實現緩衝的輸出流。
|— PrintStream:
|— DataOutputStream:
|— ObjectOutputStream:

|— PipedOutputStream:

緩衝區是提高效率用的,給誰提高呢?
BufferedWriter:是給字元輸出流提高效率用的,那就意味著,緩衝區物件建立時,必須要先有流物件。明確要提高具體的流物件的效率。

FileWriter fw = new FileWriter("bufdemo.txt");
    BufferedWriter bufw = new BufferedWriter(fw);//讓緩衝區和指定流相關聯。
    for(int x=0; x<4; x++){
        bufw.write(x+"abc");
        bufw.newLine(); //寫入一個換行符,這個換行符可以依據平臺的不同寫入不同的換行符。
        bufw.flush();//對緩衝區進行重新整理,可以讓資料到目的地中。
    }

bufw.close();//關閉緩衝區,其實就是在關閉具體的流。

BufferedReader:
    FileReader fr = new FileReader("bufdemo.txt");
    BufferedReader bufr  = new BufferedReader(fr);
    String line = null;
    while((line=bufr.readLine())!=null){  //readLine方法返回的時候是不帶換行符的。
        System.out.println(line);
    }

bufr.close();

//記住,只要一讀取鍵盤錄入,就用這句話。

BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));//輸出到控制檯
String line = null;
while((line=bufr.readLine())!=null){
    if("over".equals(line))
        break;
    bufw.write(line.toUpperCase());//將輸入的字元轉成大寫字元輸出
    bufw.newLine();
    bufw.flush();
    }
bufw.close();

bufr.close();

流物件:其實很簡單,就是讀取和寫入。但是因為功能的不同,流的體系中提供N多的物件。那麼開始時,到底該用哪個物件更為合適呢?這就需要明確流的操作規律。

流的操作規律:
1,明確源和目的。
資料來源:就是需要讀取,可以使用兩個體系:InputStream、Reader;
資料匯:就是需要寫入,可以使用兩個體系:OutputStream、Writer;
2,操作的資料是否是純文字資料?
如果是:資料來源:Reader
資料匯:Writer
如果不是:資料來源:InputStream
資料匯:OutputStream
3,雖然確定了一個體系,但是該體系中有太多的物件,到底用哪個呢?
明確操作的資料裝置。
資料來源對應的裝置:硬碟(File),記憶體(陣列),鍵盤(System.in)
資料匯對應的裝置:硬碟(File),記憶體(陣列),控制檯(System.out)。
4,需要在基本操作上附加其他功能嗎?比如緩衝。
如果需要就進行裝飾。

轉換流特有功能:轉換流可以將位元組轉成字元,原因在於,將獲取到的位元組通過查編碼表獲取到指定對應字元。

轉換流的最強功能就是基於 位元組流 + 編碼表 。沒有轉換,沒有字元流。

發現轉換流有一個子類就是操作檔案的字元流物件:
InputStreamReader
|–FileReader
OutputStreamWriter
|–FileWrier

想要操作文字檔案,必須要進行編碼轉換,而編碼轉換動作轉換流都完成了。所以操作檔案的流物件只要繼承自轉換流就可以讀取一個字元了。

但是子類有一個侷限性,就是子類中使用的編碼是固定的,是本機預設的編碼表,對於簡體中文版的系統預設碼錶是GBK。
FileReader fr = new FileReader(“a.txt”);
InputStreamReader isr = new InputStreamReader(new FileInputStream(“a.txt”),”gbk”);
以上兩句程式碼功能一致,
如果僅僅使用平臺預設碼錶,就使用FileReader fr = new FileReader(“a.txt”); //因為簡化。

如果需要制定碼錶,必須用轉換流。
轉換流 = 位元組流+編碼表。
轉換流的子類File = 位元組流 + 預設編碼表。

凡是操作裝置上的文字資料,涉及編碼轉換,必須使用轉換流。

File類:將檔案系統中的檔案和資料夾封裝成了物件。提供了更多的屬性和行為可以對這些檔案和資料夾進行操作。這些是流物件辦不到的,因為流只操作資料。

File類常見方法:
1:建立。
boolean createNewFile():在指定目錄下建立檔案,如果該檔案已存在,則不建立。而對操作檔案的輸出流而言,輸出流物件已建立,就會建立檔案,如果檔案已存在,會覆蓋。除非續寫。
boolean mkdir():建立此抽象路徑名指定的目錄。
boolean mkdirs():建立多級目錄。
2:刪除。
boolean delete():刪除此抽象路徑名錶示的檔案或目錄。
void deleteOnExit():在虛擬機器退出時刪除。
注意:在刪除資料夾時,必須保證這個資料夾中沒有任何內容,才可以將該資料夾用delete刪除。
window的刪除動作,是從裡往外刪。注意:java刪除檔案不走回收站。要慎用。
3:獲取.
long length():獲取檔案大小。
String getName():返回由此抽象路徑名錶示的檔案或目錄的名稱。
String getPath():將此抽象路徑名轉換為一個路徑名字串。
String getAbsolutePath():返回此抽象路徑名的絕對路徑名字串。
String getParent():返回此抽象路徑名父目錄的抽象路徑名,如果此路徑名沒有指定父目錄,則返回 null。
long lastModified():返回此抽象路徑名錶示的檔案最後一次被修改的時間。
File.pathSeparator:返回當前系統預設的路徑分隔符,windows預設為 “;”。
File.Separator:返回當前系統預設的目錄分隔符,windows預設為 “\”。
4:判斷:
boolean exists():判斷檔案或者資料夾是否存在。
boolean isDirectory():測試此抽象路徑名錶示的檔案是否是一個目錄。
boolean isFile():測試此抽象路徑名錶示的檔案是否是一個標準檔案。
boolean isHidden():測試此抽象路徑名指定的檔案是否是一個隱藏檔案。
boolean isAbsolute():測試此抽象路徑名是否為絕對路徑名。
5:重新命名。
boolean renameTo(File dest):可以實現移動的效果。剪下+重新命名。

String[] list():列出指定目錄下的當前的檔案和資料夾的名稱。包含隱藏檔案。

如果呼叫list方法的File 物件中封裝的是一個檔案,那麼list方法返回陣列為null。如果封裝的物件不存在也會返回null。只有封裝的物件存在並且是資料夾時,這個方法才有效。

遞迴:就是函式自身呼叫自身。
什麼時候用遞迴呢?
當一個功能被重複使用,而每一次使用該功能時的引數不確定,都由上次的功能元素結果來確定。
簡單說:功能內部又用到該功能,但是傳遞的引數值不確定。(每次功能參與運算的未知內容不確定)。

遞迴的注意事項:
1:一定要定義遞迴的條件。
2:遞迴的次數不要過多。容易出現 StackOverflowError 棧記憶體溢位錯誤。

其實遞迴就是在棧記憶體中不斷的載入同一個函式。

Java.util.Properties:一個可以將鍵值進行持久化儲存的物件。Map–Hashtable的子類。
Map
|–Hashtable
|–Properties:用於屬性配置檔案,鍵和值都是字串型別。
特點:1:可以持久化儲存資料。2:鍵值都是字串。3:一般用於配置檔案。

|– load():將流中的資料載入進集合。
原理:其實就是將讀取流和指定檔案相關聯,並讀取一行資料,因為資料是規則的key=value,所以獲取一行後,通過 = 對該行資料進行切割,左邊就是鍵,右邊就是值,將鍵、值儲存到properties集合中。
|– store():寫入各個項後,重新整理輸出流。

|– list():將集合的鍵值資料列出到指定的目的地。

以下介紹IO包中擴充套件功能的流物件:基本都是裝飾設計模式。
Java.io.outputstream.PrintStream:列印流
1:提供了更多的功能,比如列印方法。可以直接列印任意型別的資料。
2:它有一個自動重新整理機制,建立該物件,指定引數,對於指定方法可以自動重新整理。
3:它使用的本機預設的字元編碼.
4:該流的print方法不丟擲IOException。

該物件的建構函式。
PrintStream(File file) :建立具有指定檔案且不帶自動行重新整理的新列印流。
PrintStream(File file, String csn) :建立具有指定檔名稱和字符集且不帶自動行重新整理的新列印流。
PrintStream(OutputStream out) :建立新的列印流。
PrintStream(OutputStream out, boolean autoFlush) :建立新的列印流。
PrintStream(OutputStream out, boolean autoFlush, String encoding) :建立新的列印流。
PrintStream(String fileName) :建立具有指定檔名稱且不帶自動行重新整理的新列印流。
PrintStream(String fileName, String csn)

PrintStream可以操作目的:1:File物件。2:字串路徑。3:位元組輸出流。
前兩個都JDK1.5版本才出現。而且在操作文字檔案時,可指定字元編碼了。

當目的是一個位元組輸出流時,如果使用的println方法,可以在printStream物件上加入一個true引數。這樣對於println方法可以進行自動的重新整理,而不是等待緩衝區滿了再重新整理。最終print方法都將具體的資料轉成字串,而且都對IO異常進行了內部處理。

既然操作的資料都轉成了字串,那麼使用PrintWriter更好一些。因為PrintWrite是字元流的子類,可以直接操作字元資料,同時也可以指定具體的編碼。

PrintWriter:具備了PrintStream的特點同時,還有自身特點:
該物件的目的地有四個:1:File物件。2:字串路徑。3:位元組輸出流。4:字元輸出流。

開發時儘量使用PrintWriter。

方法中直接操作檔案的第二引數是編碼表。
直接操作輸出流的,第二引數是自動重新整理。

//讀取鍵盤錄入將資料轉成大寫顯示在控制檯.
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));//源:鍵盤輸入
//目的:把資料寫到檔案中,還想自動重新整理。
PrintWriter out = new PrintWriter(new FileWriter(“out.txt”),true);//設定true後自動重新整理
String line = null;
while((line=bufr.readLine())!=null){
if(“over”.equals(line))
break;
out.println(line.toUpperCase());//轉大寫輸出
}
//注意:System.in,System.out這兩個標準的輸入輸出流,在jvm啟動時已經存在了。隨時可以使用。當jvm結束了,這兩個流就結束了。但是,當使用了顯示的close方法關閉時,這兩個流在提前結束了。
out.close();

bufr.close();

SequenceInputStream:序列流,作用就是將多個讀取流合併成一個讀取流。實現資料合併。
表示其他輸入流的邏輯串聯。它從輸入流的有序集合開始,並從第一個輸入流開始讀取,直到到達檔案末尾,接著從第二個輸入流讀取,依次類推,直到到達包含的最後一個輸入流的檔案末尾為止。
這樣做,可以更方便的操作多個讀取流,其實這個序列流內部會有一個有序的集合容器,用於儲存多個讀取流物件。
該物件的建構函式引數是列舉,想要獲取列舉,需要有Vector集合,但不高效。需用ArrayList,但ArrayList中沒有列舉,只有自己去建立列舉物件。
但是方法怎麼實現呢?因為列舉操作的是具體集合中的元素,所以無法具體實現,但是列舉和迭代器是功能一樣的,所以,可以用迭代替代列舉。

合併原理:多個讀取流對應一個輸出流。
切割原理:一個讀取流對應多個輸出流。

import java.io.*;
import java.util.*;
class  SplitFileDemo{
    private static final String CFG = ".properties";
    private static final String SP = ".part";
    public static void main(String[] args) throws IOException{
        File file = new File("c:\\0.bmp");
        File dir = new File("c:\\partfiles");
        meger(dir);
    }
    //資料的合併。
    public static void meger(File dir)throws IOException{
        if(!(dir.exists() && dir.isDirectory()))
            throw new RuntimeException("指定的目錄不存在,或者不是正確的目錄");
        File[] files = dir.listFiles(new SuffixFilter(CFG));
        if(files.length==0)
            throw new RuntimeException("副檔名.proerpties的檔案不存在");
        //獲取到配置檔案
        File config = files[0];
        //獲取配置檔案的資訊。
        Properties prop = new Properties();
        FileInputStream fis = new FileInputStream(config);
        prop.load(fis);
        String fileName = prop.getProperty("filename");
        int partcount = Integer.parseInt(prop.getProperty("partcount"));
        //--------------------------
        File[] partFiles = dir.listFiles(new SuffixFilter(SP));
        if(partFiles.length!=partcount)
            throw new RuntimeException("缺少碎片檔案");
        //---------------------
        ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();
        for(int x=0; x<partcount; x++){
            al.add(new FileInputStream(new File(dir,x+SP)));
        }
        Enumeration<FileInputStream> en = Collections.enumeration(al);
        SequenceInputStream sis = new SequenceInputStream(en);
        File file = new File(dir,fileName);
        FileOutputStream fos = new FileOutputStream(file);
        byte[] buf = new byte[1024];
        int len = 0;
        while((len=sis.read(buf))!=-1){
            fos.write(buf,0,len);
        }
        fos.close();
        sis.close();
    }
    //帶有配置資訊的資料切割。
    public static void splitFile(File file)throws IOException{
        //用一個讀取流和檔案關聯。
        FileInputStream fis = new FileInputStream(file);
        //建立目的地。因為有多個。所以先建立引用。
        FileOutputStream fos = null;
        //指定碎片的位置。
        File dir = new File("c:\\partfiles");
        if(!dir.exists())
            dir.mkdir();
        //碎片檔案大小引用。
        File f = null;
        byte[] buf = new byte[1024*1024];
        //因為切割完的檔案通常都有規律的。為了簡單標記規律使用計數器。
        int count = 0;
        int len = 0;
        while((len=fis.read(buf))!=-1){
            f = new File(dir,(count++)+".part");
            fos = new FileOutputStream(f);
            fos.write(buf,0,len);
            fos.close();
        }
        //碎片檔案生成後,還需要定義配置檔案記錄生成的碎片檔案個數。以及被切割檔案的名稱。
        //定義簡單的鍵值資訊,可是用Properties。
        String filename = file.getName();
        Properties prop = new Properties();
        prop.setProperty("filename",filename);
        prop.setProperty("partcount",count+"");
        File config = new File(dir,count+".properties");
        fos = new FileOutputStream(config);
        prop.store(fos,"");
        fos.close();
        fis.close();
    }
}
class SuffixFilter implements FileFilter{
    private String suffix;
    SuffixFilter(String suffix){
        this.suffix  = suffix;
    }
    public boolean accept(File file){
        return  file.getName().endsWith(suffix);
    }
}

RandomAccessFile:
特點:
1:該物件即可讀取,又可寫入。
2:該物件中的定義了一個大型的byte陣列,通過定義指標來操作這個陣列。
3:可以通過該物件的getFilePointer()獲取指標的位置,通過seek()方法設定指標的位置。
4:該物件操作的源和目的必須是檔案。
5:其實該物件內部封裝了位元組讀取流和位元組寫入流。
注意:實現隨機訪問,最好是資料有規律。

class RandomAccessFileDemo{
    public static void main(String[] args) throws IOException{
        write();
        read();
        randomWrite();
    }
    //隨機寫入資料,可以實現已有資料的修改。
    public static void randomWrite()throws IOException{
        RandomAccessFile raf = new RandomAccessFile("random.txt","rw");
        raf.seek(8*4);
        System.out.println("pos :"+raf.getFilePointer());
        raf.write("王武".getBytes());
        raf.writeInt(102);
        raf.close();
    }
    public static void read()throws IOException{
        RandomAccessFile raf = new RandomAccessFile("random.txt","r");//只讀模式。
        //指定指標的位置。
        raf.seek(8*1);//實現隨機讀取檔案中的資料。注意:資料最好有規律。
        System.out.println("pos1 :"+raf.getFilePointer());
        byte[] buf = new byte[4];
        raf.read(buf);
        String name = new String(buf);
        int age = raf.readInt();
        System.out.println(name+"::"+age);
        System.out.println("pos2 :"+raf.getFilePointer());
        raf.close();
    }
    public static void write()throws IOException{
        //rw:當這個檔案不存在,會建立該檔案。當檔案已存在,不會建立。所以不會像輸出流一樣覆蓋。
        RandomAccessFile raf = new RandomAccessFile("random.txt","rw");//rw讀寫模式
        //往檔案中寫入人的基本資訊,姓名,年齡。
        raf.write("張三".getBytes());
        raf.writeInt(97);
        raf.close();
    }
}

管道流:管道讀取流和管道寫入流可以像管道一樣對接上,管道讀取流就可以讀取管道寫入流寫入的資料。
注意:需要加入多執行緒技術,因為單執行緒,先執行read,會發生死鎖,因為read方法是阻塞式的,沒有資料的read方法會讓執行緒等待。

public static void main(String[] args) throws IOException{
    PipedInputStream pipin = new PipedInputStream();
    PipedOutputStream pipout = new PipedOutputStream();
    pipin.connect(pipout);
    new Thread(new Input(pipin)).start();
    new Thread(new Output(pipout)).start();
}

物件的序列化:目的:將一個具體的物件進行持久化,寫入到硬碟上。
注意:靜態資料不能被序列化,因為靜態資料不在堆記憶體中,是儲存在靜態方法區中。

如何將非靜態的資料不進行序列化?用transient 關鍵字修飾此變數即可。

Serializable:用於啟動物件的序列化功能,可以強制讓指定類具備序列化功能,該介面中沒有成員,這是一個標記介面。這個標記介面用於給序列化類提供UID。這個uid是依據類中的成員的數字簽名進行執行獲取的。如果不需要自動獲取一個uid,可以在類中,手動指定一個名稱為serialVersionUID id號。依據編譯器的不同,或者對資訊的高度敏感性。最好每一個序列化的類都進行手動顯示的UID的指定。

import java.io.*;
class ObjectStreamDemo {
    public static void main(String[] args) throws Exception{
        writeObj();
        readObj();
    }
    public static void readObj()throws Exception{
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("obj.txt"));
        Object obj = ois.readObject();//讀取一個物件。
        System.out.println(obj.toString());
    }
    public static void writeObj()throws IOException{
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("obj.txt"));
        oos.writeObject(new Person("lisi",25)); //寫入一個物件。
        oos.close();
    }
}
class Person implements Serializable{
    private static final long serialVersionUID = 42L;
    private transient String name;//用transient修飾後name將不會進行序列化
    public int age;
    Person(String name,int age){
        this.name = name;
        this.age = age;
    }
    public String toString(){
        return name+"::"+age;
    }

}

DataOutputStream、DataInputStream:專門用於操作基本資料型別資料的物件。
DataOutputStream dos = new DataOutputStream(new FileOutputStream(“data.txt”));
dos.writeInt(256);
dos.close();

DataInputStream dis = new DataInputStream(new FileInputStream("data.txt"));
int num = dis.readInt();
System.out.println(num);

dis.close();

ByteArrayInputStream:源:記憶體
ByteArrayOutputStream:目的:記憶體。
這兩個流物件不涉及底層資源呼叫,操作的都是記憶體中陣列,所以不需要關閉。
直接操作位元組陣列就可以了,為什麼還要把陣列封裝到流物件中呢?因為陣列本身沒有方法,只有一個length屬性。為了便於陣列的操作,將陣列進行封裝,對外提供方法運算元組中的元素。

對於陣列元素操作無非兩種操作:設定(寫)和獲取(讀),而這兩操作正好對應流的讀寫操作。這兩個物件就是使用了流的讀寫思想來運算元組。
//建立源:

“`
ByteArrayInputStream bis = new ByteArrayInputStream(“abcdef”.getBytes());
//建立目的:
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int ch = 0;
while((ch=bis.read())!=-1){
bos.write(ch);
}
System.out.println(bos.toString());

相關推薦

JAVA基礎_Java IO 控制檯記事本記事本控制檯

Java IO流 控制檯到記事本、記事本到控制檯及詳解 1. 從記事本讀資料 import java.io.BufferedReader; import java.io.FileInputStream; import java.io.FileNotF

Java基礎IO(位元組字元記憶體帶快取的序列化和反序列化)

File類:File類提供了對檔案的操作,可以通過字串或URI來構建一個File類物件。通過物件,可以實現檔案的建立(createNewFile)、刪除(delete)、獲得檔名(getName)、獲得父目錄物件(getParentFile)、獲得父目錄名稱(

Java基礎--常用IO使用實例

姓名 onu tar set 保存 二進制文件 stack sdn != 讀取文本文件: 1 private static void ioDemo1() { 2 try { 3 FileReader fileReader = new File

java基礎44 IO技術

blog 技術 color ble html 字節流 為我 href 文件中 通過File對象可以讀取文件或者文件夾的屬性數據,如果要讀取文件的內容數據,那麽我們就要使用IO技術。 1、IO流分類 按照數據的流向劃分: 輸入流:把硬盤(或內存)中的數據讀到程

java基礎IO(一)

目標 構造方法 play pub io流 ted ima str 有一個 java基礎之IO流(一)之字節流   IO流體系太大,涉及到的各種流對象,我覺得很有必要總結一下。   那什麽是IO流,IO代表Input、Output,而流就是原始數據源與目標媒介的數據傳輸的一種

java基礎50 IO技術()

blank html 點擊 log 謝謝 幫助 target str 主頁 1、待續 待續 原創作者:DSHORE 作者主頁:http://www.cnblogs.com/dshore123/ 原文出自:https://www

java基礎54 IO技術(轉換

shadow bili cnblogs lin iter checkbox exc center div 1、轉換流 1.輸入字節的轉換流:InputStreamReader是字節流轉為字符流的橋梁,可以把輸入字節流轉換為輸入字符流 2.輸出字節流的轉換流:O

Java : java基礎(3) IO

log 讀一行 改變 上一個 system.in 指定 cti 前行 效果 流按操作類型分為兩種,字節流,字符流,按流向分為輸入流,輸出流,輸入流的抽象父類InputStream,輸出流抽象父類OutputStream,字符流的抽象父類是Reader和Writer 一般用字

java基礎知識-IO-位元組

耐得住寂寞,才能守得住繁華 流 1、在java中,所有的資料都是使用流讀寫的,流就像水流一樣,將資料從一個地方帶到另一個地方。 2、流是程式中的資料所經歷的的路徑,輸入流將資料從資料來源傳遞給程式,而輸出流將資料傳送到某個目的地。 流的分類 位元組流 位元組流傳送0

Java基礎IO小結

      Java程式中對於資料的輸入和輸出操作是以流的方式進行的。一個流可以被定義為一個數據序列。我們可以理解為:流是用來讀寫資料的。Java語言提供的java.io包可以很方便的讓我們對資料進行輸入和輸出操作。本文將和大家分享學習Java IO流的相關基礎知識。 一、

JAVA基礎21-IO

1.流分類 不同角度對流進行分類: 1.根據資料單位不同,字元流,位元組流 2.資料流方向可分為,輸入流,輸出流 3.功能不同,可分為:節點流,處理流。 2.流的體系 Java中所有的流類位於java.io包,分別繼承以下四種抽象流型別

Java基礎知識IO(File)

File概述 File類用來將檔案或者資料夾封裝成物件。方便對檔案和資料夾的屬性資訊進行操作。 構造方法: 1.File(File parent, String child) 根據 parent 抽象路徑名和 child 路徑名字串

java基礎知識--IO示例

本人的GitHub:戳我一下 示例(一)——File類的基本用法 /** * File類的基本用法 */ package com.yifanjia.one; import java.io.*

Java基礎知識-IO2

21.01_IO流(字元流FileReader) 1.字元流是什麼 字元流是可以直接讀寫字元的IO流 字元流讀取字元, 就要先讀取到位元組資料, 然後轉為字元. 如果要寫出字元, 需要把字元轉為位元組再寫出. 2.FileReader FileR

java基礎知識---IO

IO流:★★★★★,用於處理裝置上資料。 流:可以理解資料的流動,就是一個數據流。IO流最終要以物件來體現,物件都存在IO包中。 流也進行分類: 1:輸入流(讀)和輸出流(寫)。 2:因為處理的資料不同,分為位元組流和字元流。 位元組流:處理位元組資料的流物件。裝置上的

java基礎知識IO

博主作為一個接觸java時間比較短的開發人員,本篇文章記錄博主學習IO流的一些知識。 IO流用來處理裝置之間的資料傳輸,舉個例子:對於傳統的web專案來說,IO流就是就是處理記憶體和硬碟之間的資料傳輸。java對資料的處理就是通過流來實現的,java用於操作流的物件都在IO

Java基礎知識IO(位元組的快取區並自定義)

位元組流快取區 自定義位元組流快取區 read()和write()方法的特點 位元組流快取區 位元組流也有快取區 BufferedInputStream BufferedInputStream 為另一個輸入流新增一些功能,即緩衝輸入以及支援 ma

黑馬程式設計師--JAVA基礎IO

一 IO流的三種分類方式:  1.按照流向來分:                輸入流:只能從中讀取位元組資料,不能向其寫出資料                      輸出流:只能向其寫入位元組資料,不能從中讀取資料  2.按照流所處理的資料型別劃分:可分為: 位元組流:用於處理位元組

Java基礎IO 中的 flush

Java設計Io流可謂是煞費苦心,如果你是初學者我敢保證第一次接觸Java的IO類,一定會“狂暈!!”,暈,倒不是因為它有多麼難學,而是太多,而且及其讓人容易迷惑。在程式設計日子中,尤其是在網路程式設計中,幾乎離不開Java的IO,關於Java的IO流的分類,可以到網上so

java基礎IO遞歸理解

示例代碼 font hid 再次 調用方法 反斜杠 filter amp 遞歸 一、IO流(簡單理解是input/output流,數據流內存到磁盤或者從磁盤到內存等) 二、File類(就是操作文件和文件夾的) 1、FIleFile類構造方法 註意:通過構造方法創建的f