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构造方法中的路径,是否真的存在, 存在返回trueboolean isDirectory()
判断File构造方法中的路径,是不是一个目录(文件夹),是目录返回trueboolean 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()
读取单个字节, 返回读取到的字节,读取到流的末尾,返回-1int read(byte[] b)
读取字节,存储到数组中,读取到流的末尾,返回-1close()
关闭此流,释放资源
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编码。它使用一至四个字节为每个字符编码,编码规则:
- 128个US-ASCII字符,只需一个字节编码。
- 拉丁文等字符,需要二个字节编码。
- 大部分常用字(含中文),使用三个字节编码。
- 其他极少使用的Unicode辅助字符,使用四字节编码。
- 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:/"));
}