【两万字】IO流介绍大全,代码例题,内存图结构,一看就会

IO流对象

File类

  • 文件 : File计算机中存储数据的 (音乐,电影,word,excel)

  • 目录 : Directory 计算机中的文件夹,文件夹不能存储数据的,保存文件的容器

  • 路径 : 文件和目录所在计算机中的位置

    • C:\Java\jdk1.8.0_221\bin
    • C:\Java\jdk1.8.0_221\bin\java.exe

java.io.File类 : 文件和目录以及路径,变成对象.File类的方法,操作对象

File类具有平台无关性 : Windows系统, Linux系统,Mac系统

File类的构造方法

URI : 统一资源标识符, 包含了URL, 包含非网址 tentent://, mailTo://, thrunder:// , ed2k://

URL: 统一资源定位符, 就是互联网的网络地址 协议://域名 http://www.baidu.com

  • File(String path) 字符串参数必须是路径, 字符串路径变成File对象

  • File(String parent,String child) parent字符串类型的父路径, child字符串子路径

    • 绝对路径 : 路径在计算机中具有唯一性 C:\Java\jdk1.8.0_221\bin
    • 相对路径 : C:\Java\jdk1.8\bin, jdk1.8为参照路径
      • c:\java 是参照路径的父路径 (上一级的文件夹) 唯一性
      • bin 是参照路径的子路径 (下一级的文件夹) 可以多个
  • File(File parent,String child) parent是File类型父路径,child字符串子路径

    /*
	 * File类构造,传递File类型父路径和字符串的子路径
	 */
	public static void method_3() {
		File parent = new File("C:\\Java");
		File file = new File(parent,"jdk1.8.0_221");
		System.out.println(file);
	}
	
	/*
	 * File类构造,传递字符串的父路径和字符串的子路径
	 */
	public static void method_2() {
		File file = new File("C:\\Java", "jdk1.8.0_221");
		System.out.println(file);
	}
	
	/*
	 * File类构造,传递字符串参数(路径)
	 */
	public static void method() {
		File file = new File("C:\\Java\\jdk1.8.0_221\\bin");
		System.out.println(file);
	}

File类的静态成员变量

  • static String separator 与系统有关的默认名称分隔符 \ windows操作系统,目录分隔符,Linux /
  • static String pathSeparator与系统有关的路径分隔符 ; 一个路径结束了

File类的创建方法

  • boolean createNewFile() 创建新文件,创建成功,返回true, 文件的路径和文件名,在File的构造方法中
    • 如果文件已经存在,不会创建,返回false
  • boolean mkdirs() 创建文件夹,创建成功,返回true
    • 如果已经存在了,不会创建,返回false
    /*
	 * File类方法,mkdirs()创建文件夹
	 */
	public static void method_2() {
		File file = new File("d:\\abc.txt");
		boolean b = file.mkdirs();
		System.out.println(b);
	}
	
	/*
	 * File类方法 createNewFile()创建文件
	 */
	public static void method() throws IOException {
		File file = new File("d:\\a.txt");
		boolean b = file.createNewFile();
		System.out.println(b);
	}

File类的删除方法

  • boolean delete() 删除文件或者是文件夹, 不走回收站
    • 如果删除是文件夹,但是文件夹不是空,不能直接删除的
public static void method_3() {
	File file = new File("d:\\1.txt");
	boolean b = file.delete();
	System.out.println(b); 
}

File类的判断方法

  • boolean exists() 判断File构造方法中的路径,是否真的存在, 存在返回true
  • boolean isDirectory() 判断File构造方法中的路径,是不是一个目录(文件夹),是目录返回true
  • boolean isFile() 判断File构造方法中的路径,是不是一个文件,是文件返回true
	/*
	 * File类方法,判断路径是文件,还是文件夹
	 * isDirectory()  isFile()
	 */
	public static void method_2() {
		File file = new File("d:\\springboot_initializr.jar");
		if(file.exists()) {
			boolean b = file.isDirectory();
			System.out.println(b);
		}
	}

File类的获取

  • String getName() 返回File构造方法中,路径的名字,可能是文件名,也可能是文件夹名
  • String getPath() 返回路径名的字符串形式
  • File getAbsoluteFile() 返回路径的绝对路径, 返回值是File对象
  • File getParentFile() 返回指定路径的父路径, 返回值是File对象
/*
	 * File类的获取方法, getParentFile() 获取父路径的
	 * 方法返回值,是File对象
	 */
	public static void method_4() {
		//File file = new File("C:\\Java\\jdk1.8.0_221\\bin");
		File file = new File("C:/Java/jdk1.8.0_221/bin");
		//获取父路径
		File parentFile = file.getParentFile();
		System.out.println(parentFile);
	}
	
	
	/*
	 * File类获取方法, getAbsoluteFile() 获取绝对路径
	 * eclipse环境,获取的绝对路径,是当前工程的路径
	 */
	public static void method_3() {
		File file = new File("bin");
		File absoluteFile = file.getAbsoluteFile();
		System.out.println(absoluteFile);
	}
	
	/*
	 * File类获取方法,getPath() 获取路径名的字符串形态
	 */
	public static void method_2() {
		File file = new File("C:\\Java\\jdk1.8.0_221", "bin");
		String path = file.getPath();
		System.out.println(path);
		System.out.println(file.toString());
	}

	/*
	 * File类获取方法, getName()获取名字
	 */
	public static void method() {
		File file = new File("C:\\Java\\jdk1.8.0_221\\bin\\javac.exe");
		String name = file.getName();
		System.out.println(name);
	}

