目录
一、IO初识
1.IO
- 程序设计的输入输出系统(Input/Output),即为IO流
- 输入(Input)指的是:可以让程序系统从外部系统获得数据,核心含义是读取外部数据
- 输出(Output)指的是程序输出数据给外部系统,核心含义是将数据写出外部系统
2.数据源Data Source
- 数据源是提供数据的原始媒介,分为源设备和目标设备
- 源设备:为程序提供数据,一般对应输入流
目标设备:程序数据的目的地,一般对应输出流
3.流
- 流的动态概念是一连串连续动态的数据集合
- 输入流:将数据源中的数据输送到程序中
输出流:将程序中的数据输送到数据源中
4.四大IO抽象类
- InputStream :表示字节输入流的抽象类;数据读取通过子类来实现,不能直接实例化
常用方法:
int read();//读取一个字节的数据,并将字节的值作为int类型进行返回(0-255之间的值);若未读出字节则返回-1
void close();//关闭入流对象,释放资源
- OutputStream :表示字节流输出流的抽象类,将接收到的输出字节发送到某个目的地
常用方法:
void write(int n);//向目的地写入一个字节
void close();// 关闭输出流对象,释放资源
- Reader :用于读取字符流的抽象类
常用方法
int reader();//读取一个字符数据,并将返回值返回到(0-65535之间)一个值;若未读出字符则返回-1
void close();//关闭入流对象,释放资源
- Writer:用于输出字符流的抽象类
常用方法:
void write(int n);//向输出流中写入一个字节
void close();// 关闭输出流对象,释放资源
5.流的细分
- 按流的方向分类
输入流:数据流从数据源到程序(一般以InputStream、Reader结尾的流)
输出流:数据流从程序到目的地(一般以OutputStream、Write结尾的流) - 按处理的数据单元分类
字节流:以字节为单位获取数据,一般以Stream结尾的流是字节流(用于读取二进制文件等)
字符流:以字符为单位获取数据,一般以Reader、Writer结尾的流是字符流(用于读取文本类文件等) - 按处理对象不同分类
节点流:可以直接从数据源或目的地读取数据,即与数据源或目的地直接连接的流
处理流:不直接连接数据源或目的地
6.常用流
- InputStream/OutputStream
字节流的抽象类 - Reader/Write
字符流的抽象类 - FileInputStream/FileOutputStream
节点流:以字节为单位直接操作文件 - ByteArraryInputStream/ByteArraryOutputStream
字节流:以字节为单位直接操作“字节数组对象” - ObjectInputStream/ObjectOutputStream
处理流:以字节为单位直接操作“对象” - DeleteInputStream/DeleteOutputStream
处理流:以字节为单位直接操作“基本数据类型与字符类型” - FileReader/FileWriter
节点流:以字符为单位字节操作“文本文件” - BufferedReader/BufferedWrite
处理流:将Reader/Write对象进行保装,增加缓存功能,提高读写效率 - BufferedInputStream/BufferedOutputStream
处理流:将 InputStream/OutputStream 对象进行包装,增加缓存功能,提高读写效率 - InputStreamReader/OutputStreamWriter
处理流:将字节流对象转化成字符流对象 - PrintStream
处理流:将OutputStream进行包装,方便输出字符,更加灵活
二、IO流入门案例
public class Demo01 {
public static void main(String[] args) {
FileInputStream file = null;
try {
file = new FileInputStream("d:/a.txt");//a.txt中写着abc
int s1=file.read();//对应a---输出97
int s2=file.read();//对应b---输出98
int s3=file.read();//对应c---输出99
int s4=file.read();//没有了,返回-1
System.out.println(s1);
System.out.println(s2);
System.out.println(s3);
System.out.println(s4);
}catch (Exception e){
e.printStackTrace();
}finally {
if (file!=null)
try {
file.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
}
注意:在编写IO流时会经常遇到编译报错,需要通过抛出异常或捕获异常来解决
- 优化(通过while循环进行遍历,是常用的方法)
public class Demo02 {
public static void main(String[] args) {
FileInputStream file = null;
try {
file = new FileInputStream("d:/a.txt");//a.txt中写着abc
StringBuilder sb=new StringBuilder();
int temp=0;
while ((temp=file.read())!=-1){ //循环遍历出abc对应的int类型的数字
System.out.println(temp);
/*
输出
97
98
99
*/
sb.append((char) temp);
}
System.out.println(sb.toString());//输出abc
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if (file!=null)
file.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
}
三、File类
1.File类简介
File类是java提供的针对磁盘中的文件或目录装换对象的包装类。
2.File类的常用方法
- 操作文件的方法
createNewFile();//创建新文件
delete();//删除
exists();//查询是否存在
getAbsolutePath();//获取绝对路径
getPath();//获取相对路径
getName();//获取文件名
isFile();//判断是否为文件
length();//查询文件的字节数
isHidden();//判断是否为隐藏文件
public class Demo01 {
public static void main(String[] args) throws Exception{
File file = new File("d:/aa.txt");
System.out.println(file.createNewFile());//true
System.out.println(file.delete());//true
}
}
- 操作目录的方法
exists();//查询目录是否存在
isDirectory();//判断当前路径是否为目录
mkdir();//创建单级目录
mkdirs();//创建多级目录
getPatentFile();//获取当前目录的父级目录
list();//返回一个字符串数组,包含目录中文件和目录的路径名
listFiles();//返回一个File数组,表示用此抽象路径名表示的目录中的文件
public class Demo02 {
public static void main(String[] args) {
File file = new File("d:/a");
System.out.println(file.mkdir());//true
System.out.println(file.isDirectory());//true
System.out.println(file.delete());
System.out.println("===================================");
File file1 = new File("d:/b/c");
File file11 = new File("d:/b/d");
File file111 = new File("d:/b/e");
System.out.println(file1.mkdirs());
System.out.println(file11.mkdirs());
System.out.println(file111.mkdirs());
System.out.println("===================================");
File file2 = new File("d:/b");
String[] arr = file2.list();
for (String a:arr){
System.out.println(a);
}
/*
输出
c
d
e
*/
System.out.println("===================================");
File[] arr1=file2.listFiles();
for (File b:arr1){
System.out.println(b);
}
/*
输出
d:\b\c
d:\b\d
d:\b\e
*/
}
}
四、常用的流对象
1. 文件字节流
文件字节输入流、文件字节输出流
//对图片的输入和写出
public class Demo03 {
public static void main(String[] args) {
FileInputStream fis= null;
FileOutputStream fos= null;
try {
int temp=0;
fis=new FileInputStream("e:/a.jpg"); //输入字节流
fos=new FileOutputStream("e:/aa.jpg");//字节输出流
while ((temp=fis.read())!=-1){
System.out.println(temp);//输出输入字节流
fos.write(temp);//将输入的东西输出
}
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if(fis!=null){
fis.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
2.缓冲区
- 缓冲区可以提高读写效率
- 方法一:通过创建指定长度的字节数作为缓冲区,缓冲区长度必须是2的整数幂,一般情况下1024长度较为合适;适用于大文件
public class Demo04 {
public static void main(String[] args) {
FileInputStream fis= null;
FileOutputStream fos= null;
try {
int temp=0;
fis=new FileInputStream("e:/a.jpg"); //输入字节流
fos=new FileOutputStream("e:/aa.jpg");//字节输出流
byte[] bytes=new byte[1024];//创建缓冲区,提高读写效率
while ((temp=fis.read(bytes))!=-1){
System.out.println(temp);//输出输入字节流
fos.write(bytes,0,temp);//将输入的东西输出,从0到temp
}
fos.flush();//将数据从内存写入到磁盘中
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if(fis!=null){
fis.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
- 方法二:通过创建一个字节数组作为缓冲区,数组长度通过入流对象available()返回当前文件的预估长度来定义;适用于不太大的文件
public class Demo05 {
public static void main(String[] args) {
FileInputStream fis= null;
FileOutputStream fos= null;
try {
int temp=0;
fis=new FileInputStream("e:/a.jpg"); //输入字节流
fos=new FileOutputStream("e:/aa.jpg");//字节输出流
byte[] bytes=new byte[fis.available()];//创建缓冲区,提高读写效率
while ((temp=fis.read(bytes))!=-1){
fis.read(bytes);
}
fos.write(bytes);
fos.flush();//将数据从内存写入到磁盘中
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if(fis!=null){
fis.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
- 缓冲流
不是具有IO流的读写与写入功能,只是在别的流(节点流或其他处理流)上加上缓冲功能提高效率
public class Demo06 {
public static void main(String[] args) {
FileInputStream fis=null;
FileOutputStream fos=null;
BufferedInputStream bis=null;
BufferedOutputStream bos=null;
try {
fis=new FileInputStream("e:/a.jpg");
bis=new BufferedInputStream(fis);//连接fis的缓冲流
fos = new FileOutputStream("e:/aa.jpg");
bos =new BufferedOutputStream(fos);//连接fos的缓冲流
//缓冲区中,byte数组长度默认是8192
int temp=0;
while ((temp= fis.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){
bos.close();
}
if(fos!=null){
fos.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
- 定义拷贝类工具
public class Demo07 {
public static void main(String[] args) {
Copy("e:/a.jpg","e:/aa.jpg");
}
//src 表示要拷贝的来源 ,des 表示拷贝到的地址
public static void Copy(String src,String des){
FileInputStream fis=null;
BufferedInputStream bis=null;
FileOutputStream fos=null;
BufferedOutputStream bos = null;
try {
fis=new FileInputStream(src);
bis = new BufferedInputStream(fis);
fos =new FileOutputStream(des);
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){
bos.close();
}
if (fos!=null){
fos.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
3.文件字符流
- 文件字符输入流-----FileReader
public class Demo08 {
public static void main(String[] args) {
FileReader frd = null;
try {
frd = new FileReader("d:/a.txt");
int temp=0;
while ((temp=frd.read())!=-1){
System.out.println((char)temp);
}
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if (frd!=null){
frd.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
- 文件字符输出流-----FileWriter
public class Demo08 {
public static void main(String[] args) {
FileWriter fw = null;
FileWriter fw2 = null;
FileWriter fw3 = null;
try {
fw = new FileWriter("e:/a.txt");
fw.write("hello\r\n");// \r\n 是回车换行
fw.write("world\r\n");
fw2 = new FileWriter("e:/a.txt");
fw2.write("wao\r\n");//会覆盖前面的hello
fw3=new FileWriter("e:/a.txt",true);//true是使其能够继续编写,不会覆盖
fw3.write("waowaowao\r\n");
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if(fw!=null){
fw.close();
}if(fw2!=null){
fw2.close();
}if(fw3!=null){
fw3.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
- 拷贝处理
public class Demo09 {
public static void main(String[] args) {
FileReader fr = null;
FileWriter fw = null;
try {
fr=new FileReader("e:/b.txt");
fw=new FileWriter("e:/bb.txt");
char[] buffer = new char[1024];
int temp = 0;
while ((temp = fr.read(buffer))!=-1){
fw.write(buffer,0,temp);
}
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if (fr!=null){
fr.close();
}
if(fw!=null){
fw.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
- 字符缓冲流
BufferedReader / BufferedWrited
(1)字符缓冲输入流
BufferedReader 是针对字符输入流的缓冲流对象,提供更方便的按行读取的方法:readLine();
public class Demo10 {
public static void main(String[] args) {
FileReader fr = null;
BufferedReader br= null;
try {
fr = new FileReader("e:/b.txt");
br = new BufferedReader(fr);
String temp=" ";
while ((temp= br.readLine())!=null){
System.out.println(temp);
}
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if (br!=null){
br.close();
}
if (fr!=null){
fr.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
(2)字符缓冲输出流
BufferedWriter 是针对字符输出流的缓冲流对象,提供更方便的换行处理放法:newLine();
public class Demo11 {
public static void main(String[] args) {
FileWriter fw = null;
BufferedWriter bw = null;
try {
fw=new FileWriter("e:/dd.txt");
bw=new BufferedWriter(fw);
bw.write("hello");
bw.newLine();//换行
bw.write("world");
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if (bw != null){
bw.close();
}
if (fw!=null){
fw.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
- 定义拷贝工具
public class Demo12 {
public static void main(String[] args) {
Copy("e:/b.txt","e:/bb.txt");
}
public static void Copy(String src,String des){
FileReader fr = null;
FileWriter fw = null;
BufferedReader br = null;
BufferedWriter bw = null;
try {
fr=new FileReader(src);
br = new BufferedReader(fr);
fw = new FileWriter(des);
bw = new BufferedWriter(fw);
String temp = "";
while ((temp= br.readLine())!=null)
{
bw.write(temp);
bw.newLine();
bw.flush();
}
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if (br!=null){
br.close();
}
if (fr!=null){
fr.close();
}
if (bw!=null){
bw.close();
}
if (fw!=null){
fw.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
4.转换流
- InputStreamReader / OutputStreamReader用来实现将字节转化为字符流
public class Demo13 {
public static void main(String[] args) {
BufferedReader br = null;
BufferedWriter bw = null;
try {
br = new BufferedReader(new InputStreamReader(System.in));
bw = new BufferedWriter(new OutputStreamWriter(System.out));
while (true){
bw.write("请输入:");
bw.flush();
String input = br.readLine();
if (input.equals("exit")) {
break;
}
bw.write("输出:"+input);
bw.newLine();
bw.flush();
}
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if (br!=null){
br.close();
}
if (bw!= null){
bw.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
5. 字符输出流
PrintWriter,可以按行写出字符串,并且可以通过println();方法实现自动换行
public class Demo14 {
public static void main(String[] args) {
BufferedReader br = null;
PrintWriter pw = null;
try {
br =new BufferedReader(new InputStreamReader(new FileInputStream("e:/a.txt")));
pw=new PrintWriter("e:/aa.txt");
String temp="";
int i=1;
while ((temp=br.readLine())!=null){
pw.println(i+"、"+temp);
i++;
}
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if (br!=null){
br.close();
}
if(pw!=null){
pw.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
6.字节数组流
- 字节数组输入流-----ByteArraryInputStream
把内存中字节数组对象当作数据源
public class Demo01 {
public static void main(String[] args) {
byte[] arr="abcdefg".getBytes();
ByteArrayInputStream bai = null;
StringBuilder sb = new StringBuilder();
try {
bai = new ByteArrayInputStream(arr);
int temp=0;
while ((temp=bai.read())!= -1){
sb.append((char)temp);
}
System.out.println(sb.toString());
}finally {
try {
if (bai!=null){
bai.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
- 字节数组输出流-----ByteArraryOutputStream
public class Demo02 {
public static void main(String[] args) {
ByteArrayOutputStream bao = null;
StringBuilder sb=new StringBuilder();
try {
bao=new ByteArrayOutputStream();
bao.write('a');
bao.write('b');
bao.write('c');
byte[] arr=bao.toByteArray();//输出所写入的内容
for (int i=0;i<arr.length;i++){
sb.append((char)arr[i]);
}
System.out.println(sb.toString());
}finally {
try {
if (bao!=null){
bao.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
7.数据流
数据流将”基本数据类型与字符串类型“作为数据源,允许程序以与机器无关的方式从底层输入输出流中操作Java基本数据类型与字符串类型
- 数据输出流
public class Demo01 {
public static void main(String[] args) {
DataOutputStream dos = null;
try {
dos=new DataOutputStream(new BufferedOutputStream(new FileOutputStream("e:/aa.txt")));
dos.writeChar('a');
dos.writeInt(10);
dos.writeUTF("你好");
dos.flush();
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if (dos!=null){
dos.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
- 数据输入流
public class Demo02 {
public static void main(String[] args) {
DataInputStream dis = null;
try {
dis=new DataInputStream(new BufferedInputStream(new FileInputStream("e:/aa.txt")));
//读入的顺序必须与写出的顺序一致
System.out.println("char:"+dis.readChar());
System.out.println("int:"+dis.readInt());
System.out.println("String:"+dis.readUTF());
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if (dis!=null){
dis.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
8.对象流
-
对象流的本质是用来组织和存储数据的,通过序列化和反序列化来进行
-
序列化:把Java对象转换为字节序列进行传输的过程叫做对象的序列化
反序列化:把序列恢复为Java对象的过程叫做对象的反序列化 -
对象的序列化的作用:
持久化(把对象的字节序列永久的保存到磁盘上,通常放在一个文件中)
网络通信(在网络上传输对象的字节序列) -
ObjectOutputStream 代表对象输出流,他的writeObject(Object obj) 方法可以对参数指定的obj对象进行序列化
ObjectInputStream 代表对象输入流,他的readObject() 方法可以从源输入流中读取字节序列,再把它们反序列化为一个对象 -
序列化需要实现Serializable接口
-
对象流写出操作基本数据类型
public class Demo01 {
public static void main(String[] args) {
ObjectOutputStream oos = null;
try {
oos=new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream("e:/aa.txt")));
oos.writeChar('a');
oos.writeInt(10);
oos.writeBoolean(true);
oos.writeUTF("你好");
oos.flush();
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if (oos!=null){
oos.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
- 对象流读取基本类型数据
public class Demo02 {
public static void main(String[] args) {
ObjectInputStream ois = null;
try {
ois=new ObjectInputStream(new BufferedInputStream(new FileInputStream("e:/aa.txt")));
//读入的顺序必须与写出的顺序一致
System.out.println("char:"+ois.readChar());
System.out.println("int:"+ois.readInt());
System.out.println("String:"+ois.readBoolean());
System.out.println("String:"+ois.readUTF());
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if (ois!=null){
ois.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
- 将对象序列化到文件
//创建对象
public class User implements Serializable {
private int id;
private String name ;
private int age;
public User() {
}
public User(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
//进行序列化
public class Demo01 {
public static void main(String[] args) {
ObjectOutputStream oos = null;
try {
oos = new ObjectOutputStream(new FileOutputStream("e:/aa.txt"));
User user = new User(1,"wao",11);
oos.writeObject(user);
oos.flush();
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if (oos!=null){
oos.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
- 将字节反序列化
//进行反序列化
public class Demo02 {
public static void main(String[] args) {
ObjectInputStream ois = null;
try {
ois=new ObjectInputStream(new FileInputStream("e:/aa.txt"));
User user = (User) ois.readObject();
System.out.println(user.getId()+" "+user.getName()+" "+user.getAge());
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if (ois!=null){
ois.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
9. 随机访问流-----RandomAccessFile
- 可以实现对一个文件做读和写的操作;可以访问文件的任意位置,不用按照先后顺序读取
- 核心方法
RandomAccessFile(String name,String mode) // name 用来确定文件,mode取r(读)或取rw(可读写),通过mode可以确定流对文件的访问权限
seek(long a) //用来定位流对象读写文件的位置,a确定读写位置距离文件开头的字节个数
getFilePointer() // 获取流当前读写的位置
public class Demo01 {
public static void main(String[] args) {
RandomAccessFile raf =null;
try {
raf = new RandomAccessFile("e:/aa.txt","rw");//rw 可读可写
//将若干数据写入到文件中
int[] arr=new int[]{10,20,30,40,50,60,70,80};
for (int i=0;i<arr.length;i++){
raf.writeInt(arr[i]);
}
raf.seek(4);//从第4个字节开始,读4个字节,这里输出20
System.out.println(raf.readInt());//20
//隔一个读一个
for (int i=0 ;i<8 ;i+=2){
raf.seek(4*i);
System.out.print(raf.readInt()+" ");//10 30 50 70
}
System.out.println();
//替换第8个字节的30为35
raf.seek(8);
raf.writeInt(35);
for (int i=0 ;i<8 ;i+=2){
raf.seek(4*i);
System.out.print(raf.readInt()+" ");//10 35 50 70
}
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if (raf!=null){
raf.close();
}
}catch (Exception e){
e.printStackTrace();
}
}
}
}
10.File类在IO中的作用
当以文件为数据源或目标时,除了使用字符串作为文件以及位置的指定外,还可以使用File类指定
br = new BufferedReader(new FileReader(new File("e:/a.txt")));
bw = new BufferedWriter(new FileWriter(new File("e:/aa.txt")));