IO流
什么是IO
I input 输入(读取) 硬盘向内存输入数据
O output输出(写入)内存向硬盘写入数据
流:数据 (字节/字符)1个字符=2个字节,1个字节=8个二进制位
IO分类
根据数据的流向分为:输入流和输出流
-
输入流:就是把数据从其他设备上读取到内存当中.
-
输出流,就是把数据从内存当中写入到其他设备上的流.
根据数据的类型分为:字节流和字符流
-
字节流:以字节为单位,读写数据的流
-
字符流:以字符为单位,读写数据的流
IO流的顶级父类
输入流 | 输出流 | |
---|---|---|
字节流 | 字节输入流InputStream | 字节输出流OutputStream |
字符流 | 字符输入流Reader | 字符输出流Writer |
字节流
一切皆为字节
一切文件数据(文本文档.图片,视频等)在存储时,都是以二进制数字的形式保存的,都是一个一个的字节,那么数据在进行传输的时候也是如此.所以字节流可以数传任意文件数据.在操作流程的时候,我们要明确,无论使用了什么样的流对象,底层传输的始终为二进制数据.
字节输出流[OutputStream]
java.io.OutputStream此抽象类是表示输出字节流的所有类的超类,将指定的字节信息写入到目的地,它定义了字节输出流的基本共性的api方法:
-
public void close():关闭此输出流并释放与此流相关的其他任何系统资源.
-
public void flush():刷新此输出流并强制任何缓冲的输出字节信息被写入.
-
public void writer(byt[] b):将b.length字节从指定的自节数组写入到此输出流中.
-
public void write(byte b,int off,int len):将指定的字节数组写入len个字节,从偏移量off开始输出到此输出流中
-
public abstract void write(int b):将指定的字节输出到此输出流中.
FileOutputStream类
java.io.FileOutputStream类是文件字节输出流,用于将数据写入到文件中.
构造方法
-
public FilePutStream(File file):创建一个向指定file对象则表示的文件中写入数据的文件输出流.
-
public FilePutStream(String name):创建文件输出流以指定的文件名称写入文件中.
当你创建一个流对象时,必须西安传递一个文件路径,该路径下,如果没有这个文件,会创建该文件,如果有这个文件.会清空这个文件当中的数据,
FilePutOutStream作用:把内存当中的数据写入到硬盘文件中. 构造方法
- public FilePutStream(File file):创建一个向指定file对象则表示的文件中写入数据的文件输出流.
- public FilePutStream(String name):创建文件输出流以指定的文件名称写入文件中.
参数:
File file:目的地是一个文件
String name:目的地是一个文件的路径
构造方法的作用:
1.创建一个FileOutputStream类对象
2.会根据构造方法中传递的文件/文件路径(路径上文件不存在),创建一个空的文件.
3.会把FileOutputStream对象指向创建好的文件.
字节输出流的使用步骤:
1.创建一个FileOutPutStream类对象,构造方法中传递写入数据的目的地.
2.调用FileOutPutStream对象中的write方法.把数据写入到文件中.
3.释放资源.
备注;任何记事本文件在被打开的时候,包括储存方式都是以字节的方式,所以读取的时候采用的是本地字符集,whids系统采用的是GBK.
写入数据的原理:
java成员-->JVM(java)虚拟机-->OS(操作系统)-->OS调用操作系统中的写入数据的方法-->把数据写入到文件中.
示例代码:
//1.创建一个FileOutPutStream类对象,构造方法中传递写入数据的目的地.
FileOutputStream fos = new FileOutputStream("day28_IO\a.txt");
//2.调用FileOutPutStream对象中的write方法.把数据写入到文件中.
fos.write(97);
//3.释放资源
fos.close();
UTF-8 一个汉字占三个字节,GBK 一个汉字占两个字节
数据的追加续写
如何在保留目标文件中的数据,还能继续添加新的数据到目标文件中?
-
public FileOutPutStream(File file,boolean append): 创建文件输出流以以写入指定的File对象表示的文件中.
-
public FileOutputStream(String name,boolean append):创建文件输出流以指定的名称写入文件中.
这两个构造方法,参数都需要传入一个boolean类型的值,'true'表示追加数据 , 'false'表示清空原有数据.在这样的情况下创建输出流对象,就可以指定是否需要在文件的末尾添加.
写入换行
Windows系统里面,换行符号是'' '.把以指定是否需要追加续写换行
Linux系统里,换行符号是''/n'
mac系统里,换行符号是'/r'
Unix系统里,每行结尾只有换行,即
回车符 和换行符
-
回车符:回到一行的开头
-
换行符:下一行
系统中的换行:
-
Windows系统中,每行结尾是"回车+换行".即 .
-
Unix系统中,每行的结尾只有换行,即
-
Mac系统中,每行的结尾是'回车',即
//1.创建对象
FileOutputStream fo = new FileOutputStream("day28_IO\c.txt", true);
//实现数据换行
fo.write("
".getBytes());
//2.调用write()方法
fo.write("HelloWord".getBytes());
//3.关闭流对象
fo.close();
字节输入流
java.io.unputStream此抽象类是表示字节输入流的所有类的超类,可以读取字节信息到内存中,他定义了字节输入流的基本你的共性的api方法
-
public void close():关闭此输入流并释放与此流相关的其他的任何系统资源
-
public abstract int read():从输入流中读取数据的下一个字节.
-
public int read(byte[] b):从输入流中读取一些字节数,并将它们存储到字节数组b当中
备注:close方法,当完成流的相关操作后,需要调用此方法关闭输入流,释放系统资源.
FileInputStream类
java.io.FileInputStream类是文件输入流,从文件中读取字节.
构造方法
-
FileinputStream(Filoe file):通过打开与实际文件的连接来创建一个FileInputStream,该文件有文件系统中的File对象file命名.
-
FileInputStream(String name):通过打开与实际文件的连接来创建一个FileinputStream该文件有文件系统中的路径名name命名. 参数: 读取文件的数据源 String name: 文件的路径 File file: 文件 构造方法的作用有两个: 1.会创建一个FileInputStream类对象 2.会把FileInputStream类对象指定构造方法中要读取的文件 字节输入流的使用步骤: 1.创建一个FileInputStream类对象,构造方法中绑定要读取的数据 2.使用FileInputStream类对象中方法read(),读取文件中的数据 3.释放资源,关闭流对象
当你创建一个流对象时,必须穿入一个文件路径,该路径下,如果没有该文件,会抛出FileNotFoundException异常
使用read()方法读取文件中的字节
int len=0;//表示记录读取到的字节
while ((len=fi.read())!=-1)
System.out.print((char)len);
可以使用字符数组来读取数据:read(byte[] b):从输入流中读取多个字节,并且将其存储到缓冲区数组b中,当读取到文件的末尾时,返回一个-1.
代码演示:
int len3=0;//记录读取到的有效字节个数
byte[] bytes=new byte[1024];//2^10 1024b=1kb
while ((len3=fr.read(bytes))!=-1){
//byte[] 转换成String
//String(byte[]byte,int offset,int length)
// System.out.println(new String(bytes, 0, len3));
System.out.println(new String(bytes));
}
备注:使用数组读取,每次可以读取多个字节,减少了系统间的IO操作次数,从而提高了读取的效率,建议使用.
练习:图片复制
通过字节流实现图片复制
实现从说面的G1.ipeq图片复制到另一个目录下
原理:从已知的文件中读取字节,再把读取到的字节写入到另一个文件中.
//1.创建一个字节输入流对象FileInputStream,构造方法中绑定需要读取的图片路径
FileInputStream fi = new FileInputStream("C:\Users\Administrator\Desktop\笔记\Collection接口和Map接口概述.png");
//2.把文件读取出来
byte[] bytes = new byte[10240000];
// fi.read(bytes);
//创建字节输出流对象,FileOutPutStream,指向数据复制的目的地文件地址
FileOutputStream f = new FileOutputStream("day28_IO\c.png");
//方法1,直接放入整个byte数组
// f.write(bytes);
//方法2
int len=0;
while ((len=fi.read(bytes))!=-1){
f.write(bytes,0,len);
}
f.close();
fi.close();
}
备注:流的关闭顺序:先开后关,后开先关.
字符流
当使用字节流读取文本文件的时候,肯能会引发一点小问题,如果你遇到中文字符时,可能不会显示完整的字符.拿就是因为一个中文字符可能占用多个字节存储,所以java提供了一些字符流类,以字符为单位读写数据,专门用于处理文本文档文件.
字符输入流[Reader]读取
java.io.Reader抽象类是表示用于读取字符流的所有类的茶类,可以读取字符信息到内存当中,它定义了字符输入流的基本共性的api方法:
-
public void close():关闭此输入流并且释放与此流相关的其他系统资源
-
public int read():从输入流中读取一个字符.
-
public int read(char[] ahuf):从输入流中一次读取多个字符,并将它们存储到字符数组chuf当中.
FileReader类
java.io.FileReader类主要是用于读取字符文件的便捷类.构造方法使用时的编码字符集和默认的字节缓冲区.
备注:
1.字符编码:字节与字符的对应规则.在windows系统中的中文编码默认是GBK,idea中采用UTF-8
2.字节缓冲去:一个自节数组,用来临时存储字节数据.
构造方法
-
FileReader(File file):创建一个新的FileReader对象,给定的指定的需要读取的File对象.
-
FileReader(String filename):创建一个新的FileReader对象,指定需要读取的文件名称.
当你创建一个流对象时,必须闯入一个文件路径,类似于FileinputStream.
使用字符数组读取数据:read(char[] chuf),每次读取chuf的长度个字符到数组当中,返回读取到有效字符的个数.当他读取到末尾时,返回-1.
代码实例:
//创建对象,构造方法中绑定数据源
FileReader fi = new FileReader("day28_IO\c.txt");
//2.调用read方法
char[] chuf = new char[1024];
int len=0;//记录的是每次转换的有效的字符个数
while ((len=fi.read(chuf))!=-1){
//字符数组转换成字符串
//String static valueOf()
System.out.println(new String(chuf,0,len));
}
//3.释放资源
fi.colse();
字符输出流[Wruter]
java.io.Writer抽象类是表示用于写入(输出)字符流的所有类的超类.将指定的字符信息写入到目的地中.他同时定义了字符输出流的基本共性的API方法:
-
void write(int c):写入单个字符
-
void write(char[] chuf):写入字符数组
-
abstract void write(char[] chuf,int off,int len):写入char数组的一部分从off(起始索引值)开始,写入len个字符个数.
-
void write(String str):写入字符串.
-
void write(String str,int off,int len):写入字符串的一部分,从字符串的起始索引off开始,写入len个字符
-
void flush():刷新
-
void close():关闭此流,但是需要先刷新它.
FileWriter类
'java.io.FileWriter'类是用于写入字符到文件中,构造方法使用系统默认的字符编码和默认的字节缓冲区.
构造方法
-
FileWriter(File file):创建一个新的FileWriter,指定写入的file对象
-
FileWriter(String name):创建一个新的FileWriter,指定需要写入的文件的名称.
当你创建一个流对象时,必须传入一个文件路径,类似于FileOutputStream.
示例:
FileWriter fi = new FileWriter("day28_IO\b.txt");
//2.使用FileWriter赌侠凝重的方法Write.把数据写入到内存缓冲区中(字符转换为字节的过程)
//void write(int c)写入单个字符
fi.write(107);//J
//3.使用FileWriter对象的中的方法flush,把内存缓冲区中的数据刷新到文件中.
// fi.flush();
//4.释放资源(会先把内存缓冲区中的数据刷新到文件中)
fi.close();
关闭和刷新
因为内置缓冲区的原因,如果不关闭输出流,无法写入字符到文件中.但是关闭流对象,是无法继续写入数据到文件中.如果既想写入数据到文件中,又想继续使用流对象,那么就需要flush方法.
-
flush:刷新缓冲区的数据,流对象可以继续使用
-
close:先刷新缓冲区,然后会通知系统释放资源,关闭流对象,流对象不可以再使用
代码
//1.创建对象
FileWriter fi = new FileWriter("day28_IO\e.txt");
//2.调用write方法.
fi.write(97);//a
//3.刷新缓冲区
fi.flush();//把缓冲区的数据刷新到文件中
//刷新之后流还可以继续使用
fi.write(98);
//4.关闭流对象
fi.close();
//close方法之后,流已经关闭了,从内存中消失了,流不能再使用了,如果还用会异常
//java.io.IOException: Stream closed
fi.write(99);
写入字符数组:'write(char[] chuf)和write(char[] chuf,int off,ing len)',每次可以写入一个字符数组
用法类似FileOutputSrearm
续写和换行:操作类似于FileOutPutStream
//1.new
FileWriter fi = new FileWriter("day28_IO\g.txt", true);
//write
char[] chars =new char[50];
for (int i = 0; i < 50; i++) {
chars[i]=(char)(8140+i);
fi.write(chars[i]+"
");//
}
//flush
fi.flush();
//关闭流
fi.close();
}
备注:字符流,只能操作文本文件,不能操作图片,视频等非文本文件.
所以当我们单纯的就是想操作文本文件,就是用字符流,其他情况一律使用字节流.
IO异常的处理
JDK1.7之前的处理,
FileWriter fw=null;
try {
//可能会产生异常
fw = new FileWriter("day28_IO\g.txt", true);
//2.write
fw.write(97);
fw.flush();
} catch (IOException e) {
e.printStackTrace();
}
//刷新
finally {
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
之后可以把流的操作放入try的小扩号里面 新特性,try后面可以跟进一个小括号,并且放入小括号的流会在try catch结束后自动释放流
在JDK1.7之前使用try...catch...finally 处理流中的异常 格式: try{ //可能会发生的异常 }catch(异常类型 一场变量名){ 异常的处理逻辑}finally{ //释放系统资源 并且finally语句块一定会被执行 }
JDK7新特性
.可以使用try-with-resource语句,该语句确保了每个资源在语句结束时关闭,所谓的资源(resource)是指在程序完成后,必须要关闭的对象.
格式:
try(创建流对象语句,如果多个,请用";"隔开){
//可能会产生异常的代码
}catch(异常类型 一场变量名){
//异常处理逻辑
}
代码如下:
try ( //1.1new
FileOutputStream fi = new FileOutputStream("day28_IO\g.txt");
//1.2new
final FileInputStream fw = new FileInputStream("day28_IO\a.txt"))
{ //2. write
int len=0;
while ((len=fw.read())!=-1){
fi.write(len);
}
}catch (IOException e){
//异常的处理逻辑
e.printStackTrace();
}