File类的list开头方法

  • long length() 获取到文件的字节数, 文件夹没有字节数
  • File[] listFiles() 获取构造方法中路径,里面的所有文件列表(文件夹)
    • 文件夹进行遍历
  • static File[] listRoots() 获取当前计算机中的所有系统根目录
/*
	 * File类方法,listRoots()静态
	 */
	public static void method_3() {
		File[] files = File.listRoots();
		for(File f : files) {
			System.out.println(f);
		}
	}
	
	/*
	 * File类方法, listFiles()遍历文件夹
	 */
	public static void method_2() {
		File file = new File("C:\\");
		File[] files = file.listFiles();
		for(File f : files) {
			System.out.println(f);
		}
		System.out.println(files.length);
	}
	
	/*
	 * File类方法,length()文件的字节数
	 */
	public static void method() {
		File file = new File("C:\\Java\\jdk1.8.0_221\\src.zip");
		long length = file.length();
		System.out.println(length);
	}

文件过滤器

需求 : 目录 d:/abc 里面有多个文件. File类的方法listFiles()获取abc目录下面的文件,只要.java文件,其他类型的文件不获取

  • java.io.FileFilter 接口,文件过滤器接口,对获取的文件进行过滤
    • 此接口的实现类,可以传递给方法 listFiles()
    • 抽象方法 boolean accept(File f) 自定义实现类
  • File[] listFiles( FileFilter filter ) 传递文件过滤器的接口
public class FileDemo06 {
	/*
	 * 需求 : 目录 d:/abc 里面有多个文件. 
	 * File类的方法listFiles()获取abc目录下面的文件,只要.java文件,其他类型的文件不获取
	 */
	public static void main(String[] args) {
		File file = new File("d:/abc");
		//遍历abc目录,方法传递文件过滤器实现类对象
		
		//D:/abc/1.txt
		File[] files = file.listFiles( new MyFilter() );
		for(File f : files) {
			System.out.println(f);
		}
	}
}

//定义文件过滤接口的实现类
class MyFilter implements FileFilter{
	//                    //D:/abc/1.txt
	public boolean accept(File pathname) {
		//判断pathname路径,表示的文件,是不是.java文件
		//文件的后缀名是不是.java  String类方法endsWith()  忽略大小写
		return pathname.getName().toLowerCase().endsWith(".java");
	}
}

在这里插入图片描述

目录全遍历

在遍历一个目录的时候,如果发现还有子目录,进去继续遍历

方法自己调用自己进行的遍历

public static void main(String[] args) {
		iteratorDir(new File("C:\\java"));
	}
	/*
	 * 目录的遍历 : 遍历哪个目录,传递参数
	 */
	public static void iteratorDir(File dir) {
		System.out.println(dir);
		//File对象方法listFiles()目录里的遍历
		File[] files = dir.listFiles();
		for(File f : files) {
			//判断,如果f还是目录
			if(f.isDirectory()) {
				//继续遍历   iteratorDir()就是接收目录,遍历目录
				//在定义相同代码的方法,没有必要,自己调用我自己
				iteratorDir(f);
			}else {
				System.out.println(f);
			}
		}
	}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PLFSVxan-1595853974552)(images/目录遍历方式.jpg)]

方法递归调用

递归是一种编写代码上的技巧, 方法自身调用,自己调用自己

适合 : 方法的主体功能不变, 但是功能在执行的时候,参数会改变

方法递归的注意事项 :

  • 方法运行,自己调用自己,会频繁进入栈内存

    • 内存溢出 : 方法进入栈内存,内存以满
    • 使用递归 : 一定要有方法的出口,递归不能太深入
  • 方法递归,计算1+2+3+100

    • 方法的功能不变,求和,每次求和数据是变化
	public static void main(String[] args) {
		int sum = getSum(10);
		System.out.println(sum);
	}
	/*
	 * 递归计算1+2+3+...+100
	 */
	public static int getSum(int n) {
		if( n == 1)
			return 1;
		return n + getSum( n - 1 );
	}

在这里插入图片描述

I : Input 输入

O : Output 输出

流对象 : 数据流, 数据从一个设备流到另一个设备

例子 : 文档从硬盘中,流入到内存中. 文档从内存中,流入到硬盘中

​ 文档从硬盘中,流入到移动硬盘.

​ 可以从一台机器,流到另一台机器

一切都是字节

任何数据,在文件中的形态,都是字节 (文本,图片,音乐,游戏,电影) , 互联网的传输,下载文件,网盘

在这里插入图片描述

IO流的分类

  • 按照数据的流向分
    • 输入流 Input
    • 输出流 Output
  • 按照操作的数据类型分
    • 字节流 字节流可以操作任意类型的数据
    • 字符流 字符流只能操作文本类型数据
      • 什么是文本类型数据 : 使用文本工具(记事本,Notepad++,EditPlus) 打开后,人可以直接阅读的
  • 分类的合并
    • 字节输出流
      • 顶层的抽象基类 : java.io.OutputStream
    • 字节输入流
      • 顶层的抽象基类 : java.io.InputStream
    • 字符输出流
      • 顶层的抽象基类 : java.io.Writer
    • 字符输入流
      • 顶层的抽象基类 : java.io.Reader

