Java编程思想学习-Java I/O

File类

{Args:"D.*\.java"}
public class DirList{
    public static void main(String [] args){
        File path =new File(".");
        String [] list;
        if(args.length==0)
            list=path.list();
        else
            list=path.list(new  DirFilter(arg[0]));
        Arrays.sort(list,String.CASE_INSENTIVE_ORDER);
        for(String dirItem :list)
            System.out.println(dirItem);
        }
    }

class DirFileter implements FilenameFilter{
    private Pattern pattern;
    public DirFilter(String regex){
        pattern=Pattern.complex(regex);
    }
    public boolean accept(File dir,String name){
        return pattern.matcher(name).matcher();
    }
}/*output:
DirectoryDemo.java
DirList.java
DirList2.java
DirList3.java
*/

这里,DirFileter类实现了FilenameFilter接口。
publi interface FilenameFilter{
        boolean accept(File dir,String name);
    }
DirFilter这个类存在的唯一原因就是将accept()方法,提供给list()使用,使list()可以回调accept(),进而决定哪些文件包含在列表中。

这种结构常常称为回调。更具体地说,这是一个策略模式的例子,因为list()实现里基本的功能,而且按照FilenameFilter的形式提供策略
下面是策略设计模式的另一个设计:

        public class ProcessFiles{
            public interface Strategy{
                void process(File file);
            }
            private Strategy strategy;
            private String ext;
            public ProcessFiles(Strategy strategy,Strign ext){
            this.strategy=strategy;
            this.ext=ext;
            }
            public void start(String [] args){
                try{
                    if(args.length==0)
                    processDirectoryTree(fileArg);
                    else{
                        for(String arg :args){
                        File fileArg=new File(arg);
                        if(fileArg.idDirectory())
                            processDirectoryTree(fileArg);
                        else{
                        if(!arg.endsWith("."+ext))
                        arg+="."+ext;
                        strategy.process(new File(arg).getCannonicalFile());
                        }
                    }
                }catch(IOException e){
                    throw new RuntimeException(e);
                }
            }
        }
        public void processDirectoryTree(File root) throw IOException{
            for(File file: Directory.walk(root.getAbsolutePath(),".*\\."+ext))
            strategy.process(file.getCannonicalFile());
        }
        public static void main(String[] args){
            new ProcessFiles(new ProcessFiles.Strategy(){
                public void process(File file){
                    System.out.println(file);
                }
            },"java").start(args);
        }
    }       

Strategy接口内嵌ProcessFiles中,使得如果你希望实现它,就必须实现ProcessFiles.Strategy。ProcessFiles执行了查找具有特定扩展名的文件所需的全部工作,并且当它找到匹配的文件时,将直接把文件传递给Strategy对象。如果你没有提供任何参数,那么ProcessFiles就假设你希望遍历当前目录下的所有目录。

输入和输出

通过继承,任何自Inputstream或Reader派生而来的类都含有名为read()的基本方法,用于读取单个字节或者字节数组。同样,任何自OutputStream或Writer派生而来的类都含有名为write()的基本方法,用于写单个字节或字节数组。

InputStream类型(所有和输入有关的都是它的子类)

InputStream的作用是用来表示那些从不同数据源产生的输入的类。
  1. 字节数组
  2. String对象
  3. 文件
  4. “管道”,工作方式和实际管道相似,即从一段输入,从另一端输出。
  5. 一个有其他种类的流组成的序列,比便我们可以将他们收集并到一个流内。

    每一种数据源都有相应的InputStream子类.另外,FilterInputStream也属于一种InputStream,为”装饰器”类提供基类,其中”装饰器”类可以把属性或有用的接口与输入流连接在一起。

    表1-1 InputStream

功能构筑器参数,即使用
ByteArrayInputStream允许将内存的缓冲区当中InputStream的使用缓冲区,字节将从中取出。 作为一种数据源:将其与FilterInputStream对象相连以提供有用的接口
StringBufferInputStream将String转换成InputStream字符串,底层实现实际使用StringBuffer。 作为一种数据源:将其与FilterInputStream对象相连以提供有用接口
FileInputStream用于从文件中读取信息字符串,表示文件名、文件或FilterInputStream对象相连以提供有用的借口
PipedInputStream产生用于写入相关PipedOutputStream的数据。实现”管道化”的概念PipedOutputStream.作为多线程中数据源:将其与FilterInputStream对象相连以提供有用接口
SequenceInputStream将两个或多个InputStream对象转换成单一InputStream两个InputStram对象或一个容纳InputStream对象的容器Enumeration.作为一种数据源:将其与FilterInputStream对象相连以提供有用的接口。
FilterInputStream抽象类,作为”装饰器”的接口。其中,“装饰器”为其他的Inputtream类提供有用的功能.见表1-3见表1-3 见表1-3

