IO流与File类讲解

1. File类

1. 注意点

  • new一个File对象,实际上是将已经存在的文件创建成一个Java对象。
  • new一个File对象,即使传入的文件或目录不存在,代码也不会出错,因为构造一个File对象并不会导致任何磁盘操作。只有当我们调用File对象的某些方法的时候,才真正进行磁盘操作。如上述代码所示。
  • 注意Windows平台使用 \ 作为路径分隔符,在Java字符串中需要使用\表示一个\。Linux平台使用 / 作为路径分隔符
public class FileTest {
    public static void main(String[] args) {
        File file = new File("C:\\test.txt");		//文件系统中不存在
        System.out.println(file);
        System.out.println(file.isFile());
    }
}
//运行结果:
C:\test.txt
false


public class FileTest {
    public static void main(String[] args) {
        File file = new File("C:\\HaxLogs.txt");		//文件系统中存在
        System.out.println(file);
        System.out.println(file.isFile());
    }
}
//运行结果:
C:\HaxLogs.txt
true

2. File类方法
isFile():判断文件对象是否存在
isDirectory():判断目录对象是否存在
getPath():返回构造器传入的路径
getCanonicalPath():返回规范路径
boolean canRead():是否可读
boolean canWrite():是否可写
boolean canExecute():是否可执行
long length():文件字节大小
createNewFile():创建文件
delete():删除文件
createTempFile():创建临时文件
deleteOnExit():在JVM退出时删除该文件

public class FileTest {
    public static void main(String[] args) throws IOException {
        File file = new File("C:\\java\\test.txt");
        System.out.println(file.isFile());
        System.out.println(file.isDirectory());
        System.out.println(file.getPath());
        System.out.println(file.getCanonicalFile());
        System.out.println(file.canRead());
        System.out.println(file.canWrite());
        System.out.println(file.canExecute());
        System.out.println(file.length());
        if(file.createNewFile() == true){
            System.out.println("成功创建文件");
        }
        System.out.println(file.isFile());

        if(file.delete() == true){
            System.out.println("成功删除文件");
        }

		File file1 = new File("C:\\java");
        File[] files = file1.listFiles();
        for(File f:files){
            System.out.println(f);
        }
    }
}

2. InputStream

  • InputStream并不是一个接口,而是一个抽象类,是所有输入流的超类
  • InputStream抽象类定义了一个最重要的方法就是public abstract int read() throws IOException。这个方法会读取输入流的下一个字节并返回字节表示的int值。如果读到了末尾就返回-1表示不能继续读取了。
  • 打开IO流,使用完一定要关闭

FileInputStream是InputStream的一个子类。FileInputStream就是从文件流中读取数据。

public class FileTest {
    public static void main(String[] args) throws IOException {
        File file = new File("C:\\java\\Hello.java");
        InputStream in = new FileInputStream(file);
        for(;;){
            int n = in.read();			//一个个字节读取
            if(n== -1) break;			//末尾读出-1
            System.out.println((char)n);	//返回都是整数,所以要强制类型转换
        }
        in.close();
    }
}

文件内容:
在这里插入图片描述
运行结果:
在这里插入图片描述
缓冲

  • 利用缓冲区一次读取多个字节
public class FileTest {
    public static void main(String[] args) throws IOException {
        File file = new File("C:\\java\\Hello.java");
        InputStream input = new FileInputStream(file);
        boolean n;
        byte[] buffer = new byte[10];
        while((n = input.read(buffer)!=-1)){
            System.out.println(n);
            for(int i = 0;i<10;i++){
                System.out.println((char) buffer[i]);
            }
        }
        input.close();
    }
}

阻塞

  • 在调用InputStream的read()方法读取数据时,我们说read()方法是阻塞Blocking1的。它的意思就是:必须等read()方法返回后才能继续执行后面的代码。同时读取IO流相比执行普通代码,速度会慢下来很多,因此无法确定read()方法调用到底要花费多长时间。

实现类ByteArrayInputStream

public class FileTest {
    public static void main(String[] args) throws IOException {
        byte[] data = {72,101,108,108,111,33};
        InputStream input = new ByteArrayInputStream(data);
        int n;
        while((n = input.read())!=-1){
            System.out.print((char)n);
        }
    }
}

运行结果:
在这里插入图片描述