字节输出流

可以操作任意类型的数据, 从Java的程序中,输出Output, 又称为写入

OutStream类的方法 : 都是写入数据的方法 write

  • void write(int b) 写入单个字节
  • void write(byte[] b) 写入字节数组
  • void write(byte[] b int off,int len) 写入字节数组的一部分, 开始索引,写入的个数
  • close() 关闭此流,释放资源

OutputStream类的子类

IO流对象的命名非常的有可读性 前缀 + 后缀

前缀 : 这个流能干什么时期

后缀 : 这个流属于哪个分类

子类FileOutputStream :

  • 构造方法
    • FileOutputStream(String name) 传递字符串的文件名 (数据目的)
    • FileOutputStream(File file) 传递File类型的文件
    /*
	 * FileOutputStream写入单个字节
	 */
	public static void method() throws IOException {
		//创建流对象,构造方法绑定数据目的
		FileOutputStream fos = new FileOutputStream("d:/1.txt");
		//流对象的方法 write写入数据
		fos.write(49);
		fos.write(48);
		fos.write(48);
		//释放资源
		fos.close();
	}

IO流对象,write方法,没有实现写入的功能,调用操作系统的功能,实现的写入, 释放操作系统的资源

    /*
	 * FileOutputStream写入字节数组
	 */
	public static void method_2() throws IOException{
		//创建流对象,构造方法绑定数据目的
		FileOutputStream fos = new FileOutputStream("d:/1.txt");
		//创建字节数组
		byte[] bytes = "abcdefg".getBytes();
		//字节流,写入字节数组
		fos.write(bytes);
		
		//写入字节数组的一部分 
		//开始索引,写入的个数
		fos.write(bytes, 3, 2);
		
		fos.close();
	}

文件的追加写入和换行

  • FileOutputStream(String name, boolean append) 第二个参数传递是true,追加写入
  • 换行写,需要使用换行符 \r\n
	public static void method_5() throws IOException {
		FileOutputStream fos = new FileOutputStream("d:/a.txt");
		fos.write("abc\r\n".getBytes());
		fos.write("xyz".getBytes());
		fos.close();
	}
public static void method_4() throws IOException {
		FileOutputStream fos = new FileOutputStream("d:/a.txt",true);
		fos.write(122);
		fos.close();
		
	}

IO流的异常处理

/*
 * IO流对象的异常处理 : 标准写法
 * 资源释放,写在finally 无论文件是否写入成功,资源必须释放
 * try外定义变量,try内创建对象 (提升变量的作用域)
 */
public class FileOutputStreamDemo02 {
	public static void main(String[] args) {
		FileOutputStream fos = null;
		//FileOutputStream fos1 = null;
		try {
			fos = new FileOutputStream("b:/a.txt");
			//fos1 = new FileOutputStream("a1.txt");
			fos.write(97);
		}catch(IOException ex) {
			ex.printStackTrace();
		}finally{
			//fos创建对象失败,导致空指针异常,判断
			if(fos != null)
				try {
					fos.close();
				}catch(IOException ex) {
					ex.printStackTrace();
				}
			
			/*
			 * try { fos1.close(); }catch(IOException ex) { ex.printStackTrace(); }
			 */
		}
	}
}

字节输入流

可以操作任意类型的数据, 从其他的设备中,将数据读取到Java程序

InputStream类的方法 : 都是读取数据的方法 read

  • int read() 读取单个字节, 返回读取到的字节,读取到流的末尾,返回-1
  • int read(byte[] b) 读取字节,存储到数组中,读取到流的末尾,返回-1
  • close() 关闭此流,释放资源

InputStream类的子类

子类FileInputStream :

  • 构造方法
    • FileInputStream (String name) 传递字符串的文件名 (数据源)
    • FileInputStream (File file) 传递File类型的文件
	public static void main(String[] args)throws IOException{
		//创建字节输入流对象,构造方法中,绑定数据源文件
		FileInputStream fis = new FileInputStream("a.txt");
		
		//读取单个字节 方法 read()
		//read()读取结束,返回-1
		int i = 0; //接收read()方法的返回值
		while( (i = fis.read()) != -1 ) {
			System.out.print((char)i);
		}
		fis.close();
	}

读取字节数组

public static void main(String[] args) throws IOException{
		//创建字节输入流对象,绑定数据源
		FileInputStream fis = new FileInputStream("a.txt");
		//定义字节数组,长度推荐写 1024整数倍 1KB
		byte[] bytes = new byte[1024];
		int i = 0 ; //接收read()方法返回值
		while ( (i = fis.read(bytes)) != -1 ) {
			/*
			 * String类构造方法 ,传递字节数组,转成字符串,查询编码表
			 * 构造方法,还可以传递参数 new String(byte[] b , 开始索引, 转几个)
			 */
			System.out.print(new String(bytes,0,i));
		}
		fis.close();
	}

在这里插入图片描述

字节输入流读取中文问题

读取不了

public static void main(String[] args) throws IOException{
    FileInputStream fis = new FileInputStream("d:/1.txt");
    byte[] bytes = new byte[1024];
    int i = 0;
    while( (i = fis.read(bytes)) !=-1) {
    	System.out.print(new String(bytes,0,i));
    }
    fis.close();
}

字节流 : 文件复制 copy

数据源 : d:/springboot_initializr.jar