OutputStream类型

**如表1-2所示,该类别的类决定了输出所要去往的目标:字节数组(但不是String,不过你当然可以用字节数组自己创建)、文件或管道。
另外,FilterOutputStream为"装饰器"类提供了一个基类,其中"装饰器"类可以把属性或有用的接口与输入流连接在一起。**

**表1-2 OutputStream**
功能构筑器参数,即使用
ByteArrayOutputStream在内存中创建缓冲区。所有送往”流”的数据都要放置在此缓冲区缓冲区初始化尺寸(可选的)。 用于指定数据的目的地:将其与FilterOutputStream对象相连以提供有用的接口
FileOutputStream用于将信息写至文件字符串,表示文件名、文件或FileDescriptor对象。 指定数据的目的地:将其与FilterOutputStream对象相连以提供有用接口。
PipedOutputStream任何写入其中的信息都会自动作为相关PipedInputStream的输出。实现”管道化”概念。PipedInputStream指定用于多线程的数据的目的地:将其与FilterOutputStream对象相连以提供有用借口。
FilterOutPutStream抽象类,作为”装饰器”的接口。其中,”装饰器”为其他OutputStream提供有用功能。见表1-4见表1-4;见表1-4

添加属性和有用的接口

FilterInputStream和FilterOutputStream是用来提供装饰器类接口以控制特定输入流(InputStream)和输出流(OutputStream)的两个类。也是他们的子类。
通过FilterInputStream从InputStream读取数据
FilterInputStream类能够完成两件完全不同的事情。其中,DataInputStream允许我们读取,不同的基本类型数据以及String对象(所有方法都以”read”开头,例如readByte(),readFloat()等)。搭配相应的DataOutputStream,我们就可以通过数据”流”将基本类型的数据从一个地方迁徙至另一个地方。
表1-3 FilterInputStream类型

功能构筑器参数,即使用
DataInputStream与DataOutputStream搭配使用,因此我们可以按照可移植方式从流读取基本数据类型(int,char,long等)InputStream包括用于读取基本类型的全部接口
BufferedInputStream使用它可以防止每次读取时都得进行实际写操作。代表”使用缓冲区”InputStream,可以指定缓冲区大小。 本质上不是提供接口,只不过是想进程中添加缓冲区所必需的。与接口对象搭配
LineNumberInputStream跟踪输入流中的行号;可调用getLineNumber()和setLineNumber(int)InputStream 。仅增加了行号,因此可能要与接口对象搭配使用
PushbackInputStream具有”能弹出一个字节的缓冲区”。因此可以将读到的最后一个字符回退InputStream。通常作为编辑器的扫描器,之所以包含在内是因为java编译器的需要,我们可能永远不会用到

通过FilterOutputStream向OutputStream写入

表1-4 FilterOutputStream类型

功能构筑器参数,即使用
DataOutputStream与DataInputStream搭配使用,因此可以按照可移植方式向流中写入基本类型数据(int,char,long等)OutPutStream包含用于写入基本类型数据全部接口
PrintStream用于产生格式化输出。其中DataOutputStream处理数据的存储,PrintStream处理显示OutputStream,可以用boolean值指示是否在每次换行时清空缓存区应该是对OutputStream对象的”final”封装.可能会常常使用它。
BufferedOutputStream使用它以避免每次发送数据时都要进行实际的写操作。代表”使用缓冲区”.可以调用flush()清空缓存区OutputStream,可以指定缓冲区大小。 本质上并不是提供接口,只不过是向进程中添加缓冲区所必需的。与接口对象搭配

Reader和Writer

Reader和writer提供兼容Unicode与面向字符的I/O功能。有时候我没必须把来自”字节”层次结构中的泪和”字符”层次结构中的类结合起来使用。为了实现这个目的,要用到”适配器”adapter类:InputStreamReader可以把InputStream转换成Reader,而OutputStreamWriter可以把OutputStream转换成Writer.
1.数据的来源和去处
这里写图片描述
2.更改流的行为
有一点很清楚:无论我们何时使用readLine(),都不应该使用DataInputStream(这会遭到编译器的强烈反对),而应该使用BufferedReader.出来这一点,DataInputStream仍是I/O类库的首选成员。
为了更容易地过渡到使用PrintWriter,它提供了一个既能接受Writer对象又能接受任何OutputStream对象的构造器。PrintWriter的格式化接口实际上与PrintStream相同。
3 I/O流的典型使用方式