3. OutputStream

  • 和InputStream相反,Outputstream是Java标准库提供的最基本的输出流
  • 和InputStream类似,Outputstream也是抽象类,它是所有输出流的超类
  • public abstract void write(int b) throws IOException。这个方法会写入一个字节到输出流。虽然传入的是int参数,但只会写入一个字节,即只写入int最低8位表示字节的部分。
  • 和InputStream类似,Outputstream也提供了close()方法关闭输出流,以便释放系统资源。

FileOutputStream是OutputStream的一个子类。FileOutputStream就是从文件流中写入数据。

public class FileTest {
    public static void main(String[] args) throws IOException {
        File file = new File("C:\\java\\test.txt");
        OutputStream output = new FileOutputStream(file);
        output.write(72);
        output.write(101);
        output.write(108);
        output.write(108);
        output.write(111);
        output.close();
    }
}

运行结果:文件输入了字符
在这里插入图片描述
缓冲

public class FileTest {
    public static void main(String[] args) throws IOException {
        File file = new File("C:\\java\\test.txt");
        OutputStream output = new FileOutputStream(file);
        output.write("Hello".getBytes(UTF_8));
        output.close();
    }
}

阻塞

  • 和InputStream一样,Outputstream的write()方法也是阻塞的。

实现类ByteArrayOutputStream

public class FileTest {
    public static void main(String[] args) throws IOException {
        byte[] data;
        ByteArrayOutputStream output = new ByteArrayOutputStream();
        output.write("Hello ".getBytes(UTF_8));
        output.write("World!".getBytes(UTF_8));
        data = output.toByteArray();
        System.out.println(new String(data,"UTF-8"));
    }
}

4.总结InputStream与Outputstream

在这里插入图片描述

在这里插入图片描述

5. Filter模式

1. 数据源

  • FileInputStream:从文件读取数据,是最终数据源
  • ServletInputStream:从HTTP请求读取数据,是最终数据源
  • Socket.getInputStream():从TCP连接读取数据,是最终数据源

2. 对数据源添加额外功能

  • 对FileInputStream添加缓冲功能
BufferedFileInputStream extends FileInputStream
  • 对FileInputStream添加计算签名功能
DigestFileInputStream extends FileInputStream
  • 对FileInputStream添加加密解密功能
CipherFileInputStream extends FileInputStream

思考:还有其他的功能,以及功能上的结合,会产生更多的类。仅仅是一个FileInputstream就是需要很多类。那么所有数据源都要有相应的功能类,那么InputStream很快就会产生子类爆炸的情况。

3. 解决
为了解决依赖继承会导致子类数量失控的问题,JDK将InputStream分为两大类

  • 一类是直接提供数据的基础InputStream,例如:FileInputstream、ByteArrayInputStream、ServletInputStream
  • 一类是提供额外附加功能的InputStream,例如:BufferedInputStream、DigestInputStream、CipherInputStream

4. 实践使用

  • 确定数据源
InputStream file = new FileInputStream(C:\\test.txt);
  • 提供缓冲功能
InputStream buffered = new BufferedInputStream(file);
  • 提供解压缩功能
InputStream gzip = new GZIPInputStream(buffered);

得到gzip之后,按照InputStream类来使用read方法就可以了。
无论我们包装多少次,得到的对象始终是InputStream,我们直接用InputStream来引用它,就可以正常读取。这种通过一个基础组件再叠加各种附加功能组件的模式,称之为Filter模式。可以让我们通过少量的类来实现各种功能的组合。
在这里插入图片描述

6. Reader与Writer

这里主要说明Reader与InputStream之间的联系与区别,至于Writer与Outputstream之间的爱恨情仇就不赘述了。
1. 了解字节流与字符流

  • 字节流:数据以byte数据类型作为数据单位,因为byte是一个字节,故字节流是一个字节为一个数据单位
  • 字符流:数据以char数据类型作为数据单位,因为char是两个字节,故字符流是两个字节为一个数据单位

2. Reader与InputStream

  • Reader是字符流,以char数据类型为数据单位
  • InputStream是字节流,以Byte数据类型为数据单位

3. Reader与InputStream的read方法

  • Reader.read():读取一个char,返回16位int
  • InputStream.read():读取一个Byte,返回8位int
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值