数据目的 : e: /springboot_initializr.jar

  • 读取一个字节,写入一个字节
/*
	 * 复制文件 : 读写单个字节
	 */
	public static void copy_1() throws IOException{
		//字节输入流,绑定数据源
		FileInputStream fis = new FileInputStream("d:/springboot_initializr.jar");
		//字节输出流,绑定数据目的
		FileOutputStream fos = new FileOutputStream("e:/springboot_initializr.jar");
		//fis读取一个字节, fos写入一个字节
		int i = 0 ;
		while( (i = fis.read()) !=-1) {
			fos.write(i);
		}
		fos.close();
		fis.close();
	}
  • 读取一个字节数组,写入一个字节数组
/*
	 * 复制文件 : 读写字节数组
	 * 提升效率
	 */
	public static void copy_2()throws IOException {
		//字节输入流,绑定数据源
		FileInputStream fis = new FileInputStream("d:/springboot_initializr.jar");
		//字节输出流,绑定数据目的
		FileOutputStream fos = new FileOutputStream("e:/springboot_initializr.jar");
		//fis读取一个字节数组, fos写入一个字节	数组
		byte[] bytes = new byte[1024];
		int i = 0 ;
		while ( (i = fis.read(bytes)) !=-1) {
			fos.write(bytes, 0, i);
		}
		fos.close();
		fis.close();
	}

ad()) !=-1) {
fos.write(i);
}
fos.close();
fis.close();
}




- 读取一个字节数组,写入一个字节数组

