1. 程式人生 > >33 JAVA程式設計思想——JAVA IO File類

33 JAVA程式設計思想——JAVA IO File類

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow

也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!

               

33.JAVA程式設計思想——JAVA IO File類

RandomAccessFile用於包含了已知長度記錄的檔案,以便我們能用 seek()從一條記錄移至另一條;然後讀取或修改那些記錄。各記錄的長度並不一定相同;只要知道它們有多大以及置於檔案何處即可。

首先,我們有點難以相信RandomAccessFile 不屬於InputStream 或者OutputStream 分層結構的一部分。除了恰巧實現了DataInput 以及DataOutput(這兩者亦由 DataInputStream和DataOutputStream實現)介面之外,它們與那些分層結構並無什麼關係。它甚至沒有用到現有InputStream 或OutputStream 類的功能——採用的是一個完全不相干的類。該類屬於全新的設計,含有自己的全部(大多數為固有)方法。之所以要這樣做,是因為RandomAccessFile 擁有與其他 IO型別完全不同的行為,因為我們可在一個檔案裡向前或向後移動。不管在哪種情況下,它都是獨立運作的,作為Object 的一個“直接繼承人”使用。

從根本上說,RandomAccessFile 類似DataInputStream和 DataOutputStream的聯合使用。其中,getFilePointer()用於瞭解當前在檔案的什麼地方,seek()用於移至檔案內的一個新地點,而 length()用於判斷檔案的最大長度。此外,構建器要求使用另一個自變數(與C 的fopen()完全一樣),指出自己只是隨機讀("r"),還是讀寫兼施("rw")。這裡沒有提供對“只寫檔案”的支援。也就是說,假如是從DataInputStream繼承的,那麼 RandomAccessFile也有可能能很好地工作。

還有更難對付的。很容易想象我們有時要在其他型別的資料流中搜索,比如一個ByteArrayInputStream,但搜尋方法只有RandomAccessFile 才會提供。而後者只能針對檔案才能操作,不能針對資料流操作。此時,BufferedInputStream 確實允許我們標記一個位置(使用mark(),它的值容納於單個內部變數中),並用reset()重設那個位置。但這些做法都存在限制,並不是特別有用。

1.  File類

File 類有一個欺騙性的名字——通常會認為它對付的是一個檔案,但實情並非如此。它既代表一個特定檔案的名字,也代表目錄內一系列檔案的名字。若代表一個檔案集,便可用list()方法查詢這個集,返回的是一個字串陣列。之所以要返回一個數組,而非某個靈活的集合類,是因為元素的數量是固定的。而且若想得到

一個不同的目錄列表,只需建立一個不同的File 物件即可。事實上,“FilePath”(檔案路徑)似乎是一個更好的名字。

1.1             目錄列表器

假設想觀看一個目錄列表。可用兩種方式列出File 物件。若在不含自變數(引數)的情況下呼叫list(),會獲得 File 物件包含的一個完整列表。然而,若想對這個列表進行某些限制,就需要使用一個“目錄過濾器”,該類的作用是指出應如何選擇File 物件來完成顯示。

例子的程式碼:

l  程式碼如下

import java.io.*;

publicclassDirList {

    publicstatic void main(String[]args) {

        try {

            Filepath=newFile(".");

            String[]list;

            if (args.length == 0)

                list = path.list();

            else

                list = path.list(new DirFilter(args[0]));

            for (inti = 0; i < list.length; i++)

                System.out.println(list[i]);

        }catch(Exceptione) {

            e.printStackTrace();

        }

    }

}

class DirFilterimplements FilenameFilter {

    Stringafn;

    DirFilter(Stringafn){

        this.afn =afn;

    }

    publicboolean accept(File dir, String name) {

        // Strip path information:

        Stringf =new File(name).getName();

        returnf.indexOf(afn) != -1;

    }

} /// :~

l  執行

.classpath

.project

.settings

bin

src

DirFilter 類“實現”了interface FilenameFilter。下面讓我們看看FilenameFilter介面有多麼簡單:

public interface FilenameFilter {

boolean accept(檔案目錄, 字串名);

}

