IO流

  • 流:一连串流动的数据
  • 流的分类:
    1、按流向分:
    输入流
    输出流
    2、按操作单元分:
    字节流
    字符流
    3、按功能分:
    节点流:直接从数据源到目的地
    功能流:经过包装
    注意:
    1、分清数据源于目的地
    2、IO流以程序为中心
  • 字节流:万能流
    字节输入流:InputStream:抽象类,是所有字节输入流的超类
    按流向分:输入流
    按操作单元分:字节流
    按功能分:节点流
    read()方法,每次从输入流中读入一个字节的内容想要输入多个数据需重复输入。
public static void main(String[] args) throws IOException {
		//1.建立联系
		File src=new File("D:/test.txt");
		//2.选择流
		InputStream is=new FileInputStream(src);
		//3.操作  读入
		int num=-1;
		while((num=is.read())!=-1){
			System.out.println((char)num);
		}
		//4.关闭
		is.close();
	}
}

字节输出流:OutputStream:抽象类,所有字节输出流的超类
注意:使用字节输出流时,若目的地文件不存在,系统会自动创建。若目的地文件夹不存在,则不会自动创建并报出异常。

文件拷贝:
从数据源输入到程序,再从程序输出到目的地

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;

public class CopyFile03 {
	public static void main(String[] args) {
		//1.选择流
		Reader read=null;
		Writer write=null;
		try {
			read=new FileReader(new File("D:/test.txt"));
			write=new FileWriter(new File("D:/dest.txt"),true);
			//2.准备卡车 字符数组
			char[] car=new char[1024];
			int len=-1;
			while(-1!=(len=read.read(car))){
				write.write(car, 0, len);
			}
			//3.刷出
			write.flush();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}  finally{
			//关闭
			if(write!=null){
				try {
					write.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if(read!=null){
				try {
					read.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}
  • 文件夹拷贝
public class CopyDir {

	public static void main(String[] args) throws IOException {
		copyDir("D:/AAA","D:/");
	}
	
	/*
	 * 1.不能把文件拷贝到文件所在路径下
	 */
	public static void copyDir(String src,String dest) throws IOException{
		//判断/最后一次出现的位置索引
		int index=src.lastIndexOf("/");
		String str=src.substring(0, index);
		if(str.equals(dest) || (str+"/").equals(dest)){
			throw new IOException("不能把文件拷贝到文件所在路径下");
		}
		copyDir(new File(src),new File(dest));
	}
	/*
	 * 2.目标路径不能为源文件路径的子路径下
	 */
	private static void copyDir(File src,File dest) throws IOException{
		if(dest.getAbsolutePath().contains(src.getAbsolutePath())){
			throw new IOException("目标路径不能为源文件路径的子路径下");
		}
		//目标路径:完整路径
		copyDirDetails(src,new File(dest,src.getName()));
	}
	
	private static void copyDirDetails(File src,File dest){ // D:/AAA/haha.txt //E:/AAA/
		if(src.isFile()){
			//如果目标文件所在路径文件存在不存在的情况,就创建多个不存在的文件夹
			if(!dest.getParentFile().exists()){
				dest.getParentFile().mkdirs();
			}
			CopyUtil.copyFile(src, dest);
		}else if(src.isDirectory()){
			//创建目标路径所有不存在的文件夹
			dest.mkdirs();
			File[] files=src.listFiles();
			for(File srcFile:files){
				copyDirDetails(srcFile,new File(dest,srcFile.getName()));//D:/AAA/BBB/hehe.txt //E:/AAA/BBB/hehe.txt
			}
		}
	}
}
  • 字符流
    字符输入流 :InputReader:抽象类
    字符输出流:outputWriter:抽象类
    操作步骤与字节流一致
  • 功能流
    1、缓冲流:增强功能,提高性能
    使用:缓冲流(节点流)
    字节缓冲流:
    1)字节输入缓冲流:BufferedInputStream
    2)字节输出缓冲流:BufferedOutputStream
    无新增方法,可以发生多态
    字符缓冲流:
    1)字符输入缓冲流:BufferedReader 新增方法 readLine();
    2)字符输出缓冲流:BufferedWriter 新增方法 newLine();
    有新增方法,无法使用多态

2、转换流:将字节流转换为字符流
1)InputStreamReader(InputStream)
2) OutputStreamWriter(OutputStream)
使用时可能会出现的乱码情况:
1)字符编码格式不统一
2)缺少字节个数
不同编码格式汉字所占字节大小:
ISO-8859-1 1个字节
GBK 2个字节
GB2312 2个字节
UTF-8 3个字节

3、基本数据类型流:读写带有基本数据类型或String类型的数据
使用:基本数据类型流(字节节点流)
DataInputStream(InputStream) 新增方法:readXXX();
DataOutputStream(OutputStream)新增方法: writeXXX();
有新增方法,无法使用多态
注意:读入和输出顺序要保持一致

4、对象流
序列化:将对象信息转换为可存储或可传输的信息格式
序列化输出流:ObjectOutputStream 新增方法:readXXX();
反序列化输入流:ObjectInputStream 新增方法: writeXXX();
有新增方法,无法使用多态
注意:
1)使用时先序列化后反序列化
2)不是所有类都能序列化,必须要实现空接口java.io.Serializable
3)不是所有属性都需要序列化,被transient修饰的属性不需要
4)静态的内容不能被序列化
5)若父类实现了空接口java.io.Serializable,子类所有内容都可序列化