第十八章 Java I/O系统

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Youyou_0826/article/details/81105885

鉴于CSDN肆无忌惮强奸用户般的广告,博客不再更新,更多动态请移步至个人网站:https://www.youyou-2608.com

第十八章 Java I/O系统

标签 : Java编程思想


对程序语言的设计者来说,创建一个好的输入/输出(I/O)系统一项艰难的任务。

I/O系统不仅要与各种终端打交道,比如输入输出终端,网络连接,文件系统等,并且还需要多种方式,比如顺序,缓冲,二进制等。

Java中提供了大量的类来实现文件操作。

如果缺乏历史的眼光,很快我就会对什么时候该使用哪些类,以及什么时候不该使用他们而搞到迷惑。

18.1 File类

File这个名字并非指代文件,它既能代表一个特定的文件,又能代表一个目录下的文件集合。如果指代的是文件集合的话,可以调用list()方法得到一个包含该目录下文件集合的数组。

18.1.1 目录列表器

查看一个目录列表,可以有两种方法使用File对象:
* 调用不带参数的list()方法获取全部文件集合;
* 使用“过滤器”获得特定类型文件的文件集合。

package com.io;

import java.io.File;
import java.io.FilenameFilter;
import java.util.Arrays;
import java.util.regex.Pattern;

/**
 * @author [email protected]
 * @since 13:34 2018/7/18
 */
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(args[0]));
        }
        assert list != null;
        Arrays.sort(list, String.CASE_INSENSITIVE_ORDER);
        for (String dir : list) {
            System.out.println(dir);
        }
    }
}

class DirFilter implements FilenameFilter {
    private Pattern pattern;

    public DirFilter(String regex) {
        pattern = Pattern.compile(regex);
    }

    @Override
    public boolean accept(File dir, String name) {
        return pattern.matcher(name).matches();
    }
}

output:

.idea
.vscode
out
ThinkInJavaDemo

Process finished with exit code 0

匿名内部类改写:

package com.io;

import java.io.File;
import java.io.FilenameFilter;
import java.util.regex.Pattern;

/**
 * @author [email protected]
 * @since 13:53 2018/7/18
 */
public class DirListA {
    public static FilenameFilter filenameFilter(final String regex) {
        return new FilenameFilter() {
            private Pattern pattern = Pattern.compile(regex);

            @Override
            public boolean accept(File dir, String name) {
                return pattern.matcher(name).matches();
            }
        };
    }

    public static void main(String[] args) {
        /**
         * do something.
         */
    }
}

为了减少DirList类与FilenameFilter类之间的耦合,可以改写如下:

package com.io;

import java.io.File;
import java.io.FilenameFilter;
import java.util.Arrays;
import java.util.regex.Pattern;

/**
 * @author [email protected]
 * @since 13:58 2018/7/18
 */
public class DirListB {
    public static void main(String[] args) {
        File path = new File(".");
        String[] list;
        if (args.length == 0) {
            list = path.list();
        } else {
            list = path.list((dir, name) -> {
                Pattern pattern = Pattern.compile(args[0]);
                return pattern.matcher(name).matches();
            });
        }
        assert list != null;
        Arrays.sort(list, String.CASE_INSENSITIVE_ORDER);
        for (String dir : list) {
            System.out.println(dir);
        }
    }
}

18.1.2 目录使用工具

文件操作在实际开发中是非常常用的,有一个实用的文件工具类会大大提高开发效率。
下面的方法通过一个特定的正则表达式使用local()方法和walk()方法产生特定目录下的整个目录书中的所有文件构成List。

File.listFiles()产生File数组。

18.1.3 目录的检查及创建

可以使用File对象来表示已经存在的文件或者路径,也可以用来创建新的目录或文件。一些File类的常用方法:

  • canRead();
  • canWrite()
  • length();
  • getName();
  • getAbsolutelyPath();
  • lastModified();
  • getParent();
  • renameTo(new File());

18.2 输入和输出

Java中“流”类库让人迷惑的主要原因就在于:创建单一的结果流,却需要创建多个对象。

18.2.1 InputStream类型

InputStream的作用是用来表示那些从不同数据源产生的输入的类。

InputStream类型:

功能 构造参数及使用
ByteArrayInputStream 允许将内存的缓冲区当做InputStream使用 缓冲区,字节将从中取出,作为一种数据源,将其与FilterInputStream对象相连以提供有用接口
StringBufferInputStream 将String转换成InputStream 底层实际使用StringBuffer作为数据源,将其与FilterInputStream对象相连以提供有用接口
FileInputStream 用于从文件读取信息 字符串表示文件名,文件或FileDescriptor对象
PipedInputStream 产生用于写入相关PipedOutputStream的数据 PipedOutputStream作为多线程数据源,将其与FilterInputStream对象相连以提供有用接口
FilterInputStream 抽象类,作为“装饰器”的接口,为其他InputStream类提供有用功能 。。

OutputStream类型:

功能 构造参数及使用
ByteOutputStream 在内存中创建缓冲区,数据的暂时存储区域 缓冲区初始化大小,制定数据的目的地,将其与FilterOutputStream对象相连以提供有用接口
FileOutputStream 用于将信息写至文件 字符串表示文件名,文件或者FileDescriptor对象,将其与FilterOutputStream对象相连以提供有用接口
FilterOutputStream 抽象类,作为“装饰器”的接口,为其他OutputStream提供有用功能 。。

18.3 添加属性和有用的接口

18.3.1 通过FilterInputStream从InputStream输入

FilterInputStream类型:

功能 构造器和参数
DataInputStream 与DataOutputStream搭配使用 InputStream包含用于读取本类型数据的全部接口
BufferedInputStream 可以防止每次读取时都进行实际写操作,代表使用“缓冲区” InputStream,可以指定缓冲区大小
LineNumberInputStream 跟踪输入流中的行号,可调用getLineNumber()和setLineNumber(int) 仅增加了行号
PushbackInputStream 具有“能弹出一个字节的缓冲区”因此可以将读到的最后一个字节回退 通常作为编译器的扫描器,存在的原因是因为Java编译器的需要,极不常用

18.3.2 通过FilterOutputStream向OutputStream写入

FilterOutputStream类型:

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

18.4 Reader和Writer

18.4.1 数据的来源和去处

来源 去处
InputStream OutputStream
FileInputStream FileOutputStream
StringBufferInputStream StringBufferOutputStream
ByteArrayInputStream ByteOutputStream
PipedInputStream PipedOutputStream

18.6 典型的I/O流使用方式

18.6.1 缓冲输入文件

package com.io;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

/**
 * @author [email protected]
 * @since 21:22 2018/7/18
 */
public class BufferedInputFile {
    public static String read(String fileName) throws IOException {
        BufferedReader in = new BufferedReader(new FileReader(fileName));
        String s;
        StringBuilder stringBuilder = new StringBuilder();
        while ((s = in.readLine()) != null) {
            stringBuilder.append(s).append("\n");
        }
        in.close();
        return stringBuilder.toString();
    }

    public static void main(String[] args) throws IOException {
        System.out.println(read("BufferedInputFile.java"));
    }
}

18.6.2 从内存输入

package com.io;

import java.io.IOException;
import java.io.StringReader;

/**
 * @author [email protected]
 * @since 21:28 2018/7/18
 */
public class FormattedMemoryInput {
    public static void main(String[] args) throws IOException {
        StringReader in = new StringReader(BufferedInputFile.read("demo.java"));
        int c;
        while ((c = in.read()) != -1) {
            System.out.println((char) c);
        }
    }
}
package com.io;

import java.io.*;

/**
 * @author [email protected]
 * @since 21:32 2018/7/18
 */
public class TestEOF {
    public static void main(String[] args) throws IOException {
        DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream("")));
        while (in.available() != 0) {
            System.out.println((char) in.readByte());
        }
    }
}

18.6.4 基本的文件输出

package com.io;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringReader;

/**
 * @author [email protected]
 * @since 21:35 2018/7/18
 */
public class BasicFileOutput {
    static String file = "BasicFileOutput.out";

    public static void main(String[] args) throws IOException {
        BufferedReader in = new BufferedReader(new StringReader(BufferedInputFile.read("")));
        PrintWriter out = new PrintWriter(file);
        int lineCount = 1;
        String s;
        while ((s = in.readLine()) != null) {
            out.println(lineCount++ + ":" + s);
        }
        out.close();
        System.out.println(BufferedInputFile.read(file));
    }
}

猜你喜欢

转载自blog.csdn.net/Youyou_0826/article/details/81105885