它指出這種型別的所有物件都提供了一個名為 accept()的方法。之所以要建立這樣的一個類,背後的全部原因就是把accept()方法提供給 list()方法,使list()能夠“回撥”accept(),從而判斷應將哪些檔名包括到列表中。因此,通常將這種技術稱為“回撥”,有時也稱為“運算元”(也就是說,DirFilter 是一個運算元,因為它唯一的作用就是容納一個方法)。由於 list()採用一個 FilenameFilter 物件作為自己的自變數使用,所以我們能傳遞實現了FilenameFilter 的任何類的一個物件,用它決定(甚至在執行期)list()方法的行為方式。回撥的目的是在程式碼的行為上提供更大的靈活性。

通過DirFilter,我們看出儘管一個“介面”只包含了一系列方法,但並不侷限於只能寫那些方法(但是,至少必須提供一個介面內所有方法的定義。在這種情況下,DirFilter 構建器也會建立)。accept()方法必須接納一個 File 物件,用它指示用於尋找一個特定檔案的目錄;並接納一個String,其中包含了要尋找之檔案的名字。可決定使用或忽略這兩個引數之一,但有時至少要使用檔名。記住list()方法準備為目錄物件中的每個檔名呼叫accept(),核實哪個應包含在內——具體由 accept()返回的“布林”結果決定。

為確定我們操作的只是檔名,其中沒有包含路徑資訊,必須採用String物件,並在它的外部建立一個File 物件。然後呼叫 getName(),它的作用是去除所有路徑資訊(採用與平臺無關的方式)。隨後,accept()用String 類的indexOf()方法檢查檔名內部是否存在搜尋字串"afn"。若在字串內找到 afn,那麼返回值就是afn 的起點索引;但假如沒有找到,返回值就是-1。注意這只是一個簡單的字串搜尋例子,未使用常見的表示式“萬用字元”方案,比如"fo?.b?r*";這種方案更難實現。

list()方法返回的是一個數組。可查詢這個陣列的長度,然後在其中遍歷,選定陣列元素。與 C 和C++的類似行為相比,這種於方法內外方便遊歷陣列的行為無疑是一個顯著的進步。

1.2             匿名內部類

l  程式碼如下

用一個匿名內部類來重寫顯得非常理想。首先建立了一個filter()方法,它返回指向FilenameFilter 的一個控制代碼:

import java.io.*;

publicclassDirList2 {

    publicstatic FilenameFilter filter(final Stringafn) {

        // Creation of anonymous inner class:

        returnnew FilenameFilter() {

            Stringfn =afn;

            publicboolean accept(File dir, String n) {

                // Strip path information:

                Stringf =new File(n).getName();

                returnf.indexOf(fn) != -1;

            }

        };// End of anonymous inner class

    }

    publicstatic void main(String[]args) {

        try {

            Filepath=newFile(".");

            String[]list;

            if (args.length == 0)

                list = path.list();

            else

                list = path.list(filter(args[0]));

            for (inti = 0; i < list.length; i++)

                System.out.println(list[i]);

        }catch(Exceptione) {

            e.printStackTrace();

        }

    }

} /// :~

 

l  執行

.classpath

.project

.settings

bin

src

注意filter()的自變數必須是final。這一點是匿名內部類要求的,使其能使用來自本身作用域以外的一個物件。

之所以認為這樣做更好,是由於FilenameFilter 類現在同DirList2 緊密地結合在一起。然而,我們可採取進一步的操作,將匿名內部類定義成list()的一個引數,使其顯得更加精簡。

l  程式碼2

import java.io.*;

 

publicclassDirList3 {

    publicstatic void main(final String[]args) {

        try {

            Filepath=newFile(".");

            String[]list;

            if (args.length == 0)

                list = path.list();

            else

                list = path.list(new FilenameFilter() {

                    publicboolean accept(File dir, String n) {

                        Stringf =new File(n).getName();

                        returnf.indexOf(args[0]) != -1;

                    }

                });

            for (inti = 0; i < list.length; i++)

                System.out.println(list[i]);

        }catch(Exceptione) {

            e.printStackTrace();

        }

    }

} /// :~

l  執行

.classpath

.project

.settings

bin

src

main()現在的自變數是 final,因為匿名內部類直接使用args[0]。

這展示瞭如何利用匿名內部類快速建立精簡的類,以便解決一些複雜的問題。由於Java 中的所有東西都與類有關,所以它無疑是一種相當有用的編碼技術。它的一個好處是將特定的問題隔離在一個地方統一解決。但在另一方面,這樣生成的程式碼不是十分容易閱讀,所以使用時必須慎重。

