Java中IO流解析及代码实例详解

网友投稿 245 2022-10-04


Java中IO流解析及代码实例详解

目录1、IO流1.流和流的分类什么是IO流?IO流的分类?java.io包下需要掌握的流有16个:2.如何使用流1、输入流(读文件):FileInputStream2、输出流(写文件):FileOutputStream3.文件的拷贝总结

1、IO流

1.流和流的分类

什么是IO流?

I:Input (输入)

O: Ouput(输出)

IO流的分类?

有多种分类方式:

一种方式是按照流的方向进行分类:

以内存作为参照物

往内存中去,叫做输入(Input)。或者叫做读(Read) .

从内存中出来,叫做输出(output)。或者叫做写(write) .

另一种方式是按照读取薮据方式不同进行分类:

有的流是按照字节的方式读取数据,一次读取1个字节byte,等同于一次读取8个二进制。

这种流是万能的,什么类型的文件都可以读取。包括:文本文件,图片,声音文件,视频……

有的流是按照字符的方式读取数据的,一次读取一个字符,这种流是为了方便读取普通文本文件而存在的,这种流不能读取:图片、声音、视频等文件。只能读取纯文本文件,连word文件都无法读取

总结:流的分类

输入流、输出流、字节流、字符流

Java IO流的四大家族

java.io.InputStream

字节输入流

java.io.OutputStream

字节输出流

http://

java.io.Reader

字符输入流

java.io.Writer

字符输出流

注意:

四个都是抽象类。

所有流都是实现了java.io.Closeable接口,都是可关闭的

流是一个管道,是内存和硬盘之间的通道。用完后一定要关闭,不然会占用很多资源。

所有的输出流都实现了java.io.Flushable接口,都是可刷新的

最终输出后,一定要记得调用flush()方法。目的是将管道中剩余未输出的数据强行输出完(清空管道)

如果没有flash(),可能会导致丢失数据

在java中只要”类名”以strean结尾的都是字节流。以"Reader/writer"结尾的都是字符流

java.io包下需要掌握的流有16个:

文件专属:

java . io.FileInputstream

java.io.FileOutputstream

java.io.FileReader

java.io.Filewriter

转换流:(将字节流转换成字符流)

java . io . InputstreamReader

java . io. outputstreamWriter

缓冲流专属:

java. io. BufferedReader

java.io.BufferedWriter

java.io. BufferedInputstream

java . io.Bufferedoutputstrean

数据流专属:

java . io . DataInputstream

java .io. Dataoutputstrean

标准输出流:

java . io . Printwriter

java . io . Printstream

对象专属流:

java.io.ObjectInputstream

java.io.ObjectOutputstream

一下子看到这么多流。不用怕,只需要掌握一组的使用方法就可以了,使用其他的都是一样,一通百通。

下面以万能的字节流(FileInputStream、FileOutputStream)来举例说明。

2.如何使用流

1、输入流(读文件):FileInputStream

方法一

使用FileInputStream的read()

步骤:

1、 创建流对象

​ new FileInputStream(参数)

​ 参数可以是一个File类、String字符串表示的文件路径

2、使用流的方法对文件进行读

输入流调用read()方法,每次从流中读取一个数据字节。返回值是读到的字节的ASCII值

读取一个后,他会指向下一个字符,如果到达末尾。返回-1,可以用while()来实现。

3、关闭流

调用close()方法

实例:

package com.io.stream;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.IOException;

