栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java27:IO

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java27:IO

输入就是将数据从各种输入设备(包括文件、键盘等)中读取到内存中,输出则正好相反,是将数据写入到各种输出设备(比如文件、显示器、磁盘等)。
例如键盘就是一个标准的输入设备,而显示器就是一个标准的输出设备。文件既可以作为输入设备,又可以作为输出设备。

数据流按照数据单位的不同,分为字节流和字符流。

字节流:存储层面,逐字节地读取文件内容。
例如要从磁盘读入一个6字节大小的文件,就相当于读入了6个字节的数据。字符流:文件内容层面,逐字符地读取文件。


文章目录

字节流

InputStreamOutputStream

字节流 InputStream

InputStream是Java标准库提供的最基本的输入流。它位于java.io这个包里。

java.io包提供了所有同步IO的功能。

InputStream并不是一个接口,而是一个抽象类,它是所有输入流的超类。
其中定义的一个最重要的抽象方法就是read():
该方法会读取输入流的下一个字节,并返回字节表示的int值(0~255)。如果已读到末尾,返回-1表示不能继续读取了。

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

InputStream f = new FileInputStream("/Users/shaoyihao/Desktop/test.txt");
int n;
while ((n = f.read()) != -1) 
    System.out.println(n);
f.close();

应用程序在运行的过程中,如果打开了一个文件进行读写,完成后要及时地关闭,以便让操作系统把资源释放掉,否则,应用程序占用的资源会越来越多,不但白白占用内存,还会影响其他应用程序的运行。

在读取或写入IO流的过程中,可能会发生错误,例如:文件不存在导致无法读取,没有写权限导致写入失败…等等,这些底层错误由Java虚拟机自动封装成IOException异常并抛出。因此,所有与IO操作相关的代码都必须正确处理IOException。

上面的代码中,若读取过程中发生了IO错误,InputStream就没法正确地关闭,资源也就没法及时释放。

因此,我们需要用try ... finally来保证InputStream在无论是否发生IO错误的时候都能够正确地关闭,因此安全的写法为:

void f() throws IOException {
    InputStream f = null;
    try {
        f = new FileInputStream("/Users/shaoyihao/Desktop/test.txt");
        int n;
        while ((n = f.read()) != -1)
            System.out.println(n);
    } finally {
        if (f != null)
            f.close();
    }
}

这种写法有些繁琐,更简洁的写法为Java 7引入的新的try(resource)的语法,只需要编写try语句,让编译器自动为我们关闭资源。

void f() throws IOException {
    try (InputStream f = new FileInputStream("/Users/shaoyihao/Desktop/test.txt")) {
        int n;
        while ((n = f.read()) != -1)
            System.out.println(n);
    } 
}

实际上,编译器并不会特别地为InputStream加上自动关闭。编译器只看try(resource = …)中的对象是否实现了java.lang.AutoCloseable接口,如果实现了,就自动加上finally语句并调用close()方法。
InputStream和OutputStream都实现了这个接口,因此,都可以用在try(resource)中。

InputStream中还定义了available()函数,返回下一次对此输入流调用的方法可以不受阻塞地从此输入流读取的字节数,即文件指针当前位置到文件末尾的 字节数。

InputStream f = new FileInputStream("/Users/shaoyihao/Desktop/test.txt");
int size = f.available(); //文件的字节数
System.out.println(size);

for (int i = 0; i < size; i ++) {
    System.out.println((char)f.read() + " "); //以字符形式输出一个字节的内容
}
f.close();

实际上,InputStream存在着缓冲区。例如,从FileInputStream读取一个字节时,操作系统往往会一次性读取若干字节到缓冲区,并维护一个指针指向未读的缓冲区。然后,每次我们调用int read()读取下一个字节时,可以直接返回缓冲区的下一个字节,避免每次读一个字节都导致IO操作。当缓冲区全部读完后继续调用read(),则会触发操作系统的下一次读取并再次填满缓冲区。

OutputStream

OutputStream也是抽象类,它是所有输出流的超类,定义的一个重要方法为write(),用于写入一个字节到输出流。

注意:虽然传入的是int型,但仍只会写入一个字节,即只写入int最低8位表示字节的部分

OutputStream f = new FileOutputStream("/Users/shaoyihao/Desktop/test.txt");
f.write((int)'H');
f.write((int)'e');
f.write((int)'l');
f.write((int)'l');
f.write((int)'o');
f.close();

每次写入一个字节非常麻烦,更常见的方法是一次性写入若干字节,用OutputStream提供的重载方法write(byte[])来实现:

OutputStream f = new FileOutputStream("/Users/shaoyihao/Desktop/test.txt");
f.write("Hello".getBytes("UTF-8")); //将字符串转为byte数组
f.close();

和InputStream一样,上述代码没有考虑到在发生异常的情况下如何正确地关闭资源。写入过程也会经常发生IO错误,例如:磁盘已满,无权限写入等等。我们需要用try(resource)来保证OutputStream在无论是否发生IO错误的时候都能够正确地关闭:

void f() throws IOException{
    try (OutputStream f = new FileOutputStream("/Users/shaoyihao/Desktop/test.txt")) {
        f.write("Hello".getBytes("UTF-8"));
    } // 编译器在此自动为我们写入finally并调用close()
}

同时操作多个AutoCloseable资源时,在try(resource) { ... }语句中可以同时写出多个资源,用;隔开。

//将f1文件内容复制到f2
void f() throws IOException{
    try (InputStream f1 = new FileInputStream("/Users/shaoyihao/Desktop/test.txt");
         OutputStream f2 = new FileOutputStream("/Users/shaoyihao/Desktop/test2.txt")) {
        int n;
        while ((n = f1.read()) != -1) {
            f2.write(n);
        }
    }
}

OutputStream提供了一个flush()方法,用于将缓冲区的内容输出到目的地。

为什么要有flush()?
因为向磁盘、网络写入数据的时候,出于效率的考虑,操作系统并不是输出一个字节就立刻写入到文件或者发送到网络,而是把输出的字节先放到内存的一个缓冲区里(本质上就是一个byte[]数组),等到缓冲区写满了,再一次性写入文件或者网络。对于很多IO设备来说,一次写一个字节和一次写1000个字节,花费的时间几乎是完全一样的,所以OutputStream有个flush()方法,能强制把缓冲区内容输出。

通常情况下,我们不需要调用这个flush()方法,因为缓冲区写满了OutputStream会自动调用它,并且,在调用close()方法之前,也会自动调用flush()方法。

但是在某些情况下,我们必须手动调用flush()方法。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/770877.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号