```java
/*
	 * 复制文件 : 读写字节数组
	 * 提升效率
	 */
	public static void copy_2()throws IOException {
		//字节输入流,绑定数据源
		FileInputStream fis = new FileInputStream("d:/springboot_initializr.jar");
		//字节输出流,绑定数据目的
		FileOutputStream fos = new FileOutputStream("e:/springboot_initializr.jar");
		//fis读取一个字节数组, fos写入一个字节	数组
		byte[] bytes = new byte[1024];
		int i = 0 ;
		while ( (i = fis.read(bytes)) !=-1) {
			fos.write(bytes, 0, i);
		}
		fos.close();
		fis.close();
	}

字节流缓冲区

文件复制,数组做为缓冲区,目的提高流对象的读写效率.

JDK提供了字节流的缓冲流对象,目的也是为了高效. 字节输出流的缓冲流,字节输入流的缓冲流

BufferedOutputStream字节输出流缓冲区流

提高字节输出流对象的效率

  • BufferedOutputStream继承OutputStream
    • 缓冲流本身也是字节的输出流
    • write写入字节的方法,无需在学习的
  • 构造方法
    • BufferedOutputStream (OutputStream out)
    • new对象的时候,构造方法中传递任意的字节输出流,传递哪个流,高效哪个流

BufferedInputStream字节输入流的缓冲区流

提高字节输入流对象的效率

  • BufferedInputStream继承InputStream
    • 缓冲流本身也是字节的输入流
    • read读取字节的方法,无需在学习的
  • 构造方法
    • BufferedInputStream(InputStream in)
    • new对象的时候,构造方法中传递任意的字节输入流,传递哪个流,高效哪个流
	public static void main(String[] args) throws IOException {
		bufferedReader();
	}
	/* 字节输入流的缓冲流
	 * 读取文件
	 * new对象,传递字节输入出流
	 */
	public static void bufferedReader() throws IOException {
		//创建字节输入流,构造方法,绑定数据源
		FileInputStream fis = new FileInputStream("buffer.txt");
		//创建字节输入流的缓冲流,构造方法里面,传递字节输入流
		BufferedInputStream bis = new BufferedInputStream(fis);
		//变量.保存read方法的返回值
		int len = 0;
		//数组缓冲
		byte[] bytes = new byte[1024];
		while( (len = bis.read(bytes)) !=-1) {
			System.out.print(new String(bytes,0,len));
		}
		bis.close();
	}
	
	/*
	 * 字节输出流的 缓冲流使用
	 * new对象,传递字节输出流
	 */
	public static void bufferedWriter() throws IOException{
		//创建字节输出流
		FileOutputStream fos =  new FileOutputStream("buffer.txt");
		//创建字节输出流的缓冲流,构造方法里面,传递字节输出流
		BufferedOutputStream bos = new BufferedOutputStream(fos);
		//写入数据,单个字节
		bos.write(100);
		
		//字节数组
		byte[] bytes = "abcdefg".getBytes();
		bos.write(bytes);
		
		//数组的一部分
		bos.write(bytes, 2, 2);
		
		//释放资源,释放缓冲流即可
		bos.close();
	}

字符编码

计算机中储存的信息都是用二进制数表示的,而我们在屏幕上看到的数字、英文、标点符号、汉字等字符是二进制数转换之后的结果。按照某种规则,将字符存储到计算机中,称为编码 。反之,将存储在计算机中的二进制数按照某种规则解析显示出来,称为解码 。比如说,按照A规则存储,同样按照A规则解析,那么就能显示正确的文本f符号。反之,按照A规则存储,再按照B规则解析,就会导致乱码现象。

编码 : 字符转换为字节。

解码 : 字节转换为字符。

  • 字符编码Character Encoding : 就是一套自然语言的字符与二进制数之间的对应规则。

    生活中的文字和计算机文字的对应关系 a–>97–>0110 0001

字符集

  • 字符集 Charset:也叫编码表。是一个系统支持的所有字符的集合,包括各国家文字、标点符号、图形符号、数字等。

计算机要准确的存储和识别各种字符集符号,需要进行字符编码,一套字符集必然至少有一套字符编码。常见字符集有ASCII字符集、GBK字符集、Unicode字符集等。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RkJG6VAt-1595854012674)(…/…/…/讲义/JavaEE16全天讲义/day12-IO流/img/1_charset.jpg)]

可见,当指定了编码,它所对应的字符集自然就指定了,所以编码才是我们最终要关心的。

  • ASCII字符集
    • ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统,用于显示现代英语,主要包括控制字符(回车键、退格、换行键等)和可显示字符(英文大小写字符、阿拉伯数字和西文符号)。
    • 基本的ASCII字符集,使用7位(bits)表示一个字符,共128字符。ASCII的扩展字符集使用8位(bits)表示一个字符,共256字符,方便支持欧洲常用字符。
  • ISO-8859-1字符集
    • 拉丁码表,别名Latin-1,用于显示欧洲使用的语言,包括荷兰、丹麦、德语、意大利语、西班牙语等。
    • ISO-8859-1使用单字节编码,兼容ASCII编码。
  • GBxxx字符集
    • GB就是国标的意思,是为了显示中文而设计的一套字符集。
    • GB2312:简体中文码表。一个小于127的字符的意义与原来相同。但两个大于127的字符连在一起时,就表示一个汉字,这样大约可以组合了包含7000多个简体汉字,此外数学符号、罗马希腊的字母、日文的假名们都编进去了,连在ASCII里本来就有的数字、标点、字母都统统重新编了两个字节长的编码,这就是常说的"全角"字符,而原来在127号以下的那些就叫"半角"字符了。
    • GBK:最常用的中文码表。是在GB2312标准基础上的扩展规范,使用了双字节编码方案,共收录了21003个汉字,完全兼容GB2312标准,同时支持繁体汉字以及日韩汉字等。
      • 中文版操作系统使用的编码表就是GBK。
      • 中文汉字在2312和GBK编码表中均为两个字节表示,第一个字节为负数,第二个字节可能是负数也可能是正数。
    • GB18030:最新的中文码表。收录汉字70244个,采用多字节编码,每个字可以由1个、2个或4个字节组成。支持中国国内少数民族的文字,同时支持繁体汉字以及日韩汉字等。尚未正式启用。
  • Unicode字符集
    • Unicode编码系统为表达任意语言的任意字符而设计,是业界的一种标准,也称为统一码、标准万国码。
    • 它最多使用4个字节的数字来表达每个字母、符号,或者文字。有三种编码实现方案,UTF-8、UTF-16和UTF-32。最为常用的UTF-8编码。
    • UTF-8编码,可以用来表示Unicode标准中任何字符,它是电子邮件、网页及其他存储或传送文字的应用中,优先采用的编码。互联网工程工作小组(IETF)要求所有互联网协议都必须支持UTF-8编码。所以,我们开发Web应用,也要使用UTF-8编码。它使用一至四个字节为每个字符编码,编码规则:
      1. 128个US-ASCII字符,只需一个字节编码。
      2. 拉丁文等字符,需要二个字节编码。
      3. 大部分常用字(含中文),使用三个字节编码。
      4. 其他极少使用的Unicode辅助字符,使用四字节编码。
      5. UTF-8是变长编码表,汉字在UTF-8中均为负数。

字符流

字符流 : 只能操作文本文件,其他类型文件,不能操作. 局限性很大

JDK中的字符流 : 字节流 + 编码表 组成而来的

在这里插入图片描述

Writer : 所有字符输出流的父类

  • 只能写入文本文件
  • 方法都是write
    • write(int c) 写入单个字符
    • write(char[] ch) 写入字符数组
    • write(char[] ch,int off,int len )写入字节数组的异步
    • write(String str)写入字符串

转换流

OutputStreamWriter转换流,继承Writer,也是字符的输出流

转换 : 字符流通向字节流的桥梁, 字符流转成字节流

字符 : 查询指定的编码表,变成字节,传递到字节流中

  • OutputStreamWriter类构造方法
    • OutputStreamWriter( OutputStream out)传递字节输出流,使用系统默认编码表 GBK
    • OutputStreamWriter( OutputStream out,String charsetName) 传递字节输出流,指定编码表
  • 注意 : 字符流写入数据,查询编码表,查询完了就完了
    • 查询编码表后的字节,写入到文件去: 方法 flush()
    • 释放资源方法 close() 关闭流前,先刷新
public static void main(String[] args) throws IOException {
		writeUTF();
	}
	/*
	 * 指定的编码表UTF-8
	 * 创建转换流对象,构造方法传递字节输出流,传递编码表名字
	 */
	public static void writeUTF() throws IOException{
		//创建转换流对象,构造方法传递字节输出流,传递编码表名字
		OutputStreamWriter osw = 
				new OutputStreamWriter(new FileOutputStream("utf.txt"),"utf-8");
		//写入字符串
		osw.write("你好");
		
		osw.close();
	}
	
	/*
	 * 系统默认的编码表GBK
	 * 创建转换流对象,构造方法传递字节输出流
	 */
	public static void writeGBK() throws IOException{
		//创建转换流对象,构造方法传递字节输出流
		OutputStreamWriter osw = 
				new OutputStreamWriter(new FileOutputStream("gbk.txt"));
		//字符串
		osw.write("你好");

		//刷新流的缓冲
		osw.flush();
		osw.close();
	}

Reader: 所有字符输入流的父类

  • 只能读取文本文件
  • 方法都是read, 读取到文件末尾返回 -1
    • int read() 写入单个字符
    • read(char[] ch)读取字符数组,返回读取到的字符个数,读取到文件末尾返回 -1

转换流

InputStreamReader转换流,继承Reader,也是字符的输入流

转换 : InputStreamReader是字节流,通向字符流的桥梁, 字节转成字符

字符 : 根据读取的字节,查询编码表,转成字符

  • InputStreamReader构造方法
    • InputStreamReader (InputStream in)传递任意字节输入流,系统默认的编码表GBK
    • InputStreamReader (InputStream in,String chatsetName)传递任意字节输入流,指定编码表
public static void main(String[] args) throws IOException {
		readUTF();
	}
	/*
	 * 指定编码表UTF-8
	 * 创建转换流对象,传递字节输入流,传递编码表名字
	 */
	public static void readUTF() throws IOException{
		//创建转换流对象,传递字节输入流,传递编码表
		InputStreamReader isr = 
				new InputStreamReader(new FileInputStream("utf.txt"),"UTF-8");
		//读取字符数组
		char[] chs = new char[1024];
		//int变量,保存read()方法的返回值
		int len = 0 ;
		while( (len = isr.read(chs)) !=-1) {
			System.out.println(new String(chs,0,len ));
		}
		isr.close();
	}
	
	/*
	 *  系统默认的编码表GBK
	 *  创建转换流对象,传递字节输入流
	 */
	public static void readGBK() throws IOException{
		//创建转换流对象,传递字节输入流
		InputStreamReader isr =
				new InputStreamReader(new FileInputStream("gbk.txt"));
		//读取字符数组
		char[] chs = new char[1024];
		//int变量,保存read()方法的返回值
		int len = 0 ;
		while( (len = isr.read(chs)) !=-1) {
			System.out.println(new String(chs,0,len ));
		}
		isr.close();
	}public static void main(String[] args) throws IOException {
		readUTF();
	}
	/*
	 * 指定编码表UTF-8
	 * 创建转换流对象,传递字节输入流,传递编码表名字
	 */
	public static void readUTF() throws IOException{
		//创建转换流对象,传递字节输入流,传递编码表
		InputStreamReader isr = 
				new InputStreamReader(new FileInputStream("utf.txt"),"UTF-8");
		//读取字符数组
		char[] chs = new char[1024];
		//int变量,保存read()方法的返回值
		int len = 0 ;
		while( (len = isr.read(chs)) !=-1) {
			System.out.println(new String(chs,0,len ));
		}
		isr.close();
	}
	
	/*
	 *  系统默认的编码表GBK
	 *  创建转换流对象,传递字节输入流
	 */
	public static void readGBK() throws IOException{
		//创建转换流对象,传递字节输入流
		InputStreamReader isr =
				new InputStreamReader(new FileInputStream("gbk.txt"));
		//读取字符数组
		char[] chs = new char[1024];
		//int变量,保存read()方法的返回值
		int len = 0 ;
		while( (len = isr.read(chs)) !=-1) {
			System.out.println(new String(chs,0,len ));
		}
		isr.close();
	}

FileWriter

写入字符文件的便捷类

FileWriter继承OutputStreamWriter,继承Writer

方便之处, FileWriter类只能使用系统默认的编码表

FileWriter类构造方法 :

  • FileWriter(File file)传递File对象
  • FileWriter(File file,boolean append),传递File对象,传递的是true,文件追写
  • FileWriter(String filename),传递字符串文件名
  • FileWriter(String filename,boolean append),传递字符串文件名,传递的是true,文件追写
public static void main(String[] args) throws IOException {
		//创建便捷类对象,构造方法传递字符串文件名
		FileWriter fw = new FileWriter("abc.txt");
		//写入单个字符
		fw.write(97);
		//字符流写入数据,需要刷新的
		fw.flush();
		
		//写入字符数组
		char[] ch = "你好,我的程序世界OK".toCharArray();
		fw.write(ch);
		fw.flush();
		
		//写入数组一部分
		fw.write(ch, 2, 3);
		fw.flush();
		
		//写入字符串
		fw.write("写字符串hehe,嘻嘻");
		fw.flush();
		
		fw.close();
	}
  • 字符输出流的方法 flush()和close()区别
    • flush() 刷新该流的缓冲, 数据从内存刷新到目的文件
    • close()关闭流,关闭之前刷新
    • flush() 方法,刷新后,流对象可以继续使用
    • close()关闭流,也刷新,但是流对象,不能在使用

在这里插入图片描述

FileReader

读取字符文件的便捷类

FileReader继承InputStreamReader继承Reader

方便之处, FileReader类只能使用系统默认的编码表

FileReader构造方法 :

  • FileReader(File file)传递File类型对象
  • FileReader(String filename)传递字符串的文件名
	public static void main(String[] args) throws IOException{
		//创建便捷类对象,构造方法传递文件名
		FileReader fr = new FileReader("abc.txt");
		//变量,保存read()方法的返回值
		int len = 0;
		char[] chs = new char[1024];
		while( (len = fr.read(chs)) !=-1) {
			System.out.print( new String(chs,0,len));
		}
		fr.close();
	}

字符流子类父类的区别

  • 字符输出流
  • OuputStreamWriter 父类 : 写入文本文件的时候,指定编码表, 灵活
  • FileWriter子类 : 写入文本文件的时候,编码表只能使用系统默认的
  • 字符输入流
    • InputStreamReader父类 : 读取文本文件的时候,指定编码表, 灵活
    • FileReader子类 : 读取文本文件的时候,编码表只能使用系统默认的
  • 字符流应用,一直就是系统的默认编码,建议使用子类.需要自己指定编码表,只能使用父类

字符流的缓冲流

BufferedWriter字符输出流的缓冲区流

BufferedWriter类继承Writer,本身也是字符输出流.

对字符,数组,或者是字符串的高效写入

字符输出流缓冲流的最重要的功能

  • void newLine() 写入换行符号
    • 自己手动使用 \r\n 实现换行, 不推荐使用
    • 推荐使用newLine()方法, 具有平台无关性
    • Windows系统换行 \r\n,\n Linux系统换行\n,Mac系统换行\r

BufferedWrite类的构造方法

  • BufferedWriter(Writer w) 传递任意的字符输出流,传递哪个流,就高效哪个流
    • 两个选择 : FileWriter OutputStreamWriter
public static void main(String[] args)throws IOException {
    //创建字符输出流,绑定文件
    FileWriter fw = new FileWriter("buffer.txt");
    //创建字符输出流的缓冲流,构造方法传递字符输出流
    BufferedWriter bfw = new BufferedWriter(fw);
    bfw.write("第一行");
    //缓冲流对象的方法 newLine()换行
    bfw.newLine();
    bfw.write("第二行");
    bfw.newLine();
    bfw.write("第三行");

    bfw.close();
}

BufferedReader字符输入流的缓冲区流

BufferedReader类继承Reader,本身是字符输入流.

实现字符,数组,行的高效读取

字符输出流缓冲流的最重要的功能

  • String readLine() 读取文本一行,返回字符串

BufferedReader类构造方法

  • BufferedReader(Reader r) 传递任意的字符输入流,传递谁就对谁高效
    • FileReader类, InputStreamReader
public static void main(String[] args) throws IOException {
		//创建字符输入流,绑定数据源文件
		FileReader fr = new FileReader("buffer.txt");
		//创建字符输入流的缓冲区流
		BufferedReader bfr = new BufferedReader(fr);
		//读取方法 readLine() 读文本行
		//利用方法readLine()返回null
		String line = null;
		while( (line = bfr.readLine()) != null) {
			System.out.println(line);
		}	
		bfr.close();
	}

字符流复制文件问题

只能操作文本文件,局限性非常大的.

不能复制文件,如果需要文件复制,选择字节流!

案例

提供数据 : 多个姓名和年龄,存储在文本文件

读取数据,每个人,按照年龄排序,排序后的结果,存储到新的文件中

思想 : 文本中的数据,读取到集合,对集合中的元素排序,排序后的内容写回到文件中

public static void main(String[] args) throws IOException{
		//读取person.txt, 按行读取
		BufferedReader bfr = new
					BufferedReader(new FileReader("person.txt"));
		//创建List集合,存储多个Person对象
		List<Person> list = new ArrayList<Person>();
		//循环读取文件
		String line = null;
		while( (line = bfr.readLine())!=null) {
			//切割方法,分类姓名和年龄
			String[] strs = line.split(" +");// 0索引是姓名,1索引是年龄
			//创建Person对象
			Person p = new Person(strs[0], Integer.parseInt(strs[1]));
			list.add(p);
		}
		bfr.close();
		//集合排序, 自定义比较器
		Collections.sort(list, new Comparator<Person>() {
			public int compare(Person p1,Person p2) {
				return p1.getAge() - p2.getAge();
			}
		});
		//字符输出缓冲流
		BufferedWriter bfw = new BufferedWriter(new FileWriter("personSort.txt"));
		//遍历集合,取出一个Person对象,写入一个
		for(Person p : list) {
			bfw.write(p.getName()+"  "+p.getAge());
			bfw.newLine();
			bfw.flush();
		}
		bfw.close();
	}

打印流

java.io.PrintStream 字节输出流

java.io.PrintWriter 字符输出流

  • 打印流的特点 :

    • 打印流,只负责数据目的,不负责数据来源
    • 打印流,永远不会抛出IOException
    • 打印流.实现了大量的打印方法. print,println
  • PrintWriter构造方法 : 数据目的

    • PrintWriter(File file) 数据的目的File对象
    • PrintWriter(String filename) 数据的目的是字符串文件名
    • PrintWriter(OutputStream out) 数据目的是字节输出流
    • PrintWriter(Writer w) 数据目的是字符输出流
public static void main(String[] args) throws IOException {
		//System.out.println(100);
		method_2();
	}
	/*
	 * 打印流的数据目的是字符输出流
	 */
	public static void method_2()throws IOException {
		//创建字符输出流
		FileWriter fw = new FileWriter("print2.txt");
		//打印流对象,构造方法,传递字符输出流
		PrintWriter pw = new PrintWriter(fw);
		pw.println(true);
		pw.close();
	}
	
	/*
	 * 打印流的数据目的是字节输出流
	 * println 原样输出
	 */
	public static void method() throws IOException{
		//创建字节输出流
		FileOutputStream fos = new FileOutputStream("print.txt");
		//创建打印流对象,构造方法传递字节输出流
		PrintWriter pw = new PrintWriter(fos);
		//打印流的方法输出 println()
		pw.println(100);
		pw.close();
	}
  • 打印流可以使用自动刷新
    • 打印流开启自动刷新,数据目的必须是流对象
    • 打印流的构造方法第二参数,写true
    • 必须调用方法 : println(),printf(),format() 三个中一个,启用自动刷新
/*
	 * 打印流的自动刷新功能
	 * 如果数据目的,不是流对象,能否使用自动刷新呢,不能
	 * 但是可以转换
	 *   FileWriter(String 文件名)
	 *   FileWriter(File file)
	 *   
	 */
	public static void method_3()throws IOException {
		//创建打印流对象,输出目的必须是流对象
		PrintWriter pw = new PrintWriter(new FileWriter("print3.txt"),true);
		PrintWriter pw2 = new PrintWriter( new FileWriter( new File("print3.txt")),true);
		
		pw.println(200);
		pw.close();
		pw2.close();
	}

对象序列化

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t6yK6rOV-1595854012684)(images/对象的序列化.jpg)]

对象序列化

对象中的数据,写入到硬盘中保存

java.io.ObjectOutputStream

  • ObjectOutputStream用法
    • 构造方法ObjectOutputStream(OutputStream out) : 传递字节输出流
    • 方法 : writeObject(Object obj) 写入对象
  • 被序列化的对象,的类必须实现java.io.Serializable
	public static void main(String[] args) throws IOException {
		writeObj();
	}
	/*
	 * ObjectOutputStream对象的序列化
	 * 写对象
	 */
	public static void writeObj()throws IOException {
		Person person = new Person("张三",22);
		//创建序列化流,构造方法传递字节输出流
		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.txt"));
		//写入对象
		oos.writeObject(person);
		
		oos.close();
	}

对象反序列化

文件中的对象,读取出来,放在内存中

java.io.ObjectInputStream

ObjectInputStream用法

  • 构造方法ObjectInputStream(InputStream in) : 传递字节输入流,输入流中绑定的文件,必须是序列化文件
  • 方法 : Object readObject() 读取对象
/*
	 * ObjectInputStream对象反序列化
	 * 读取对象
	 */
	public static void readObj() throws IOException,ClassNotFoundException{
		//创建字节输入流对象,文件必须是序列化的
		FileInputStream fis = new FileInputStream("person.txt");
		//创建对象的反序列化对象,构造方法传递字节输入流
		ObjectInputStream ois = new ObjectInputStream(fis);
		//读取对象
		Object obj = ois.readObject();
		System.out.println(obj);
		
		ois.close();
	}
  • 静态修饰,不属于对象,属于自己的类,因此静态不能序列化
  • transient修饰的成员变量,阻止进行序列化

反序列化的异常问题

Exception in thread “main” java.io.InvalidClassException: entity.Person; local class incompatible: stream classdesc serialVersionUID = -7348514067820173288, local class serialVersionUID = -3178541272046788724
序列号冲突异常

如果修改了源码,依然可以直接进行反序列化,而不要序列化. 自定义序列号

我们自己定义了序列号, javac编译的时候,不会在帮我们写序列号

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DemHiJWW-1595854012685)(images/序列号问题.jpg)]

Properties类

IO结合,实现持久化的数据

  • IO结合的方法
    • load (InputStream in) 传递字节输入流
    • load (reader r) 传递字符输入流
  • Properties集合中的数据,从流中获取来的
	public static void main(String[] args) throws IOException {
		//字节输入流,读取文件
		FileInputStream fis = new FileInputStream("pro.properties");
		Properties prop = new Properties();
		//集合对象的方法load, IO流管理
		prop.load(fis);
		fis.close();
		System.out.println(prop);
	}

第三方jar包

第一方 : 版权方法Oracle

第二方 : 我们自己

第三方 : 除了第一,第二都是第三方

美国,非营利性的软件基金会,阿帕奇 (Apache)

如果使用第三方jar包

jar里面都是.class文件

  • 在eclipse工程里面,创建文件夹,名字 lib
  • jar放在lib里面
  • jar包放在你的类库中,鼠标右键 --> Build Path Add

IOUtils类

方法全部是静态方法,大部分是释放资源的

  • closeQuietly(OutputStream out) 释放资源,字节输出流,悄悄的关闭
  • closeQuietly(InputStream in)悄悄的关闭
  • closeQuietly(Writer w)悄悄的关闭
  • closeQuietly(Reader r)悄悄的关闭
  • copy(InputStream in ,OutputStream out) 文件复制

FileUtils

方法全部是静态方法

  • copyDirectoryToDirectory(File src,File desc)复制文件夹
	public static void main(String[] args)throws IOException {
		// copy(InputStream  in ,OutputStream out) 文件复制 
		/*
		 * FileInputStream fis = new FileInputStream("d:/springboot_initializr.jar");
		 * FileOutputStream fos = new FileOutputStream("e:/springboot_initializr.jar");
		 * IOUtils.copy(fis, fos); IOUtils.closeQuietly(fis); IOUtils.closeQuietly(fos);
		 */
		
		FileUtils.copyDirectoryToDirectory(new File("d:/abc"), new File("e:/"));
		
	}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值