目录
5、FileInputStream 和FileOutputStream
8、BufferedReader 和BufferedWriter
9、BufferedInputStream 和 BufferedOutputStream
10、 对象流 ObjectInputStream 和 ObjectOutputStream
10.3 对象流 ObjectInputStream 和 ObjectOutputStream
10.4 案例 ObjectOutputStream 序列化
10.5 案例 ObjectInputStream 反序列化
12.2 InputStreamReader 和 OutputStreamWriter
1、概念
文件:就是保存数据的地方
文件流:文件在程序中是以流的形式来操作的
流:数据在数据源(文件)和程序(内存)之间经历的路径
输入流:数据从数据源(文件)到程序(内存)之间的路径
输出流: 数据从程序(内存)到数据源(文件)之间的路径
2、常用的文件操作
2.1 创建文件
-
new File(String pathname) //根据路径构建一个File对象
-
new File(File parent ,String child) //根据父目录文件 + 子路径构建
-
new File(String parent,String child) //根据父目录 + 子路径构建
-
createNewFile 创建新文件
案例:在e盘上,创建news1.txt、news2.txt、news3.txt 用三种不同方式创建
package com.sofwin.config;
import org.junit.Test;
import java.io.File;
import java.io.IOException;
/**
* @packageName: com.sofwin.config
* @author: wentao
* @date: 2022/11/7 19:47
* @version: 1.0
* @email 1660420659@qq.com
* @description: 创建文件 利用三种方式
*/
public class CreateIoFile {
@Test
//方式1 new File(String pathname) //根据路径构建一个File对象
public void create01() {
String filePath = "e:\\news1.txt";
File file = new File(filePath);
try {
file.createNewFile();
System.out.println("文件创建成功!");
} catch (IOException e) {
e.printStackTrace();
}
}
//方式2 new File(File parent ,String child) //根据父目录文件 + 子路径构建
@Test
public void create02() {
File file = new File("e:\\");
File file1 = new File(file,"news2.txt");
try {
//这个代码才是真正将内存中数据 创建到磁盘中
file1.createNewFile();
System.out.println("文件创建成功!");
} catch (IOException e) {
e.printStackTrace();
}
}
//方式3 new File(String parent,String child) //根据父目录 + 子路径构建
@Test
public void create03() {
String parenPath = "e:\\";
String childPath = "news3.txt";
File file = new File(parenPath,childPath);
try {
file.createNewFile();
System.out.println("文件创建成功");
} catch (IOException e) {
e.printStackTrace();
}
}
}
2.2 获取文件相关信息
-
getName
-
getAbsolutePath
-
getParent
-
length
-
exists
-
isFile
-
isDirectory
package com.sofwin.config;
import org.junit.Test;
import java.io.File;
/**
* @packageName: com.sofwin.config
* @author: wentao
* @date: 2022/11/7 20:01
* @version: 1.0
* @email 1660420659@qq.com
* @description: 获取文件信息
*/
public class FileInformation {
public static void main(String[]args){
}
//获取文件信息
@Test
public void info() {
//创建文件对象
File file = new File("e:\\news1.txt");
//调用相应的方法,得到对应信息
System.out.println("文件名字="+file.getName());
System.out.println("文件绝对路径"+file.getAbsolutePath());
System.out.println("文件父类目录"+file.getParent());
System.out.println("文件大小(字节)"+file.length());
System.out.println("文件是否存在"+file.exists());
System.out.println("文件是否 是一个文件"+file.isFile());
System.out.println("文件是否 是一个目录"+file.isDirectory());
}
}
2.3 目录的操作和文件删除
-
mkdir 创建一级目录
-
mkdirs 创建多级目录
-
delete 删除空目录或文件
-
在java中 将文件夹也当做文件
3、 IO流原理及流的分类
-
IO是Input和Output的缩写,I/O技术是非常实用的技术,用于处理数据传输。如读写文件,网络通讯等
-
java程序中,对数据的输入和输出操作以 流的方式进行
-
java.io包下提供了各种流类和接口,用以获取不同种类的数据,并通过方法输入或输出数据
-
输入input:读取外部数据(磁盘、光盘等存储设置的数据)到程序(内存)中
-
输出output: 将程序(内存)数据输出到磁盘、光盘等存储设备中
3.1 流的分类
-
按操作数据单位不同分为:字节流 (8bit) 二进制文件,字符流(字符) 文本文件
-
按数据流的流向不同分为:输入流和输出流
-
按流的角色不同分为:节点流,处理流/包装流
抽象基类 | 字节流 | 字符流 |
---|---|---|
输入流 | InputStream | Reader |
输出流 | OutputStream | Wirter |
-
java的IO流共涉及40多个类,实际上非常规则,都是从上面四个抽象基类派生的
-
由者四个类派生出来的子类名称都是以其父类名作为子类名后缀
4、InputStream 字节输入流
4.1 InputStream的常用子类
-
FileInputStream 文件输入流
-
BufferedInputStream 缓存字节输入流
-
ObjectInputStream 对象字节输入流
5、FileInputStream 和FileOutputStream
5.1 FileInputStream
应用案例
要求:请使用FileInputStream 读取hello.txt文件并将文件内容显示到控制台
package com.sofwin.config;
import org.junit.Test;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLOutput;
/**
* @packageName: com.sofwin.config
* @author: wentao
* @date: 2022/11/7 21:26
* @version: 1.0
* @email 1660420659@qq.com
* @description: 文件输入流 (字节输入流)
*/
public class FileInputStream_ {
public static void main(String[]args){
}
/**
* 单个字节的读取 效率比较低
* 使用 read(byte[] bytes)进行优化
*
* 一般字节输入流都是用于读取二进制文件,文本文件是由字符输入流读取
* 因为一旦出现汉字 一个一个读取字节,但是一个汉字代表是哪个字节 就会出现中文乱码的问题
*/
@Test
public void readFile01() {
int readData;
InputStream io = null;
try {
//创建FileInputStream
io = new FileInputStream("e:\\hello.txt");
//从该输入流读取一个字节的数据 ,如果没有返回-1 表示读取完毕
while ((readData = io.read()) != -1) {
System.out.print((char)(readData));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//一定要关闭流
try {
io.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Test
public void readFile02() {
int len = 0;
InputStream io = null;
byte[] b = new byte[8]; //一次读取8个字节
try {
//创建FileInputStream
io = new FileInputStream("e:\\hello.txt");
//一次读取 byte数组长度 如果返回成功 len为文件中读取的个数 如果数据读完返回-1
while ((len = io.read(b)) != -1) {
System.out.print(new String(b,0,len));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//一定要关闭流
try {
io.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
5.2 FileOutputStream
应用案例
要求:请使用FileOutputStream 在a.txt文件中写入 “helloWorld” ,(如果文件不存在,会自动创建文件)
package com.sofwin.config;
import org.junit.Test;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
/**
* @packageName: com.sofwin.config
* @author: wentao
* @date: 2022/11/7 22:07
* @version: 1.0
* @email 1660420659@qq.com
* @description: FileOutputStream_
*/
public class FileOutputStream_ {
/**
* 演示使用FileOutputStream 将数据写到文件中,如果该文件不存在,则创建该文件
*/
@Test
public void wirteFile() {
OutputStream op = null;
try {
//1.如果new FileOutputStream("e:\\a.txt"); 创建方式
// 当写入内容会覆盖原先的内容
//2.如果new FileOutputStream("e:\\a.txt",true); 创建方式
// 当写入内容会追加到文件后面
op = new FileOutputStream("e:\\a.txt");
String str = "helloWorld";
//也可以指定编码
op.write(str.getBytes());
System.out.println("写入成功");
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
op.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
综合案例
要求:使用FileInputStream和FileOutputStream将图片进行拷贝
package com.sofwin.config;
import org.junit.Test;
import java.io.*;
/**
* @packageName: com.sofwin.config
* @author: wentao
* @date: 2022/11/8 11:04
* @version: 1.0
* @email 1660420659@qq.com
* @description: 文件拷贝
*/
public class FileCopy {
@Test
//完成文件拷贝 将e:\\1.JPG 拷贝到 f:\\2.JPG
public void copyFile() {
InputStream io = null;
OutputStream op = null;
byte[] b = new byte[1024];
int dataLen = 0;
//1、创建文件输入流 将文件读入到程序
//2. 创建文件输出流 将读取的数据写入到磁盘中(文件中)
//3.读取部分数据就写入到文件中
try {
io = new FileInputStream("e:\\1.JPG");
op = new FileOutputStream("f:\\2.JPG");
while ((dataLen = io.read(b)) != -1) {
//读取到后就写入到文件
op.write(b,0,dataLen);
}
System.out.println("拷贝成功");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
//最后关闭资源
try {
if (op != null) {
op.close();
}
if (io != null) {
io.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
6、FileReader 和 FileWriter
6.1 FileReader相关方法
-
new FileReader(File/String)
-
read 每次读取单个字符,返回该字符,如果到文件末尾就返回-1
-
read(char[]) 批量读取多个字符到数组,返回读取到到的字符数 ,如果到文件莫问返回-1
6.2 FileWriter相关方法
-
new FileWriter(File/String) :覆盖模式,相当于流的指针在首端
-
new FileWriter(File/String , true) :追加模式,相当于流的指针在尾端
-
writer(int) 写入单个字符
-
writer(char[]) 写入整个数组
-
writer(char[],off,len) 写入指定数组的指定部分
-
writer(String) 写入整个字符串
-
writer(String ,off,len) 写入字符串的指定文职
-
注意: FileWriter使用后,必须要关闭 (close)或刷新(flush),否则写入不到指定的文件
6.3 案例
要求:使用FileReader 从 reader.txt 中读取内容并显示
package com.sofwin.config;
import org.junit.Test;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
/**
* @packageName: com.sofwin.config
* @author: wentao
* @date: 2022/11/8 11:27
* @version: 1.0
* @email 1660420659@qq.com
* @description: TODO
*/
public class FileReader_ {
//从f:\\reader.txt 读取内容并显示出来
@Test
public void fileReader() {
Reader reader = null;
int readData = 0;
try {
reader = new FileReader("f:\\reader.txt");
//单个字符读取
while ((readData = reader.read()) != -1) {
System.out.print((char)readData);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if (reader == null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
@Test
public void fileReader2() {
Reader reader = null;
int readLen = 0;
char[] chars = new char[8];
try {
reader = new FileReader("f:\\reader.txt");
//按照字符数组读取文件
while ((readLen = reader.read(chars)) != -1) {
System.out.print(new String(chars,0,readLen));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
if (reader == null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
要求:使用FileWriter 将"风雨之后,必见彩虹"写入到 note.txt中文件中
注意细节 使用后必须要关闭或者刷新
package com.sofwin.config;
import org.junit.Test;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
/**
* @packageName: com.sofwin.config
* @author: wentao
* @date: 2022/11/8 11:37
* @version: 1.0
* @email 1660420659@qq.com
* @description: 文件输出流
*/
public class FileWriter_ {
@Test
public void fileWriter() {
Writer writer = null;
char[] chars = {'a','b','网'};
try {
//默认是覆盖写入 会覆盖文件之前的内容
//最终将writer方法的内容加入进去
//例如原先文件有aaa三个内容
//执行两个write 1.write('h') 2. write('w')
//结果就变成了 hw 覆盖了之前的aaa
writer = new FileWriter("f:\\node.txt");
// 1. writer(int) 写入单个字符
writer.write('我');
// 2. writer(char[]) 写入整个数组
writer.write(chars);
// 3. writer(char[],off,len) 写入指定数组的指定部分
writer.write(chars,0,1);
// 4. writer(String) 写入整个字符串
writer.write("风雨之后,必见彩虹");
// 5. writer(String ,off,len) 写入字符串的指定文职
writer.write("伤害",0,1);
} catch (IOException e) {
e.printStackTrace();
}finally {
//对应的FileWriter 一定要关闭流 或者flush才能真正的把数据写入到文件中
/*
对应源码 当执行close的时候才走到这个关键的 this.out.writer进行写数据
this.bb.flip();
int var1 = this.bb.limit();
int var2 = this.bb.position();
assert var2 <= var1;
int var3 = var2 <= var1 ? var1 - var2 : 0;
if (var3 > 0) {
if (this.ch != null) {
assert this.ch.write(this.bb) == var3 : var3;
} else {
this.out.write(this.bb.array(), this.bb.arrayOffset() + var2, var3);
}
}
*/
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
System.out.println("程序结束");
}
}
7、节点流和处理流
7.1 节点流
节点流可以从一个特定的数据源读写数据 如FileReader FileWriter
7.2 处理流
处理流(包装类) 是“连接” 已存在的流(处理流或节点流)之上,为程序提供更为强大的读写功能,如BufferedReader BufferedWriter
7.3 节点流和处理流的区别和联系
-
节点流是底层流/低级流,直接跟数据源相接
-
处理流(包装流),用于包装节点流,既可以消除不同节点流的实现差异,也可以提供更方便的方法来完成输入和输出
-
处理流对节点流进行包装,使用了修饰器设计模式,不会直接与数据源相连
-
处理流的功能主要体现 (我认为类似于多态一样)
-
性能的提高: 主要以增加缓冲的方式来提高输入输出的效率
-
操作的便捷: 处理流提供了一系列便捷的方法来一次输入输出大批量数据,使得更加灵活方便
-
8、BufferedReader 和BufferedWriter
BufferedReader 和BufferedWriter 属于字符流,是按照字符来读取数据的
关闭的时候,只需要关闭外层流即可 也就是包装流即可(真正处理读写的是节点流,处理流(包装流)只是一个包装,但是从写了close方法 只要关闭包装流就会自动将节点流关闭)
案例1 BufferedReader
要求: 使用BufferedReader 读取文本文件,并显示在控制台
package com.sofwin.config;
import org.junit.Test;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
/**
* @packageName: com.sofwin.config
* @author: wentao
* @date: 2022/11/8 15:19
* @version: 1.0
* @email 1660420659@qq.com
* @description: TODO
*/
public class BufferedReaderTest {
@Test
public void bufferedReaderTest() throws IOException {
BufferedReader bufferedReader = new BufferedReader(new FileReader("f:\\node.txt"));
//读取
String line;
//按行读取
//当返回null的时候 代表读取完毕
while ((line = bufferedReader.readLine()) != null) {
System.out.println(line);
}
//关闭流,注意只需要关闭外层流就可以
//因为底层会自动关闭节点流
bufferedReader.close();
/*
public void close() throws IOException {
synchronized (lock) {
if (in == null)
return;
try {
in.close(); //这个in就是我们传入的fileReader
} finally {
in = null;
cb = null;
}
}
}
*/
}
}
案例2 BufferedWriter
要求:使用BufferedWriter 将“hello,你好啊,宝贝”写入到文件中
package com.sofwin.config;
import org.junit.Test;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
/**
* @packageName: com.sofwin.config
* @author: wentao
* @date: 2022/11/8 15:30
* @version: 1.0
* @email 1660420659@qq.com
* @description: TODO
*/
public class BufferWriterTest {
@Test
public void bufferWriter() throws IOException {
BufferedWriter writer = new BufferedWriter(new FileWriter("f:\\c.txt"));
writer.write("hello,你好啊,宝贝1");
//插入一个和系统相关的换行符
writer.newLine();
writer.write("hello,你好啊,宝贝2");
writer.newLine();
writer.write("hello,你好啊,宝贝3");
writer.close();
}
//如果设置的是追加
@Test
public void bufferWriter2() throws IOException {
//new FileWriter("f:\\c.txt",true) 以追加的方式写入到文件中
BufferedWriter writer = new BufferedWriter(new FileWriter("f:\\c.txt",true));
writer.write("hello,你好啊,宝贝1");
//插入一个和系统相关的换行符
writer.newLine();
writer.write("hello,你好啊,宝贝2");
writer.newLine();
writer.write("hello,你好啊,宝贝3");
writer.close();
}
}
案例3 同时使用
要求:使用BufferedReader和BufferedWriter 完成文本的拷贝
package com.sofwin.config;
import java.io.*;
/**
* @packageName: com.sofwin.config
* @author: wentao
* @date: 2022/11/8 15:38
* @version: 1.0
* @email 1660420659@qq.com
* @description: TODO
*/
public class BufferedCopy {
public static void main(String[]args) {
String srcFilePath = "f:\\c.txt";
String destFilePath = "f:\\wt.txt";
BufferedReader bufferedReader = null;
BufferedWriter bufferedWriter = null;
String str ;
try {
bufferedReader = new BufferedReader(new FileReader(srcFilePath));
bufferedWriter = new BufferedWriter(new FileWriter(destFilePath));
//readLine 读取一行数据 但是没有带换行
while ((str = bufferedReader.readLine()) !=null) {
bufferedWriter.write(str);
bufferedWriter.newLine(); //进行换行
}
System.out.println("拷贝完毕");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (bufferedReader != null) {
bufferedReader.close();
}
if (bufferedWriter != null) {
bufferedWriter.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
9、BufferedInputStream 和 BufferedOutputStream
BufferedInputStream ,在创建的时候,会创建一个内部缓冲区数组
BufferedOutputStream 实现了缓冲的输出流,可以讲多个字节写入底层输出流和在那个,而不必对每次字节写入调用底层系统
应用 同时使用
要求:使用BufferedInputStream 和 BufferedOutputStream 完成对图片/音乐的拷贝
package com.sofwin.config;
import java.io.*;
/**
* @packageName: com.sofwin.config
* @author: wentao
* @date: 2022/11/8 15:58
* @version: 1.0
* @email 1660420659@qq.com
* @description: 使用BufferedInputStream 和 BufferedOutputStream 完成对图片/音乐的拷贝
* 字节流可以操作文本文件的拷贝吗? 可以操作
*/
public class BufferedTest {
public static void main(String[]args){
String srcFilePath = "e:\\1.JPG"; //源文件位置
String destFilePath = "e:\\wt.JPG"; //目的位置
BufferedInputStream inputStream = null;
BufferedOutputStream outputStream = null;
byte[] b = new byte[1024];
int readLen = 0;
try {
inputStream = new BufferedInputStream(new FileInputStream(srcFilePath));
outputStream = new BufferedOutputStream(new FileOutputStream(destFilePath));
while ((readLen = inputStream.read(b)) != -1) {
outputStream.write(b,0,readLen);
}
System.out.println("拷贝成功");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
//关闭流
try {
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
10、 对象流 ObjectInputStream 和 ObjectOutputStream
10.1 需求:
-
将 int num = 10这个int数据保存到文件中,注意保存的不单单是数据,还有数据类型,使得我们能够从文件中直接恢复int num = 10
-
将Dog dog = new Dog(“旺财”,3)这个对象保存到文件中,并且能够从文件中恢复成dog对象
-
上面的要求,就是能够将基本数据类型或者对象进行序列化和反序列化
10.2 序列化和反序列化
-
序列化就是保存数据的时候,保存数据的值和数据类型
-
反序列化就是恢复数据的时候,恢复数据的值和数据类型
-
需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让类是可序列化的,该类必须要实现如下两个接口的一个
-
Serializable (推荐 这个是一个标记接口)
-
Externallizable //该接口有方法需要实现,一般我们使用上面的Serializable接口
-
10.3 对象流 ObjectInputStream 和 ObjectOutputStream
-
功能:提供了对基本数据类型或者对象类型的序列化和反序列化的方法
-
ObjectOutputStream 提供了序列化的功能
-
ObjectInputStream 提供了反序列化的功能
-
这两个也是处理流(包装流)
10.4 案例 ObjectOutputStream 序列化
要求:使用ObjectOutputStream 序列化基本数据类型和一个Dog对象(name ,age) ,并保存到data.txt文件中
package com.sofwin.config;
import java.io.*;
/**
* @packageName: com.sofwin.config
* @author: wentao
* @date: 2022/11/8 16:44
* @version: 1.0
* @email 1660420659@qq.com
* @description: 使用ObjectOutputStream 序列化基本数据类型和一个Dog对象(name ,age) ,并保存到data.txt文件中
*/
public class ObjectOutputStream_ {
public static void main(String[]args) throws IOException {
//序列化后保存的文件格式,不是存文本的,而是按照它的格式保存的
String filePaht ="e:\\data.txt";
ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream(filePaht));
//序列化数据到文件中
//100 -->Integer --> 这个类实现了Serializable接口
objectOutputStream.writeInt(100);
objectOutputStream.writeBoolean(true);
objectOutputStream.writeChar('a');
objectOutputStream.writeDouble(9.5);
objectOutputStream.writeUTF("风花雪月");
//保存一个Dog对象
objectOutputStream.writeObject(new Dog("大黄",2));
objectOutputStream.close();
System.out.println("数据化序列化到文件中");
}
}
class Dog implements Serializable {
private String name;
private int age ;
public Dog(String name, int age) {
this.name = name;
this.age = age;
}
}
10.5 案例 ObjectInputStream 反序列化
要求:使用ObjectInputStream data.txt文件中数据反序列化出来
package com.sofwin.config;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
/**
* @packageName: com.sofwin.config
* @author: wentao
* @date: 2022/11/8 16:54
* @version: 1.0
* @email 1660420659@qq.com
* @description: TODO
*/
public class ObjectInputStream_ {
public static void main(String[]args) throws IOException, ClassNotFoundException {
String filePath ="e:\\data.txt";
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(filePath));
//注意: 读取顺序一定要和存储的顺序一致 否则会出现异常
int read = objectInputStream.readInt();
System.out.println(read);
boolean b = objectInputStream.readBoolean();
System.out.println(b);
char c = objectInputStream.readChar();
System.out.println(c);
double v = objectInputStream.readDouble();
System.out.println(v);
String s = objectInputStream.readUTF();
System.out.println(s);
//o的编译运行是Object 运行类型是dog
Object o = objectInputStream.readObject();
System.out.println(o.getClass());
System.out.println(o);
//这里有一个非常很重要的细节
//1.如果我们希望调用Dog的方法 需要向下转型
//但是我们没有创建Dog类 所以需要将Dog类拷贝到key引入的位置
System.out.println("解读完毕");
objectInputStream.close();
}
}
10.6 对象处理流的注意事项
-
读写顺序要一致
-
要求实现序列化或反序列化的对象,需要实现Serializable接口
-
序列化的类中建议添加SerialVersionUID,为了提高版本的兼容性
-
序列化对象的时候,默认将里面的所有属性进行序列化,但是除了static或transient修饰的成员
-
序列化对象的时候,要求里面的数据性类型也需要实现序列化接口
-
序列化具备可继承性,也就是如果某类已经实现了序列化,则它的所有子类也已经默认实现了序列化
11、标准输入输出流
类型 | 默认设备 | |
---|---|---|
System.in 标准输入 | InputStream | 键盘 |
System.out 标准输出 | PrintStream | 显示器 |
package com.sofwin.config;
/**
* @packageName: com.sofwin.config
* @author: wentao
* @date: 2022/11/8 19:45
* @version: 1.0
* @email 1660420659@qq.com
* @description: TODO
*/
public class standardInputAndOutput {
public static void main(String[]args){
//System类 public final static InputStream in = null;
//它的编译类型 InputStream 运行类型 BufferedInputStream
//标准输入 键盘
System.out.println(System.in.getClass());
//public final static PrintStream out = null;
//编译类型 PrintStream 运行类型 PrintStream
//表示标准输出 显示器
System.out.println(System.out.getClass());
}
}
11.1 案例
-
传统方法 System.out.println() 是使用out对象将数据输出到显示器
-
传统方法 Scanner scan = new Scanner(System.in) 是从标准输入键盘接受数据
12、 转换流
12.1 为什么需要转换流
package com.sofwin.config;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
/**
* @packageName: com.sofwin.config
* @author: wentao
* @date: 2022/11/8 19:55
* @version: 1.0
* @email 1660420659@qq.com
* @description: 看一个中文乱码问题
*/
public class Transformation {
public static void main(String[]args) throws IOException {
//读取f:\\node.txt 文件到程序
//创建字符输入流 BufferReader 处理流
//在默认情况下 读取文件是按照utf-8编码读取的
//如果修改成国标码后 就会出现中文路那么问题了
//这个时候就出现了转换流 因为转换流可以设置编码格式 设置完毕后进行转换为字符流
String s;
BufferedReader bufferedReader = new BufferedReader(new FileReader("f:\\node.txt"));
while ((s = bufferedReader.readLine()) != null) {
System.out.println(s);
}
bufferedReader.close();
}
}
12.2 InputStreamReader 和 OutputStreamWriter
-
InputStreamReader 是Reader的子类 可以将InputStream (字节流)包装成Reader(字符流)
-
OutputStreamWriter 是Writer的子类 实现将OutputStream(字节流)包装成Writer(字符流)
-
当处理纯文本数据的时候,如果使用字符流效率更高,并且可以有效解决中文乱码问题,所以建议将字节流转换成字符流
-
可以在使用时指定编码格式(比如 utf-8、gbk、iso8850-1)
案例:
要求 字节流FileInputStream 包装成字符流InputStreamReader,对文件进行读取 按照gbk格式,进而包装成ufferedReader
package com.sofwin.config;
import com.sun.org.apache.bcel.internal.generic.NEW;
import java.io.*;
/**
* @packageName: com.sofwin.config
* @author: wentao
* @date: 2022/11/8 19:55
* @version: 1.0
* @email 1660420659@qq.com
* @description: FileInputStream 转换为 InputStreamReader 指定编码gbk
*/
public class Transformation {
public static void main(String[] args) throws IOException {
String s;
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(
new FileInputStream("f:\\node.txt"), "gbk"));
while ((s = bufferedReader.readLine()) != null) {
System.out.println(s);
}
bufferedReader.close();
}
}
案例:
要求: 编程将字节流FileOutputStream 保证成字符流 OutputStreamWriter,对文件进行写入(按照gbk的格式)
package com.sofwin.config;
import java.io.*;
/**
* @packageName: com.sofwin.config
* @author: wentao
* @date: 2022/11/8 20:39
* @version: 1.0
* @email 1660420659@qq.com
* @description: TODO
*/
public class OutputStreamWriter_ {
public static void main(String[]args) throws IOException {
OutputStreamWriter gbk = new OutputStreamWriter(new FileOutputStream("f:\\lkj.txt"), "gbk");
gbk.write("我是一个小孩子\n");
gbk.write("java开发");
gbk.close();
System.out.println("保存文件,按照gbk格式");
}
}
13、打印流
打印了只有输出流,没有输入流
PrintStream(字节流) 和 PrintWriter(字符流)
13.1 PrintStream
package com.sofwin.config;
import java.io.IOException;
import java.io.PrintStream;
/**
* @packageName: com.sofwin.config
* @author: wentao
* @date: 2022/11/8 20:49
* @version: 1.0
* @email 1660420659@qq.com
* @description: PrintStream 字节打印流
*/
public class PrintStream_ {
public static void main(String[]args) throws IOException {
PrintStream out = System.out;
//在默认情况下 打印流PrintStream 输出数据的位置是 标准输出显示器
/*
public void print(String s) {
if (s == null) {
s = "null";
}
write(s);
}
*/
out.print("join hello");
//因为print底层使用的write 所以我们可以直接调用write进行打印/输出
out.write("哈哈,小宝贝".getBytes());
out.close();
//我们可以去修改打印流输出的位置
System.setOut(new PrintStream("e:\\t1.txt"));
System.out.println("hello 李科技");
}
}
13.2 PrintWriter
package com.sofwin.config;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
/**
* @packageName: com.sofwin.config
* @author: wentao
* @date: 2022/11/8 21:09
* @version: 1.0
* @email 1660420659@qq.com
* @description: 演示PrintWriter 使用方式
*/
public class PrintWriter_ {
public static void main(String[]args) throws IOException {
// PrintWriter writer = new PrintWriter(System.out); //默认控制台
//指定位置
PrintWriter writer = new PrintWriter(new FileWriter("e:\\f2.txt"));
writer.print("北京你好");
writer.close(); //如果不关闭 无法写入
}
}
14、 Properties类
传统方法获取 Properties类中的jdbc.driver对应的值
jdbc.properties
jdbc.driver=com.mysql.cj.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/xiangmu?serverTimezone=UTC jdbc.username=root jdbc.pwd=root
package com.sofwin.config;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
/**
* @packageName: com.sofwin.config
* @author: wentao
* @date: 2022/11/8 21:27
* @version: 1.0
* @email 1660420659@qq.com
* @description: 传统方式获取properties文件内容
* */
public class Porperties_01 {
public static void main(String[]args) throws IOException {
BufferedReader bufferedReader = new BufferedReader(new FileReader("jdbc.properties"));
String data;
while ((data = bufferedReader.readLine()) != null) {
//要求我们获取指定jdbc.driver的值
String[] split = data.split("=");
System.out.println(split[0]+"对应的值:"+split[1]);
}
bufferedReader.close();
}
}
使用传统的方法我们是可以读取到 xxx .properties文件
但是读取的是一行数据,我们只是对应等号右边的值
因此我们得到的数据 还要进行处理,当数据量多的时候,处理麻烦
所以这时候就引出了Properties类 专门进行处理 xxx.properties文件 ,非常方便
14.1 基本介绍
-
专门用于读写配置文件的集合类
配置文件的格式: 键=值
-
注意:键值对不需要空格,值不需要用引号引起来。默认类型是String
14.2 常见方法
-
load 加载配置文件的键值对到Properties对象
-
list 将数据显示到指定设备/流对象
-
getProperty(key) 根据键获取值
-
setPorperty(key,value) 设置键值对到Properties对象
-
store 将Properties中的键值对存储到配置文件,在idea中,保存信息到配置文件,如果含有中文,会存储为unicode码
package com.sofwin.config;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;
/**
* @packageName: com.sofwin.config
* @author: wentao
* @date: 2022/11/8 22:41
* @version: 1.0
* @email 1660420659@qq.com
* @description: TODO
*/
public class Properties02 {
public static void main(String[]args) throws IOException {
//1.使用Properties类来读取jdbc.properties文件
Properties properties = new Properties();
//2.加载指定的配置文件
properties.load(new FileReader("D:\\springboot\\springbootTest\\springboot_01_01test\\src\\main\\resources\\jdbc.properties"));
//3.显示到控制台
properties.list(System.out);
//4.根据key获取值
String userName = properties.getProperty("jdbc.username");
String pwd = properties.getProperty("jdbc.pwd");
System.out.println("userName:"+userName);
System.out.println("pwd:"+pwd);
//5. 添加/修改键值对 如果没有key就是创建 如果有key 就是相当于替换(修改)
properties.setProperty("wt","123456");
properties.setProperty("lkh","李科技");
//6.将键值对保存起来
//第二个null 代表一个注释 如果有的话直接会在properties文件最上面写上注释
properties.store(new FileOutputStream("D:\\springboot\\springbootTest\\springboot_01_01test\\src\\main\\resources\\jdbc.properties"),null);
}
}