IO流
1.IO流
1.1流介绍
在Java中流就是用来传递数据的一个工具,类似于生活中的管道,两者的区别就是生活中的管道里面可能是水、石油或者其他东西,二Java中的这个流运载的是数据.
1.1.2输入输出流
IO是输入input与输出output的缩写,根据数据的流向方向不同,我们可以分为输入流与输出流,在Java中流都在java.io包中。
**输入流:**就是将数据从各种输入设备(键盘、文件等)读到程序当中去
**输出流:**就是将程序中的数据写入到各种输出设备(显示器、磁盘等)当中
1.2数据源
数据源指定就是提供数据的媒介,常见的数据源有数据库、文件、内存等。
数据源分为:源设备和目标设备
源设备:为程序提供数据的设备,对应输入流。
目标设备:程序数据的目的地,对应输出流。
例如:
文件————>程序————>显示器
这其中文件为源设备,显示器为目标设备。
注意:源设备与目标设备都是相对与程序而言的。
1.3Java四大抽象类流
java中有四大抽象类流:InputStream/OutputStream,Reader/Write。这四大抽象流是所有IO流的父类,也就是说其他的流都是这四大的子类。
1.3.1InputStream
它代表的是字节输入流,它是所有字节输入流的父类,
使用方法:int read():读取一个字节数据,并将字节的值作为int类型返回(0~255之间的一个值),如果未读出字节就返回-1(-1代表读取结束)
void close():关闭输入流对象,释放相关系统资源。
1.3.2OutputStream
它代表的是字节输出流,它是所有字节输出流的父类。
使用方法:
void read():向目的地写入一个字节
void close():关闭输出流,释放相关系统资源。
1.3.3Reader
Reader用来读取字符流抽象类,数据单位为字符,它是所有字符输入流的父类。
常用方法:
int read():读取一个字符数据,并将字节的值作为int类型返回(0~65535之间的一个值),如果未读取到字节就返回-1(-1代表读取结束)
void close():关闭输入流对象,释放相关系统资源。
1.3.4Writer
Write用来写入字符抽象类,数据单位为字符,它是所有字符输出流的父类。
常用方法:
void write(int n):向输出流写入一个字符
void close():关闭输出流,释放相关系统资源。
1.4Java流的概念细分
按流的方向分为:
输入流:从源设备到程序
输出流:从程序到目标设备
按处理数据单元分为:
字节流:以字节为单位的流,一般以Stream结尾的都是字节流
字符流:以字符为单位的流,以Reader/Write结尾的都是字符流
按处理对象分为:
节点流:可以直接从数据源或者目的地读写数据
处理流:不直接链接数据源或目的地,是处理流的流
1.5IO流体系
1.InputStream/OutputStream :字节流的抽象类
2.Reader/Write :字符流的抽象类
3FileInputStream/FileOutputStream :节点流,以字节为单位这操作文件。
4.ByteArrayInputStream/ByteArrayOutputStream :节点流,以字节为单位操作字节数组对象
5.ObjectInputStream/ObjectOutputStream:处理流,以字节为单位直接操作对象
6.DataInputStream/DataOutputStream:处理流,以字节为单位直接操作基本数据类型与字符串类型
7.FileReader/FileWrite:节点流,以字节为单位这操作文本文件。(只能读写文本文件)
8.BuffteredReader/BuffteredWrite :处理流,对Reader/Write 进行包装,增加缓存能力,提高读写效率。
9.BuffteredInputStream/BuffteredOutputStream:处理流,对InputStream/OutputStream 进行包装,增加缓存能力,提高读写效率。
10.InputStreamReader/OutputStreamWrite:处理流,将字节流转化为字符流。
11.PrintStream:处理流,对OutputStream进行包装,方便输出字符,更加灵活。
2.简单IO流程序
public class Demo001 {public static void main(String[] args) {
FileInputStream fis=null;
try {
fis=new FileInputStream("D:\\Desktop\\txt.txt");
fis.read();
int temp=0;
while((temp= fis.read())!=-1){
System.out.println(temp);
}
} catch ( IOException e) {
throw new RuntimeException(e);
} finally {
try {
if (fis!=null) {
fis.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
3.File类
3.1File类的作用
File类是对磁盘中的文件或目录转换对象的包装类,File对象可以代表一个文件或目录,可以获文件或者目录属性的功能,实现文件或目录的创建、删除等功能。
3.1File类的常用方法
3.1.1针对文件的方法
creatNewFile():创建新文件
delete():直接从磁盘删除
exists():查询文件是否存在
getAbsoultePath():获取绝对路径
isFile():判断是否是文件
length():查看文件字节数
isHidden():测试文件是否是一个隐藏文件
字节流临时存储文件 int temp=0
字符流临时存储文件 String temp=“ ”
3.1.2针对目录的常用方法
exists():查询目录是否存在
isDirectory():测试是否为目录
mkdir():创建目录
getParenFile():获取当前目录的父级目录
list():返回一个字符串数组,包含目录中的文件和目录的路径名
listFile():返回一个File数组,表示用此抽象路径名表示的目录中的文件
3.2操作
3.2.1操作文件
public class FileDemo{
public static void main(String[] args){
//创建File对象
File file=new File(Pathname:"D:\\Desktop\\txt.txt");
System.out.println(file.creatNewFile());
}
}
3.2.2操作目录
public class FileDemo{
public static void main(String[] args){
//创建File对象
File file=new File(Pathname:"d:/a");
System.out.println(file.mkdir());
}
}
4.常用类
4.1 文件字节流
文件字节流可以处理所有类型文件
4.1.1文件输入流
public class FirstDemo{
public static void main(String[] args){
FileInputStream fis = null;
try{
//创建字节输入流对象
fis=new FileInputStream(name:"文件地址名");
int temp=0;
while((temp=fis.read())!=-1){
System.out.println(temp);
}
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(fis!=null){
fis.close()
}
}catch(Exception e)
e.printStackTrace()
}
}
}
}
}
4.1.2文件输出流
public class FirstDemo{
public static void main(String[] args){
FileInputStream fis = null;
try{
//创建字节输入流对象
fis=new FileInputStream(name:"文件地址名");
int temp=0;
while((temp=fis.read())!=-1){
System.out.println(temp);
}
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(fis!=null){
fis.close()
}
}catch(Exception e)
e.printStackTrace()
}
}
}
}
}
4.2通过缓存区提高读写效率
4.2.1方式一
创建一个长度一定的字节数组,来提高读写效率,适用于较大图片的缓冲区定义。缓冲区的长度一般是2的整数次幂,一般都会定义为1024的长度。
public class FirstDemo{
public static void main(String[] args){
FileInputStream fis = null;
FileOutputStream fos =null;
try{
//创建字节输入流对象
fis=new FileInputStream(name:"文件地址名");
//创建字节输入流对象
fos=new FileOutputStream (name:"文件地址名");
byte[] buff=new byte[1024];
int temp=0;
while((temp=fis.read(buff))!=-1){
fos.write(buff,off:0,temp);
}
//将数据从内存中写入到磁盘中
fos.flush();
}catch(Exception e){
e.printStackTrace();
}finally{
try(){
if(fis!=null){
fis.close();
}
if(fos!=null);
fos.close();
}
}catch(Exception e)
e.printStackTrace()
}
}
}
}
}
4.2.2 方式二
创建一个没有规定长度的字节数组,数组长度由输入流对象available()返回当前预估长度来定义,但这个方法不适合大文件。
public class FirstDemo{
public static void main(String[] args){
FileInputStream fis = null;
FileOutputStream fos =null;
try{
//创建字节输入流对象
fis=new FileInputStream(name:"文件地址名");
//创建字节输入流对象
fos=new FileOutputStream (name:"文件地址名");
byte[] buff=new byte[fis.available()];
fis.read(buff);
//将数据从内存中写入到磁盘中
fos.read(buff);
fos.flush();
}catch(Exception e){
e.printStackTrace();
}finally{
try(){
if(fis!=null){
fis.close();
}
if(fos!=null);
fos.close();
}
}catch(Exception e)
e.printStackTrace()
}
}
}
}
}
4.3通过字节缓冲区提高读写效率
字节缓冲流是一种处理流,缓冲流先将数据储存起来,当缓存区存满后或手动刷新后,再一次性读写到程序或释放到目的地中。BuffteredInputStream和BuffteredOutputStream这两个是缓冲字节流,通过内部缓存数组来提高操作流的效率。缓冲流默认byte数组长度为8192
public class FirstDemo{
public static void main(String[] args){
FileInputStream fis = null;
FileOutputStream fos =null;
BufferedInputStream bis=null;
BufferedOutputStream bos=null;
try{
fis=new FileInputStream(name:"文件地址名");
bis=new BufferedInputStream(fis);
fos=new FileOutputStream(name:"文件地址名");
bos=new BufferedOutputStream(fos);
int temp=0;
while((temp=bis.read())!=-1){
bos.write(temp);
}
bos.flush();
}catch(Exception e){
e.printStackTrace();
}finally{
try(){
if(bis!=null){
bis.close();
}
if(fis!=null){
fis.close();
}
if(bos!-null){
bod.close();
}
if(fos!=null);
fos.close();
}
}catch(Exception e)
e.printStackTrace()
}
}
}
}
}
4.4 文件字节流的文件拷贝
public class FirstDemo{
public static void main(String[] args){
copyFile(src:"文件地址名",des:"文件地址名");
}
public static void copyFile(String src,String des){
FileInputStream fis = null;
FileOutputStream fos =null;
BufferedInputStream bis=null;
BufferedOutputStream bos=null;
try{
fis=new FileInputStream(name:"文件地址名");
bis=new BufferedInputStream(fis);
fos=new FileOutputStream(name:"文件地址名");
bos=new BufferedOutputStream(fos);
int temp=0;
while((temp=bis.read())!=-1){
bos.write(temp);
}
bos.flush();
}catch(Exception e){
e.printStackTrace();
}finally{
try(){
if(bis!=null){
bis.close();
}
if(fis!=null){
fis.close();
}
if(bos!-null){
bod.close();
}
if(fos!=null);
fos.close();
}
}catch(Exception e)
e.printStackTrace()
}
}
}
}
}
4.5 文件字节流
当处理的文件为文本文件时,可以用文件字符流来处理
4.5.1文件字符输入流
public class FirstDemo{
public static void main(String[] args){
FileReader frd = null;
try{
//创建字节输入流对象
frd=new FileReader(fileName:"文件地址名");
int temp=0;
while((temp=frd.read())!=-1){
System.out.println(temp);
}
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(frd!=null){
frd.close()
}
}catch(Exception e)
e.printStackTrace()
}
}
}
}
}
4.5.2文件字符输出流
public class FirstDemo{
public static void main(String[] args){
FileWriter fw = null;
FileWriter fw2 =null;
try{
//创建字节输入流对象
fw=new FileWriter(fileName:"文件地址名");
fw.write(str:"文件地址名");
fw.write(str:"文件地址名");
fw.flush();
fw2=new FileWriter(fileName:"文件地址名");
fw2.write(str:"文件地址名");
fw2.write(str:"文件地址名");
fw2.flush();
}catch(Exception e){
e.printStackTrace();
}finally{
try(){
if(fw!=null){
fw.close();
}
if(fw2!=null){
fw2.close();
}
}catch(Exception e)
e.printStackTrace()
}
}
}
}
}
4.6 文件字符流对文件进行拷贝
public class FirstDemo{
public static void main(String[] args){
FileReader fr = null;
FileWriter fw2 =null;
try{
//创建字节输入流对象
fr=new FileReader(fileName:"文件地址名");
fw=new FileWriter(fileName:"文件地址名");
char[]buffer=new char[1024];
int temp=0;
while((temp=fr.reader(buffer))!=-1){
fw.write(buffer,0,temp);
}
fw.flush();
}catch(Exception e){
e.printStackTrace();
}finally{
try(){
if(fr!=null){
fr.close();
}
if(fw!=null){
fw.close();
}
}catch(Exception e)
e.printStackTrace()
}
}
}
}
}
4.7字符缓冲流
BufferedReader/BufferedWriter增加了缓存机制,提高读写文本文件的效率。
4.7.1字符缓冲输入流
BufferedReader用于字符输入缓存流,使用按行读取的方法:readLine()。
public class FirstDemo{
public static void main(String[] args){
FileReader fr = null;
BufferedReader br =null;
try{
//创建字节输入流对象
fr=new FileReader(fileName:"文件地址名");
br=new BufferedReader(fr);
String temp=" ";
while((temp=br.readerLine())!=-1){
System.out.println(temp);
}
}catch(Exception e){
e.printStackTrace();
}finally{
try(){
if(fr!=null){
fr.close();
}
if(br!=null){
br.close();
}
}catch(Exception e)
e.printStackTrace()
}
}
}
}
}
4.7.2字符输出缓冲流
BufferedWriter用于字符输出缓冲流,newLine实行换行处理。
public class FirstDemo{
public static void main(String[] args){
FileWriter fw = null;
BufferedWriter bw =null;
try{
//创建字节输入流对象
fw=new FileWriter(fileName:"文件地址名");
bw=new BufferedWriter(fw);
bw.write(str:"内容");
bw.write(str:"内容");
bw.newLine();
fw.write(str:"内容");
bw.write(str:"内容");
bw.flush();
String temp="";
while((temp=br.readerLine())!=-1){
System.out.println(temp);
}
}catch(Exception e){
e.printStackTrace();
}finally{
try(){
if(fw!=null){
fw.close();
}
if(bw!=null){
bw.close();
}
}catch(Exception e)
e.printStackTrace()
}
}
}
}
}
4.8通过字符缓冲流对文件的拷贝
public class FirstDemo{
public static void main(String[] args){
copyFile(src:"文件地址名",des:"文件地址名");
}
public static void copyFile(String src,String des){
BufferedReader br = null;
BufferedWriter bw =null;
try{
br=new BufferedReader(new FileReader(src));
bw=new BufferedWriter(new FileWriter(des));
String temp="";
while((temp=br.readLine())!=null){
bw.write(temp);
bw.readeLine();
}
bw.flush();
}catch(Exception e){
e.printStackTrace();
}finally{
try(){
if(br!=null){
br.close();
}
if(bw!=null){
bw.close();
}
}catch(Exception e)
e.printStackTrace()
}
}
}
}
}
4.9通过字符缓冲流文件内容添加行号
public class FirstDemo{
public static void main(String[] args){
BufferedReader br = null;
BufferedWriter bw =null;
try{
br=new BufferedReader(new FileReader(fileName:"文件地址名"));
bw=new BufferedWriter(new FileWriter(fileName:"文件地址名"));
String temp="";
while((temp=br.readLine())!=null){
bw.write(str:i+","+temp);
bw.readeLine();
}
bw.flush();
}catch(Exception e){
e.printStackTrace();
}finally{
try(){
if(br!=null){
br.close();
}
if(bw!=null){
bw.close();
}
}catch(Exception e)
e.printStackTrace()
}
}
}
}
}
4.10转换流
4.10.1通过转换流实现键盘输入和屏幕输出
nputStreamReader/OutputStreamReader用来将字节流转换成字符流。System.in与System.out是字节流对象,代表键盘的输入与输出道控制器。如果想按行接收用户输入和读取用户输出,那么就得要用BufferedReader的方法readerLine()和write(String.str),但用这种方法必须是Reader与Writer方法,所以这时候就需要用到转换流来处理。
public class ConvertStream{
punlic static void main(String[] args){
BufferedReader br=null;
BufferedWriter bw=null;
try{
br=new BuffererReader(new InputStreamReader(System.in));
bw=new BuffererReader(new OutputStreamWriter(System.out));
while(true){
bw.write(str:"请输入:");
String input=br.readLine();
if("exit".equals(input)){
break;
}
bw.write("你输入的是:"+input);
bw.flush();
}
}catch(Exception e){
e.printStackTRrace();
}finally{
try{
if(bw!=null){
bw.close();
}
if(br!=null){
br.close();
}
}catch(Exception e)
e.printStackTrace()
}
}
}
}
}
4.10.2通过字节流读取文本文件并添加行号
public class LineNumberDemo2{
public static void main(String[] args){
BufferedReader br = null;
BufferedWriter bw= null;
try{
br=new BuffererReader(new InputStreamReader(name:"文件地址名"));
bw=new BuffererWriter(new FilOutputStream(name:"文件地址名"));
String temp="";
int i=1;
while(temp=br.readLine){
bw.write(str.i+",+temp");
bw.newLine();
i++;
}
bw.flush();
}caatch(Exception e){
e.printStackTrance();
}finally{
try{
if(br !=null){
br.close();
}
}catch(Exception e){
e.printStackTrance();
}
}
}
}
}
4.11字符输出流
Java中提供了专门用于字符输出的流对象PrintWriter,该对象具有自动行刷新缓冲字符输出流,特点是可以按行写出字符串,并且可通过println();方法来实现自动换行。
4.12 字符数组流
ByteArrayInputStream和ByteArrayOutStream经常用在需要流和数组之间相互转换的地方
4.12.1字符数组输入流
FileInputStream是把文件当作数据源,ByteArrayInputStream则是把内存中的字节数组对象当作数据源。
public class ByteArrayInputDemo{
public static void main(String[] args){
byte[] arr="arr".getBytes();
ByteArrayInputStream bis=null;
StringBuilder sb =new StringBuilder();
try{
bis=new ByteArrayInputStream();
int temp=0;
while((temp=bis.read())!=-1){
sb.append((char)temp);
}
System.out.println(sb.toString());
}finally{
try{
if(bis!=null){
bis.close();
}
}catch(Exception e){
e.printStackTrance();
}
}
}
}
}
4.12.2字节数组输出流
ByteArrayOutStream流对象是将流中数据以字节数组形式存储。
public class ByteArrayInputDemo{
public static void main(String[] args){
byte[] arr="abcdefg".getBytes();
ByteArrayInputStream bis=null;
StringBuilder sb =new StringBuilder();
try{
bis=new ByteArrayInputStream();
int temp=0;
while((temp=bis.read())!=-1){
sb.append((char)temp);
}
System.out.println(sb.toString());
}finally{
try{
if(bis!=null){
bis.close();
}
}catch(Exception e){
e.printStackTrance();
}
}
}
}
}
4.13数据流
数据流将基本数据类型与字符串类型作为数据源,从而实现程序一机器无关的方式从底层输入输出流中Java基本数据类型与字符串类型。
DataInputStream/DataOutputStream提供了可以存取与机器无关的所有java基础类型数据(int、double、String)
public class DataOutputDemo{
public static void main(String[] args){
DataOutputStream dos=null;
try{
new DataOutputStream(new BufferedOutputStream(new FileOutputStream(name:"文件名地址")));
dos.writeChar(v:'a');
dos.writeInt(v:10);
dos.writeDouble(Math.random());
dos.writeBoolean(v:true);
dos.writeUTF(str:"内容");
dos.flush();
}catch(Exception e){
e.printStackTrance();
}finally{
try{
if(dos!=null){
dos.close();
}
}catch(Exceptiion e){
e.printStackTrance();
}
}
}
}
}
4.13.2数据输入流
public class DataInputDemo{
public static void main(String[] args){
DataInputStream dis=null;
try{
dis=new DataInputStream(new BufferedInputStream(new FileInputStream(name:"文件地址名")));
System.out.println("char:"+dis.readChar());
System.out.println("int:"+dis.readInt());
System.out.println("double:"+dis.readDouble());
System.out.println("boolean:"+dis.readBoolean());
System.out.println("String:"+dis.readUTF());
}catch(Exception e){
e.printStackTrance();
}finally{
try{
if(dis !=null){
dis.close();
}
}catch(Exception e){
e.printStackTrance();
}
}
}
}
}
4.14对象流
对象的本质是用来组织和存储数据的,对象本身也是一种数据
4.14.1对象的序列化和反序列化
数据会以二进制的形式在网络上传送,例如当我们通过http协议发送字符串信息,我们也可以在网络上直接发送Java对象。发送方需要把这个Java对象转换成字节序列,才能在网络上传送,接收方则需要把字节序列再恢复成Java对象才能正常读取。
把Java对象转换成字节序列的过程叫做对象的序列化,把字节序列恢复成Java对象的过程为对象的反序列化。
对象序列化的作用由两种:
(1)持久化:把对象的字节序列永久的保存在硬盘上,通常存放在一个文件中。
(2)网络通信:在网络上传送对象的字节序列,例如:服务器之间的数据通信、对象传递。
4.14.2序列化涉及的类和接口
ObjectOutputStream代表对象输出流,它的writeObject(Object ob)方法可对参数指定的obj对象进行序列化,把得到的字节写到目标输入流中。
ObjectInputStream代表对象输入流,它的readObject()方法从一个源输入流中读取字节序列,再把它们反序列化为一个对象,并将其返回。
只有实现Serializable接口的对象才能被序列化。Sereiailzable接口是一个空接口,只起到标记作用。
4.15随机访问流
RandomAccessFile可以实现两个作用:
(1)实现对一个文件作读和写的操作
(2)可以访问文件的任意位置,不想其他流只能按照先后顺序读取
RandomAccessFile(String name,String mode)name用来确定文件,mode取r(读)或rw(可读),通过mode可以确定流对文件的访问权限。
seek(long a)用来定位流对象读写文件的位置,a确定读写位置距离文件开头的字节个数。
getFilePointer()获得当前读写位置
4.16File在IO包中的作用
当数据源或目标为文件时,除了可以使用字符串作为文件以及位置指定以外,也可以用File来指定。
5.Apache包
5.1FileUitls的使用
cleanDirectory:清除目录,但不删除目录
contenEquals:比较两个文件是否相等
copyDirectory:将一个目录拷贝到另一个目录
copyFile:将一个文件拷贝到新地址
copyFileDirectory:将一个文件拷贝到新地址下
copyInoutStreamToFile:将一个输入流中的东西拷贝到某个文件中
deleteDirectory:删除目录
deleteQuietly:删除文件
listFiles:l列出指定目录下的所有文件
openInputStream:打开指定文件的输入流
readFileToString:将文件作为字符串数组返回
readLines:把文件内容按行返回到字符串数组中
size:返回文件或目录大小
write:将字符串内容直接写到文件
writeByteArrayToFile:将字节数组内容写到文件
writeLines:将容器中元素的toString方法返回的内容依次写入文件
writeStringToFile:将字符串内容写到文件
5.2IOUtils的使用
buffer方法:将传入的流进行包装,变成缓冲流,并可以通过参数指定缓冲大小
closeQueitly方法:关闭流
conentEquals方法:比较两个流的内容是否一致
copy方法:将输入流内容拷贝到输出流中,可以指定字符编码
copyLarge方法:将输入流内容拷贝到输出流中
linelterator方法:返回可以迭代每一行内容的迭代器
read方法:将输入流中部分内容读入字节数组中
readFully方法:将输入流中所有内容读入字节数组中
readLine方法:读入输入流一行内容
toBufferedInputStream方法:将输入转为带缓存的输入流
toByteArray,toCharArray方法:输入流内容转化为字节数组、字符数组
toString方法:将输入流或数组中的内容转化为字符串
Write方法:向流里写入内容
writeLine方法:向流里写入一行内容