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
        计划二               :         des4, after des3, 5d
  • 关于 甘特图 语法,参考 这儿,

UML 图表

可以使用UML图表进行渲染。 Mermaid. 例如下面产生的一个序列图::

张三 李四 王五 你好!李四, 最近怎么样? 你最近怎么样,王五? 我很好,谢谢! 我很好,谢谢! 李四想了很长时间, 文字太长了 不适合放在一行. 打量着王五... 很好... 王五, 你怎么样? 张三 李四 王五

这将产生一个流程图。:

链接
长方形
圆角长方形
菱形
  • 关于 Mermaid 语法,参考 这儿,

FLowchart流程图

我们依旧会支持flowchart的流程图:

  • 关于 Flowchart流程图 语法,参考 这儿.

导出与导入

导出

如果你想尝试使用此编辑器, 你可以在此篇文章任意编辑。当你完成了一篇文章的写作, 在上方工具栏找到 文章导出 ,生成一个.md文件或者.html文件进行本地保存。

导入

如果你想加载一篇你写过的.md文件或者.html文件,在上方工具栏可以选择导入功能进行对应扩展名的文件导入,
继续你的创作。


  1. mermaid语法说明 ↩︎

  2. 注脚的解释 ↩︎

猜你喜欢

转载自blog.csdn.net/ugghhj/article/details/84076795