1.3             順序目錄列表

經常都需要檔名以排好序的方式提供。由於 Java 1.0 和Java 1.1 都沒有提供對排序的支援(從 Java 1.2開始提供),用建立的 SortVector將這一能力直接加入自己的程式。

l  程式碼

import java.io.*;

publicclassSortedDirList {

    private Filepath;

    private String[]list;

    public SortedDirList(final Stringafn) {

        path = new File(".");

        if (afn ==null)

            list = path.list();

        else

            list = path.list(new FilenameFilter() {

                publicboolean accept(File dir, String n) {

                    Stringf =new File(n).getName();

                    returnf.indexOf(afn) != -1;

                }

            });

        sort();

    }

    void print() {

        for (inti = 0; i < list.length; i++)

            System.out.println(list[i]);

    }

    privatevoid sort() {

        StrSortVectorsv =new StrSortVector();

        for (inti = 0; i < list.length; i++)

            sv.addElement(list[i]);

        // The first time an element is pulled from

        // the StrSortVector the list is sorted:

        for (inti = 0; i < list.length; i++)

            list[i] = sv.elementAt(i);

    }

    // Test it:

    publicstatic void main(String[]args) {

        SortedDirListsd;

        if (args.length == 0)

            sd = new SortedDirList(null);

        else

            sd = new SortedDirList(args[0]);

        sd.print();

    }

} /// :~

l  執行

.classpath

.project

.settings

bin

src

這裡進行了另外少許改進。不再是將path(路徑)和 list(列表)建立為main()的本地變數,它們變成了類的成員,使它們的值能在物件“生存”期間方便地訪問。事實上,main()現在只是對類進行測試的一種方式。一旦列表建立完畢,類的構建器就會自動開始對列表進行排序。

這種排序不要求區分大小寫,所以最終不會得到一組全部單詞都以大寫字母開頭的列表,跟著是全部以小寫字母開頭的列表。然而,我們注意到在以相同字母開頭的一組檔名中,大寫字母是排在前面的——這對標準的排序來說仍是一種不合格的行為。Java 1.2 已成功解決了這個問題。

1.4             檢查與建立目錄

File 類並不僅僅是對現有目錄路徑、檔案或者檔案組的一個表示。亦可用一個 File 物件新建一個目錄,甚至建立一個完整的目錄路徑——假如它尚不存在的話。亦可用它瞭解檔案的屬性(長度、上一次修改日期、讀/寫屬性等),檢查一個File 物件到底代表一個檔案還是一個目錄,以及刪除一個檔案等等。下列程式完整展示瞭如何運用File 類剩下的這些方法:

l  程式碼

import java.io.*;

 

publicclassMakeDirectories {

    privatefinal static Stringusage = "Usage:MakeDirectories path1 ...\n" + "Creates each path\n"

            +"Usage:MakeDirectories -d path1...\n" +"Deleteseach path\n" + "Usage:MakeDirectories -r path1 path2\n"

            +"Renames from path1 to path2\n";

    privatestatic void usage() {

        System.err.println(usage);

        System.exit(1);

    }

    privatestatic void fileData(Filef) {

        System.out.println("Absolute path: "+f.getAbsolutePath()+ "\n Can read: " + f.canRead() + "\n Can write: "

                +f.canWrite() +"\n getName: "+ f.getName() +"\n getParent: "+ f.getParent() + "\n getPath: "

                +f.getPath() +"\n length: "+ f.length() +"\n lastModified: "+ f.lastModified());

        if (f.isFile())

            System.out.println("it's a file");

        elseif (f.isDirectory())

            System.out.println("it's a directory");

    }

 

    publicstatic void main(String[]args) {

        if (args.length < 1)

            usage();

        if (args[0].equals("-r")) {

            if (args.length != 3)

                usage();

            Fileold=newFile(args[1]),rname=newFile(args[2]);

            old.renameTo(rname);

            fileData(old);

            fileData(rname);

            return;// Exit main

        }

        intcount = 0;

        booleandel = false;

        if (args[0].equals("-d")) {

            count++;

            del = true;

        }

        for (;count < args.length;count++) {

            Filef =new File(args[count]);

            if (f.exists()) {

                System.out.println(f +" exists");

                if (del) {

                    System.out.println("deleting..."+f);

                    f.delete();

                }

            }else{// Doesn't exist

                if (!del) {

                    f.mkdirs();

                    System.out.println("created "+f);

                }

            }

            fileData(f);

        }

    }

} /// :~

