IO流

本文深入讲解Java中的IO流概念及应用,包括字节流、字符流及其常用的缓冲流,并介绍了如何处理异常,以及如何利用缓冲流提高数据读写的效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

IO流

 

IO流用来处理设备之间的数据传输

Java对数据的操作是通过流的方式

Java用于操作流的类都在IO包中

 

IO流常用父类

 

字节流的抽象父类:

 

InputStream

outputStream

 

字符流的抽象父类

 

Reader

Writer

 

IO程序书写

 

使用前,导入IO包中的类

使用时.进行IO异常处理

使用后,释放资源

 

流按流向分为:输入流FileInputStream,输出流FileOutStream

 

流按操作类型分为:

字节流: 字节流可以操作任何数据,因为任何数据都是以字节的形式存储

字符流; 字符流只能操作纯字符数据,比较方便

 

 

字符流

 

FileInputStream fis = new FileInputStream("文件名"); //创建IO流对象

int x = fis.read(); //硬盘上读取一个字节 --> 若读完所有字节,则返回-1

sout(x); //输出文件字节

files.close(); //关流释放资源

 

构造方法

File InpuStream(String name)

File InpuStream(File file)

 

方法

read() --> 读取一个字节数据,返回这个字节,结束 返回-1

read(byte[] b) --> 读取一个字节数组 ,返回该数组.结束返回-1

将数据读取到字节数组里面,字节数组长度是几,一次就读取几个

close()

 

--> 为什么返回值用int接受?

 

因为,字节输入流可以操作任意类型的文件,若每次都返回byte,有可能在读到中间的时候遇到11111111,即 -1 -->所以int接受,在前面补上24个0满足4字节,那么结束标记的-1就为int型

 

FileOutputStream fos = new FileOutputStream("文件名/或者File类型的文件"); //创建字节输出流对象

fos.write(97); //虽然写出的是int数,但是到文件上的是一个字节,自动取出前三个8位

 

FileOutputStream ==> 在创建对象的时候如果没有这个文件,会帮创建出来

--> 如果有,就会将文件清空,重写写入新的内容

--> 如果想续写,就在第二个参数中添加true

--> 将这个文件绑定到这个输出流中,以后通过这个输出流操作的就是这个文件了

 

--> 写入到文件中的是数字对应的ASC码值

在java中,一个字符占2个字节,但若该字符在ascii码中,是占一个字符的

中文在操作系统中占多个字节 --> GBK中2个字节 UTF-8中占3个字节

 

构造方法

FileOutpuStream(String name)

FileOutpuStream(File file)

FileOutpuStream(File file,boolean append) --> 不改变内容,续写

FileOutpuStream(String str , boolean append) --> ...

 

方法

write(int b)

write(byte[] b)

--> getBytes()使用平台默认的编码方式转成字节数组

--> String(byte[] bytes) 字节数组转字符串

--> String(byte[] int offset , int length) 将字节数组的一部分转成String

byte[] bArr = "戳文能啊开开阿帆鄂城啊".getBytes();

fos.write(bArr);

write(byte[] , int off , int end)

close()

 

核心代码:(多次)

 

FileInputStream fis = new FileInputStream("双源.jpg");==>创建输入流对象,关联双源.jpg

FileOutputStream fos = new FileOutputStream("copy.jpg");==>创建输出流,copy.jpg

int b ;(效率太低)

while((b = fis,read()) ! = -1 ){ ==>不断读取每个字节

fos.write(); ==> 将每个字节取出

}

 

第二种方法(不推荐使用,因为有可能导致内存溢出)

byte[] arr = new byte[fis.available()];

fis.read(arr); //将文件的字节读取到内存中

fos.write(arr); //将内存的字节撰写到文件上

 

第三种copy(小数组)

byte[] arr = new byte[2];

while(int len = fis.read(arr) != -1){ //将文件上的字节读取到字节数组中

fos.write(arr,0,len)

}