public class TestFileInputStream {

//定义一个流对象

private static FileInputStream fis;

public static void main(String[] args) {

try {

//1、 创建流对象.参数可以是一个File类、String字符串表示的文件路径

fis = new FileInputStream("E:\\aaa.txt");//在e盘下有一个aaa.txt的文件夹,内容为(abcdefg)

//2、使用流的方法对文件进行读

while (true) {

int read = fis.read();//注意这里返回的是int类型,代表是字符的ASCII值

if (read==-1) {//读到最后会返回-1,退出条件

break;

}

System.out.println(read);

}

} catch (FileNotFoundException e) {//异常细粒化,不同异常可以选择不同的处理方式

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

} finally {

try {

//3、关闭流

fis.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

/*输出

97

98

99

100

101

102

103

*/

int read()

该方法因为每次都是只读取一个字节,这样内存和硬盘交互太频繁 ,开销大且效率不高。一般不使用,但是要了解,这是基础。

方法二

一般使用这种方法

使用read(byte[] b)

一次读取最多 b.length 个字节,减少内存和硬盘交互,提高执行效率

该方法返回的是读到的字节的数量

使用步骤:和前面只有第二步有些差别

byte[] b= new byte[3];

int readNum = fis.read(b);

解析

新建一个byte[]数组b,代表我们一次需要读多少个字符。读完这么多字符后,下次一读是从当前读到的位置开始,和上面一样

将byte数组b传入read()方法中,返回一个我们byte数组的大小,此时readNum值为3

那么我们读出来的数据在哪里呢。自然是存放在byte数组里。我们打印b数组看,发现b数组里存放的读到的ascii值

细节:

因为数组的长度是我们设定的。如果文件读到最后,不一定刚好符合我们设定的长度,最后一组的长度只有小于或等于数组的长度。如果小于它会返回剩余的字符的数量,读不到返回-1,我们可以利用这个作为循环退出的条件。

另外一个,因为他的长度小于b数组,那么它的值也是无法填满b数组的,此时,它只更新b数组中前面的n个读到的值,b数组后面的是上一个读取时读取到的值。

实例:

仍然读取aaa.txt文件,内容为(abcdefg)

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.IOException;

import java.util.Arrays;

public class TestFileInputStream2 {

private static FileInputStream fis;

public static void main(String[] args) {

try {

fis = new FileInputStream("IO流\\aaa.txt");

//准备一个byte数组

byte[] b= new byte[3];

int readNum = 0;

while (true) {

//先进行读操作。

readNum=fis.read(b);

//判断

if (readNum == -1) {

break;

}

//将字符数组转为String,后面两个参数为起始位置,和长度

String str = new String(b, 0, readNum);

System.out.println(str);

}

/*输出

abc

def

g

*/

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

} finally {

try {

//关闭流

fis.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

其他常用的方法

int available()

返回流中还有多少个字符没有读。(相当于获得文件读到的位置到末尾字符的个数,如果没开始读,返回文件中总字符的数量)

使用这个可以对一些比较小的(字符长度)文件一次读完,如果不超过byte数组的范围的话

public class TestFileInputStream3 {

public static void main(String[] args) throws IOException {

FileInputStream fis = new FileInputStream("IO流\\aaa.txt");

byte[] bytes = new byte[fis.available()];//创建一个和文件字符数量一样大的byte数组,文件不能太大。

fis.read(bytes);

System.out.println(new String(bytes));//b转为字符串,输出abcdefg

}

}

skip(long n)

顾名思义:从输入流中跳过并丢弃 n 个字节的数据。

2、输出流(写文件):FileOutputStream

和输入的流程差不多,过程也基本相同

write(byte[] b)

注意:

package com.io.stream.output;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

/**

* @Author cyh

* @Date 2021/8/7 17:21

*/

public class Test1 {

private static FileOutputStream fos;

public static void main(String[] args) {

try {

//新建一个输出流,参数是输出的路径,最后的为文件名。

fos = new FileOutputStream("IO流\\bbb.txt");

//新建一个byte数组,里面对应的是abcd的ascii值

byte[] bytes = {97, 98, 99, 100,101,127}; //注意byte的范围是-128~127

//输出流调用write方法写入byte数组,以文件形式保存到上面的路径

fos.write(bytes);

//写完之后,一定要刷新

fos.flush();

} catch (IOException e) {

e.printStackTrace();

} finally {

try {

fos.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

追加写文件

想要追加写文件,则需要在新建流的的时候,加一个参数true。

表示将字节写入文件末尾处,而不是写入文件开始处

//新建一个输出流,参数是输出的路径,最后的为文件名。增加true表示开启追加写

fos = new FileOutputStream("IO流\\bbb.txt",true);

注意:和上面一样,不一样的点只是追加写。

write(byte[] b, int off, int len)

将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此文件输出流.

意思就是,写入的内容为off~len。如果off是0,len是数组长度,那就全部写入;如果off是数组长度-1,len是数组长度,那就只写入了一个字符

3.文件的拷贝

使用FileInputStream+FileOutputStream即可完成文件的拷贝

拷贝的过程应该是一边读、一边写

使用上面的字节流拷贝文件的时候,文件类型随意,是万能的。什么文件都可以拷贝

实例

package com.io.stream.copy;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

/**

* @Author cyh

* @Date 2021/8/7 17:53

*/

public class TestCopy {

private static FileInputStream fis;

private static FileOutputStream fos;

public static void main(String[] args) {

try {

//创建一个输入流

fis = new FileInputStream("D:\\edgeDownload\\VSCodeUserSetup-x64-1.55.0.exe");

//创建一个输出流

fos = new FileOutputStream("C:\\Users\\PC\\Desktop\\copy\\b\\VSCodeUserSetup-x64-1.55.0.exe");

//核心,一边读、一边写

byte[] bytes = new byte[1024*1024];//1MB,一次最多拷贝1MB

int readNum=0;

while((readNum=fis.read(bytes))!=-1){

fos.write(bytes,0,readNum);//将bytes全部写入

}

//刷新

fos.flush();

} catch (FileNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

} finally {

//资源要分开释放,不然一个出错会导致另一个无法释放

try {

fis.close();

} catch (IOException e) {

e.printStackTrace();

}

try {

fos.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

总结

本篇文章就到这里了,希望能给你带来帮助,也希望您能够多多关注我们的更多内容!


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:带你掌握二进制SCA检测工具的短板及应对措施
下一篇:什么是 Ping (ICMP) 洪水攻击?(什么是滑档)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~