l  執行

Usage:MakeDirectories path1 ...

Creates each path

Usage:MakeDirectories -d path1 ...

Deletes each path

Usage:MakeDirectories -r path1 path2

Renames from path1 to path2

加上執行引數:-rtest1.txt test2.txt

然後在目錄中增加test1.txt檔案,執行後

Absolute path: F:\java_test\test1.txt

 Can read: false

 Can write: false

 getName: test1.txt

 getParent: null

 getPath: test1.txt

 length: 0

 lastModified: 0

Absolute path: F:\java_test\test2.txt

 Can read: true

 Can write: true

 getName: test2.txt

 getParent: null

 getPath: test2.txt

 length: 0

 lastModified: 1460890496589

it's a file

 

在fileData()中,可看到應用了各種檔案調查方法來顯示與檔案或目錄路徑有關的資訊。

main()應用的第一個方法是 renameTo(),利用它可以重新命名(或移動)一個檔案至一個全新的路徑(該路徑由引數決定),它屬於另一個File 物件。這也適用於任何長度的目錄。

若試驗上述程式,就可發現自己能製作任意複雜程度的一個目錄路徑,因為mkdirs()會幫我們完成所有工作。在Java 1.0 中,-d標誌報告目錄雖然已被刪除,但它依然存在;但在 Java 1.1 中,目錄會被實際刪除。

2.  附SortVector.java

import java.util.*;

publicclassSortVector extendsVector {

    private Comparecompare; // To hold the callback

    public SortVector(Comparecomp) {

        compare = comp;

    }

    publicvoid sort() {

        quickSort(0,size() - 1);

    }

    privatevoid quickSort(intleft, intright) {

        if (right >left) {

            Objecto1 = elementAt(right);

            inti = left - 1;

            intj = right;

            while (true) {

                while (compare.lessThan(elementAt(++i),o1))

                    ;

                while (j > 0)

                    if (compare.lessThanOrEqual(elementAt(--j),o1))

                        break;// out of while

                if (i >=j)

                    break;

                swap(i,j);

            }

            swap(i,right);

            quickSort(left,i - 1);

            quickSort(i + 1,right);

        }

    }

    privatevoid swap(intloc1, intloc2) {

        Objecttmp= elementAt(loc1);

        setElementAt(elementAt(loc2),loc1);

        setElementAt(tmp,loc2);

    }

} /// :~

3.  附StrSortVector.java

import java.util.*;

interface Compare {

    boolean lessThan(Objectlhs, Object rhs);

 

    boolean lessThanOrEqual(Objectlhs, Object rhs);

} /// :~

publicclassStrSortVector{

    private SortVectorv = new SortVector(

            // Anonymous inner class:

            new Compare() {

                publicboolean lessThan(Object l, Object r) {

                    return ((String)l).toLowerCase().compareTo(((String)r).toLowerCase())< 0;

                }

                publicboolean lessThanOrEqual(Object l, Object r) {

                    return ((String)l).toLowerCase().compareTo(((String)r).toLowerCase())<= 0;

                }

            });

    privateboolean sorted =false;

    publicvoid addElement(String s) {

        v.addElement(s);

        sorted = false;

    }

    public String elementAt(intindex) {

        if (!sorted) {

            v.sort();

            sorted = true;

        }

        return (String)v.elementAt(index);

    }

    publicEnumerationelements() {

        if (!sorted) {

            v.sort();

            sorted = true;

        }

        returnv.elements();

    }

    // Test it:

    publicstatic void main(String[]args) {

        StrSortVector sv = newStrSortVector();

        sv.addElement("d");

        sv.addElement("A");

        sv.addElement("C");

        sv.addElement("c");

        sv.addElement("b");

        sv.addElement("B");

        sv.addElement("D");

        sv.addElement("a");

        Enumeratione =sv.elements();

        while (e.hasMoreElements())

            System.out.println(e.nextElement());

    }

} /// :~

 

 

           

給我老師的人工智慧教程打call!http://blog.csdn.net/jiangjunshow

這裡寫圖片描述 你好! 這是你第一次使用 **Markdown編輯器** 所展示的歡迎頁。如果你想學習如何使用Markdown編輯器, 可以仔細閱讀這篇文章,瞭解一下Markdown的基本語法知識。