fis.close();//==>关闭资源

fos.close();

 

定义小数组的标准格式

 

byte[] arr = new byte[1024*8];

while(int len = fis.read(arr) != -1){

fos.write(arr,0,len)

}

 

-->如果忘记加arr,返回的就不是读取字节个数,而是返回的码表值

 

缓冲流

 

四种

字节缓冲流: BufferedInputStream / BufferedOutputStream

字符缓冲流: BufferedReader / BufferedWriter

--> 在创建流对象时,会创建一个车内置的默认大小的缓冲区数组,通过缓冲区的读写,减少系统IO次数

--> 缓冲流其实本身并不具备读写功能,它的作用其实是为了其他流加速

 

构造方法

BufferedInputStream(InputStream in) --> 创建一个新的缓冲输入流

BufferedOutputStream(OutputStream out) --> 创建一个新的缓冲输出流

 

BufferedReader br = new BufferedReader(new FileReader(...))

BufferedWriter bw = new BufferedWriter(new FileWriter(...))

 

缓冲区特有方法

public String readLine() --> 读一行文字

pubilc void newLine() --> 写一行分隔符,由系统属性定义符号

 

 

FileInputStream fis = new FileInputStream();

--> 创建输入流对象,关联文件

FileOutputStream fos = new FileOutputStream();

--> 创建输出流对象,关联文件

BufferedInputStream bis = new BufferedInputStream(fis);

--> 创建缓冲区对象,对输入流进行包装让其变得更加强大

BufferedOutputStream bos = new BufferedOutputStream(fos);

 

int b ;

while(b = bis.read() != -1){

bos.write(b);

}

 

bis.close();

bos.close();

 

缓冲区思想

 

小数组合buffer的对比

 

 

 

读写中文

 

代码块

--> 一下方法有可能出现问题,有可能读到半个中文字节的情况

FileInputStream fis = new FileInputStream();

--> 创建输入流对象,关联文件

byte[] arr = new byte[3];

int len;

while((len = fis.read()) ! = -1){

sout(new String(arr,0,len));

}

fis.close;

 

异常处理

 

标准异常处理1.7版本

 

代码块

 

FileInputStream fis = null ;

--> 创建输入流对象,关联文件

FileOutputStream fos = null;

--> 创建输出流对象,关联文件