3.1 缓冲输入文件

    public class BufferedInputFile{
        public  static String read(String filename) throws IOException{
        BufferedReader in=new BufferedReader(new FileReader(filename);
        String s;
        StringBuilder sb=new BufferedReader();
        while((s=in.readLine()!=null)
            sb.append(s+"\n");
        in.close();
        return sb.toString();
        }
        public static void main(String [] args)
            throws IOException{          System.out.println(read("BufferedInputFile.java"));
        }
    }   

字符串sb用来积累文件的全部内容(包括必须添加的换行符,因为readLine()已将它们删除)。最后,调用close()方法关闭文件。

3.2 从内存输入

下面实例,用到了上述3.1的BufferedInputFlie.java代码。

        public class MemoryInput{
            public static void main(String[] args)
            throws IOException{
                StringReader in=new StringReader(BufferredInputFile.read("MemoryInput.java"));
                int c;
                while((c=in.read())!=-1)
                    System.out.println((char)c);
            }
        }   

注意read()是以int 形式返回下一字节,因此必须类型转换为char才能正确打印。

3.3 格式化的内存输入

下面实例,用到了上述3.1的BufferedInputFlie.java代码。
要读取格式化数据,可以使用DataInputStream,它是以面向字节的I/O类。因此我们必须使用InputStream类而不是Reader类。

    public class FormattedMemoryInput{
        public static void main(String [] args)
        throws IOException{
            try{
                DataInputStream in=new DataInputStream(new ByteArrayInputStream(BufferedInputFile.read("FormattedMemotyInput.java").getBytes()));
                while(true)//or while(in.available()!=0)
                    System.out.print((char)in.readByte());
                }catch(EOFException e){
                    System.out.prinln("End of stream");
                }
            }
        }

必须为ByteArrayInputStream提供字节数组。ByteArrayInputStream是一个适合传递给DataInputStream的InputStream.
注意,available()的工作方式会随着所读取得媒介类型的不同而不同。字面上就是“在没阻塞的情况下所能读取的字节数”.对于文件,这意味着整个文件;对于不同类型的刘,可能就不是这样。

3.4 基本的文件输出

下面实例,用到了上述3.1的BufferedInputFlie.java代码。
FileWriter对象可以向文件写入数据。首先,创建一个与指定文件连接的FileWriter.实际上,我们通常会用BufferedWriter将其包装起来以缓冲输出。本例中,为了提供格式化机制,它被装饰成了PrintWriter.按照这种方式创建的数据文件可作为普通文本文件的读取。

    public class BasicFileOutput{
        static String file="BasicFileOutput.out";
        public static void main(String [] args)
        throws IOException{
            BufferedReader in=new BufferedReader(new StringReader(BufferedInputFile.read("BasicFileoutput.java")));
        PrintWriter out =new PrintWriter(new BufferedWriter(new FileWriter(file)));
        //or  PrintWriter out=new PrintWriter(file);
        int lineCount=1;
        String s;
        while((s=in.readLine())!=null)
            out.println(lineCount++ +":"+s);
        int lineCount=1;
        String s;
        while((s=in.readLine())!=null)
            out.println(lineCount++ +":"+s);
        out.close();
        System.out.println(BufferedInputFile(file));
        }
    }
一旦读完输入数据流,readLine()会返回Null.只有out显示调用close(),缓冲区的内容才会被刷新。
也可以使用or后面的快捷方式。你仍然是在进行缓存只是不必自己去实现。遗憾的事其他常见的写入任务,都没用快捷方式。

3.5 存储和恢复数据

PrintWriter可以对数据进行格式化,以便人们的阅读。但是为了输入可供另一个”流”恢复的数据,我们需要用DataOutputStream写数据,并用DataInputStream恢复数据。当然流可以是任何形式.

    public class StoringAndRecoveringData{
        public static void main(String [] args)
        throws IOException{
            DataOutputStream out=new DataOutputStream(new BufferedOutputStream(new FileOutputStream("Data.txt")));
            out.writeDouble(3.13159);
            out.writeUTF("Square root of 2");
            out.close();
            DataInputStream in=new DataInputStream(new BufferedInputStream(new FileInputStream("Data.txt")));
            System.out.println(in.readDouble());
            System.out.println(in.readUTF());
            System.out.println(in.readDouble());
            System.out.println(in.readUTF());
        }
    }/*output:
    3.13159
    That was pi
    1.41413
    Square root of 2
    */

如果我们使用DataOutputStream写入数据,java保证我们可以使用DataInputStream准确地读取数据–无论读和写数据的平台多么不同.
但是为了保证所有的读方法都能正常工作,我们必须知道流中数据项所在的确切位置,因为极有可能将保持的double数据作为一个简单的字节序列、char或其他类型读入。因此我们必须:要么为文件中的数据采用固定的格式;要么将额外的消息保存在文件中,比便能够对其进行解析。注意,对象序列化和xml可能是更容易存储和读取复杂数据结构的方式。

3.6 读取随机

使用RandomAccessFile,类似于组合了DataInputStream和DataOutPutStream(因为它实现了相同的接口:DataInput和DataOutput).另外我们可以看到,利用seek()可以在文件中移动,并修改某个值。

    public class UsingRandomAccessFile{
        static String file="rtest.dat";
        stativ void display() throws IOException{
            RandomAccessFile rf=new RandomAccessFile(file,"r");
            for(int i=0;i<7;i++)
            System.out.println(rf.readUTF());
            rf.close();
        }
        public static void main(String [] args)
        Throws IOException{
            RandomAccessFile rf=new RandomAccessFile(file,"rw");
            for(i=0;i<7;i++)
                rf.writeDouble(i*1.414);
            rf.writeUTF("The end of the file");
            rf.close();
            display();
            rf=new RandomAccessFie(file,"rw");
            rf.seek(5*8);
            rf.writeDouble(47.0001);
            rf.close();
            display();
        }/*Output
        value 0:0.0
        value 1:1.414
        value 2:2.828
        value 3:4.242
        value 4:5.656
        value 5:7.069999999999999
        value 6:8.484
        The end of the file
        value 0:0.0
        value 1:1.414
        value 2:2.828
        value 3:4.242
        value 4:5.656
        value 5:47.0001
        value 6:8.484
        The end of the file
        */

RandomAccessFile不支持装饰,第二个参数可以指定”r(只读)”或”rw(读写)”.

3.7.1 文件读写的一个实用工具
    public class TextFile extends ArrayList<String>{
        public static String read(String fileName){
            StringBuilder sb=new StringBuilder();
            try{
                BufferedReader in=new BufferedReader(
                new FileReader(new File(fileName)
                .getAbsoluteFile()));
                try{
                    String s;
                    while((s=in.readLine())!=null){
                        sb.append(s);
                        sb.append("\n");
                    }
                }finally{
                    in.close();
                }
            }catch(IOException e){
                throw new RuntimeException(e);
            }
            return sb.toString();
        }
        public static void write(String fileName,String text){
            try{
                PrintWriter out=new PrintWriter(
                new File(fileName).getAbsoluteFile());
                try{
                    out.print(text);
                    }finally{
                    out.close();
                    }
                }catch(IOException e){
                    throw new RuntimeException(e);
                }
        }
        public TextFile(String fileName,String splitter){
                    super(Arrays.asList(read(fileName).split(splitter)));
        if(get(0).equals("")) remove(0);
        }
        public TextFile(String fileName){
            this(fileName,"\n");
        }
        public void write(String fileName){
            try{
                PrintWriter out=new PrintWriter(
                new File(fileName).getAbsoluteFile());
              try{
                  for(String item:this)
                  out.println(item);
                }finally{
                out.close();
                }
            }catch(IOException e){
                throw new RuntimeException(e);
            }
        }
        public static void main(Stirng []args){
            String file=read("TextFile.java");
            write("test.txt",file);
            TextFile text=new TextFile("test.txt");
            text.write("test2.txt");
            TreeSet<String> words=new TreeSet<String>(
            new TextFile("TextFile.java","\\W+"));
            System.out.println(words.headSet("a"));
        }
    }/*Output:
[0,ArrayList,Arrays,Break,BufferedReader,BufferedWriter,Clean,Display,File,FileReader,FileWriter,IOException,Normally,Output,PrintWriter,Read,Regulay,RuntimeException,Simple,Static,String,StringBuilder,System,TextFile,Tools,TreeSet,W,Write]
*/              
3.7.2 读取二进制文件
    public class BinaryFile{
        public static byte[] read(File bFile) Throws 
        IOException{
            BufferredInputStream bf=new BufferedInputStream(new FileInputStream(bFile));
            try{
                byte[] data=new byte[bf.available()];
                bf.read(data);
                return data;
            }finally{
                bf.close();
            }
        }
        public static byte[] read(String bFile)
        throws IOException{
            return read(new File(bFile).getAbsoluteFile());
            }
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值