新的改變

我們對Markdown編輯器進行了一些功能拓展與語法支援,除了標準的Markdown編輯器功能,我們增加了如下幾點新功能,幫助你用它寫部落格:

  1. 全新的介面設計 ,將會帶來全新的寫作體驗;
  2. 在創作中心設定你喜愛的程式碼高亮樣式,Markdown 將程式碼片顯示選擇的高亮樣式 進行展示;
  3. 增加了 圖片拖拽 功能,你可以將本地的圖片直接拖拽到編輯區域直接展示;
  4. 全新的 KaTeX數學公式 語法;
  5. 增加了支援甘特圖的mermaid語法1 功能;
  6. 增加了 多螢幕編輯 Markdown文章功能;
  7. 增加了 焦點寫作模式、預覽模式、簡潔寫作模式、左右區域同步滾輪設定 等功能,功能按鈕位於編輯區域與預覽區域中間;
  8. 增加了 檢查列表 功能。

功能快捷鍵

撤銷:Ctrl/Command + Z
重做:Ctrl/Command + Y
加粗:Ctrl/Command + B
斜體:Ctrl/Command + I
標題:Ctrl/Command + Shift + H
無序列表:Ctrl/Command + Shift + U
有序列表:Ctrl/Command + Shift + O
檢查列表:Ctrl/Command + Shift + C
插入程式碼:Ctrl/Command + Shift + K
插入連結:Ctrl/Command + Shift + L
插入圖片:Ctrl/Command + Shift + G

合理的建立標題,有助於目錄的生成

直接輸入1次#,並按下space後,將生成1級標題。
輸入2次#,並按下space後,將生成2級標題。
以此類推,我們支援6級標題。有助於使用TOC語法後生成一個完美的目錄。

如何改變文字的樣式

強調文字 強調文字

加粗文字 加粗文字

標記文字

刪除文字

引用文字

H2O is是液體。

210 運算結果是 1024.

插入連結與圖片

連結: link.

圖片: Alt

帶尺寸的圖片: Alt

當然,我們為了讓使用者更加便捷,我們增加了圖片拖拽功能。

如何插入一段漂亮的程式碼片

部落格設定頁面,選擇一款你喜歡的程式碼片高亮樣式,下面展示同樣高亮的 程式碼片.

// An highlighted block var foo = 'bar'; 

生成一個適合你的列表

  • 專案
    • 專案
      • 專案
  1. 專案1
  2. 專案2
  3. 專案3
  • 計劃任務
  • 完成任務

建立一個表格

一個簡單的表格是這麼建立的:

專案 Value
電腦 $1600
手機 $12
導管 $1

設定內容居中、居左、居右

使用:---------:居中
使用:----------居左
使用----------:居右

第一列 第二列 第三列
第一列文字居中 第二列文字居右 第三列文字居左

SmartyPants

SmartyPants將ASCII標點字元轉換為“智慧”印刷標點HTML實體。例如:

TYPE ASCII HTML
Single backticks 'Isn't this fun?' ‘Isn’t this fun?’
Quotes "Isn't this fun?" “Isn’t this fun?”
Dashes -- is en-dash, --- is em-dash – is en-dash, — is em-dash

建立一個自定義列表

Markdown
Text-to- HTML conversion tool
Authors
John
Luke

如何建立一個註腳

一個具有註腳的文字。2

註釋也是必不可少的

Markdown將文字轉換為 HTML

KaTeX數學公式

您可以使用渲染LaTeX數學表示式 KaTeX:

Gamma公式展示 Γ ( n ) = ( n 1 ) ! n N \Gamma(n) = (n-1)!\quad\forall n\in\mathbb N 是通過尤拉積分

Γ ( z ) = 0 t z 1 e t d t &ThinSpace; . \Gamma(z) = \int_0^\infty t^{z-1}e^{-t}dt\,.

你可以找到更多關於的資訊 LaTeX 數學表示式here.

新的甘特圖功能,豐富你的文章

gantt
        dateFormat  YYYY-MM-DD
        title Adding GANTT diagram functionality to mermaid
        section 現有任務
        已完成               :done,    des1, 2014-01-06,2014-01-08
        進行中               :active,  des2, 2014-01-09, 3d
        計劃一               :         des3, after des2, 5d