try{

fis = new FileInputStream();

fos = new FileOutputStream();

int b;

while((b = fis.read()) != -1){

fos.write();

}

}finally{

try{

if(fis != null){

fis.close();

}finally{

if(fos != null){

fos.close();

}

}

标准异常处理1.6版本

 

 

JDK7的处理

 

DK7优化后的try-with-resource 语句,该语句确保了每个资源在语句结束时关闭。所谓的资源(resource)是指在程序完成后,必须关闭的对象。

try (创建流对象语句,如果多个,使用';'隔开) {

// 读写数据

} catch (IOException e) {

e.printStackTrace();

}

// 创建流对象

try ( FileWriter fw = new FileWriter("fw.txt"); ) { --> ()内必须放的是AutoCloseable的实现类

// 写出数据

fw.write("黑马程序员"); //黑马程序员

} catch (IOException e) {

e.printStackTrace();

}

--> 不管程序结果如何,都会调用在try中创建的close方法

--> 这个close方法,不需要我们手动去调用,系统会帮我们去调用

 

JDK9的改进(了解内容)

try-with-resource 的改进,对于引入对象的方式,支持的更加简洁。被引入的对象,同样可以自动关闭,无需手动close

 

// 创建流对象

final FileReader fr = new FileReader("in.txt");

FileWriter fw = new FileWriter("out.txt");

// 引入到try中

try (fr; fw) {

// 定义变量

int b;

// 读取数据

while ((b = fr.read())!=-1) {

// 写出数据

fw.write(b);

}

} catch (IOException e) {

e.printStackTrace();

}

 

字符流

Reader

--> 字符输入流的顶层父类,抽象类 常用子类FileReader

--> 以字符为单位进行读取

 

构造方法

FileReader(File file)

FileReader(String fileName)

 

方法

int read()

int read(char[] cbuf) --> 返回读取到的有效个数

 

Writer

--> 字符输出流的顶层父类,抽象类 常用子类FileWriter

--> 以字节为单位进行读取

 

构造方法

FileWriter(File file)

FileWriter(String FileName)

 

方法

void write(String str) 写入字符串

void write(char[] cbuf , int off , int len)

void write(int c)

void write(String str , int off , int len)

--> write方法将写入的数据放入到了内存缓冲区,必须flush一下

flush() 刷新(字节流写入的时候必须注意)

 

flush和close方法的区别

 

close --> 具备刷新的功能,在关闭流之前,就会先刷新一次缓冲区,将缓冲区的字节全都刷新到文件上再关闭,刷新完后不能继续写

flush --> 具备刷新功能 , 刷完后可以继续写,需要实时刷新的

 

读取字符

FileReader fr = new FileReader(" ");

int c;

while((c = fr.read()) != -1){// ==> 通过项目默认的码表一次读取一个字符

sout((char) c );

}

 

写入字符

FileWriter fw = new FileWriter(" ");

fw.write(" ... ");

fw.write(97);

fw.close();

 

字符流的拷贝

FileReader fr = new FileReader(" ");

FileWriter fw = new FileWriter(" ");

 

int c;

while(( c = fr.read()) != -1){

fw.write();

}

fr.close();

fw.close();// ==> write内容有一个2k的缓冲区,如果不关流,就会将内容写到缓冲区里,关流会将内容写出,并关闭(刷洗缓冲区)

 

字符流的使用场景

 

字符流可以拷贝文件,但不推荐使用

 

--> read时将字节转换为字符,.write时将字符转换为字节

--> 程序需要读取一段文本,或者写出一段文本的时候可以使用字符流

--> 读取的时候是按照字符的大小读取的,不会出现半个中文

--> 写出的时候可以直接将字符串写出,不用转换为字节数组

 

字符流是否可以拷贝非纯文本的文件

 

--> 不可以拷贝非纯文本的文件

--> 因为在读的时候会将字节转换为字符,可能找不到对应的字符,就会用?代替,写出的时候会将字符转换成字节写出去

--> 如果是?直接写出,这样,文件就乱了

 

自定义字符数组的拷贝

FileReader fr = new FileReader(" ...");

FileWriter fw = new FileWriter(" ");

char[] arr = new char[1024];

int len;

while((len = fr.read(arr) != -1)){

fw.writer(arr,0,len);

}

fr.close();

fw.close()

 

带缓冲的字符流

BufferedReader br = new BufferedReader(new FileReader());

BufferedWriter br = new BufferedWriter(new FileReader());

int c;

while(c = br.read(arr) != -1)){

bw.writer(arr,0,len);

}

br.close();

bw.close();

 

(BufferReader)readLine() ==> 读取文本行,通过换行/回车认为可直接终止

(BufferWriter)newLine(); ==> 写入一个行分隔符

 

newLine() --> 是跨平台的方法

\r\n --> 仅windows系统

 

文本反转

 

1.创建输入输出流

2.创建集合对象

3.将读到的数据存储在集合中

4.反向遍历集合写到文件上

5.关流

 

注意:

流对象尽量符合晚开早关

 

LineNumberReader

LineNumberReader linr = new LineNumberReader(" ");

String line ;

while((line = lnr.readLine()) != null){

sout(lnr.getLineNumber() + line);

}

lnr.close();

 

设计模式

 

步骤

1.获取被装饰类的引用

2.在构造方法中传入被装饰类的对象

3.对原有功能进行升级

好处

降低程序的耦合性,被装饰的类的变化,与装饰类无关

 

转换流图解

 

 

 

 

图片加密

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值