新javaIO流详解+图解(韩顺平老师)
目录文件IO流原理及流的分类节点流和处理流输入流(InputStream,Reader)输出流(OutputStream,Writer)Properties类文件的基础知识什么是文件文件,对我们来说并不陌生,文件是保存数据的地方,比如大家用的word文档,txt文件,excel文件。它既可以保存一张图片,也可以保持视频,声音文件流文件在程序中以流的形式来操作的流:数据在数据源(文件)和程序(内存)
文章目录
- 前言
-
-
- 文件的基础知识
- 创建文件
- 目录操作
- IO流原理和分类
- FileInputStream (字节输入流)
- FileOutputStream(字节输出流)
- 文件拷贝
- 文件字符流说明
- FileReader
- FileWriter
- 节点流处理流
- 处理流设计模型
- BufferedReader
- BufferedWriter
- Buffered拷贝
- Buffed字节处理流
- 字节处理流拷贝文件
- 对象处理流
- ObjectOutputStream
- ObjectInputStream
- 对象处理流使用细节
- 标准输入输出流
- 乱码引出转换流
- InputStreamReader
- OutputStreamWriter
- PrintStream
- PrintWriter
- 配置文件引出Properties
-
前言
本文章包括了大部分java IO流的重要知识,是基于韩顺平老师的讲解,十分详细且易懂,主要包括:
- 文件
- IO流原理及流的分类
- 节点流和处理流
- 输入流(InputStream,Reader)
- 输出流(OutputStream,Writer)
- Properties类
。
文件的基础知识
-
什么是文件
-
文件,对我们来说并不陌生,文件是保存数据的地方,比如大家用的word文档,txt文件,excel文件。它既可以保存一张图片,也可以保持视频,声音
-
文件流
文件在程序中以流的形式来操作的
流:数据在数据源(文件)和程序(内存)之间经历的路径
输入流:数据从数据源(文件)到程序(内存)的路径
输出流:数据从程序(内存)到数据源(文件)的路径
创建文件
-
创建文件对象相关构造器和方法
-
相关方法
- 1. new File(String pathname)//根据路径构建一个File对象 new File(File parent,String child)//根据父目录文件+子路径构建 new File(String parent,String child)//根据父目录+子路径构建 createNewFile//创建新文件
-
-
创建文件对象相关构造器和方法
package IO_file;
import org.junit.jupiter.api.Test;
import java.io.File;
import java.io.IOException;
//创建文件
public class FileCreate {
public static void main(String[] args) {
}
//方式1:new File( String pathname)
@Test
public void create01(){
String filePath ="C:\\news1.txt";
File file = new File(filePath);
try {
file.createNewFile();
System.out.println("文件创建成功");
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
//方式2:new File(File parent,String child)//根据父目录文件+子路径构建
//c:\\news2.txt
public void create02(){
File parentfile = new File("c:\\");
String childfile ="news.txt";
//这里file在java程序中只是一个java对象
//只有执行了createNewFile方法,才会正在地在磁盘创建该文件
File file = new File(parentfile,childfile);
try {
file.createNewFile();
System.out.println("创建成功");
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
//方法3:new File(String parent,String child)//根据父目录+子路径构建
public void create03(){
String parentpath = "c:\\";
String childname ="news3.txt";
File file = new File(parentpath,childname);
try {
file.createNewFile();
System.out.println("创建成功!");
} catch (IOException e) {
e.printStackTrace();
}
}
}
目录操作
常见地文件操作
-
目录的操作和文件删除
mkdir创建一级目录,mkdirs创建多级目录,delete删除空目录或文件
-
案例演示
- //判断 c:\news1.txt 是否存在,如果存在就删除
- //判断 c:\demo02目录是否存在,存在就删除,否则就提示不存在
- //判断 c:\demo\a\b\c 目录是否存在,如果存在就提示存在,否则就创建
package IO_file;
import org.junit.jupiter.api.Test;
import java.io.File;
public class Directory_ {
public static void main(String[] args) {
//
}
//判断 c:\\news1.txt 是否存在,如果存在就删除
@Test
public void m1(){
String filePath = "c:\\news1.txt";
File file = new File(filePath);
if(file.exists()){
if(file.delete()){
System.out.println(filePath+"删除成功");
}
else{
System.out.println(filePath+"删除失败");
}
}else{
System.out.println("该文件不存在...");
}
}
//判断 c:\\demo02目录是否存在,存在就删除,否则就提示不存在
//这里我们需要体会到,在java编程中,目录也被当成文件
@Test
public void m2(){
String filePath = "c:\\demo02";
File file = new File(filePath);
if(file.exists()){
if(file.delete()){
System.out.println(filePath+"删除成功");
}
else{
System.out.println(filePath+"删除失败");
}
}else{
System.out.println("该文件不存在...");
}
}
//判断 c:\\demo\\a\\b\\c 目录是否存在,如果存在就提示存在,否则就创建
@Test
public void m3(){
String directionPath = "c:\\demo\\a\\b\\c";
File file = new File(directionPath);
if(file.exists()) {
System.out.println(directionPath+"该目录已经存在");
}
else{
if(file.mkdirs()) {//创建一级目录用mkdir(),创建多久目录用mkdirs();
System.out.println(directionPath+"创建成功");
}
else
System.out.println(directionPath+"创建失败");
}
}
}
IO流原理和分类
-
Java IO流原理
-
I/O是Input/Output的缩写,I/O技术是非常实用的技术,用于处理数据传输。如读/写文件,网络通讯等。
-
Java程序中,对于数据的输入/输出操作以"流(stream)"的方式进行。
-
java.io包下提供了各种"流"类和接口,用以获取不同种类的数据,并通过方法输入或输出数据
-
输入input:读取外部数据(磁盘,光盘等存储设备的数据)到程序(内存)中。
-
输出output:将程序(内存)数据输出到磁盘,光盘等存储设备中
-
-
流的分类
-
按操作数据单位不同分为:字节流(8 bit),字符流(按字符)
-
按数据流的流向不同分为:输入流,输出流
-
按流的角色的不同分为:节点流,处理流/包装流
抽象基类 字节流 字符流 输入流 InputStream Reader 输出流 OutputStream Writer - java中IO流共涉及40多个类,实际上非常规则,都是从如上4个抽象基类派生的。
- 由这4个类派生出来的子类名称都是以其父类名为子类名后缀
-
-
IO流体系图-常用的类
- IO流体系图
- 文件VS流
FileInputStream (字节输入流)
IO流体系图-常用的类
- InputStream抽象类是所有类字节输入流的超类
- InputStream常用的子类
- FileInputStream:文件输入流
- BufferedInputStream:缓存字节输入流
- ObjectInputStream:对象字节输入流
- FileInputStream介绍
- FileInputStream应用实例
- 创建FileInputStream对象,用read()方法读取文件数据
/*
*单个字节读取,效率低
* ->使用read()
*/
@Test
public void readFile01(){
String filePath = "c:\\hello.txt";
int readData=0;
FileInputStream fileInputStream=null;
try {
//创建fileInputStream对象,用于读取文件
fileInputStream = new FileInputStream(filePath);
//从该输入流读取一个字节的数据。如果没有输入可用,此方法将阻止
//如果返回-1,表示读取完毕
while((readData=fileInputStream.read())!=-1){
System.out.print((char)readData); //打印是int转换为char显示
} //若打印汉字会出现乱码,一个汉字三个字节,而这是一个字节一个字节打印
} catch (IOException e) {
e.printStackTrace();
}finally {
//关闭文件流,释放资源
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
-
创建FileInputStream对象,用read(byte[] b)方法读取文件
/* *使用read(byte[] b) */ @Test public void readFile02(){ String filePath = "c:\\hello.txt"; int readLen=0; //字节数组 byte[] buf = new byte[8];//一次读8个字节 FileInputStream fileInputStream=null; try { //创建fileInputStream对象,用于读取文件 fileInputStream = new FileInputStream(filePath); //从该输入流读取最多b,length字节的数据到字节数组。此方法将阻塞,直到某些输入可用 //如果返回-1,表示读取完毕 //如果读取正常,返回实际读取的字节数 while((readLen=fileInputStream.read(buf))!=-1){ System.out.print(new String(buf,0, readLen)); //打印是int转换为String显示 } //若打印汉字会出现乱码,一个汉字三个字节,而这是一个字节一个字节打印 } catch (IOException e) { e.printStackTrace(); }finally { //关闭文件流,释放资源 try { fileInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } }
FileOutputStream(字节输出流)
IO流体系图-常用的类
-
FileOutputStream应用实例
要求:请使用FileOutStream在a.txt文件,中写入"hello,world",如果文件不存在,会创建文件
演示使用FileOutStream 将数据写到文件中
public class FileOutputStream01 { public static void main(String[] args) { } @Test /* * 演示使用FileOutStream 将数据写到文件中 * 如果文件不存在,则创建该文件 */ public void writeFile(){ //创建FileOutStream对象 //说明 //1.new FileOutputStream(filePath)创建方式,当写入内容是,会覆盖原来内容 //2.new FileOutputStream(filePath,true)创建方式,当写入内容是,是追加到文件后面 String filePath="c:\\a.txt"; FileOutputStream fileOutputStream = null; try { //得到FileOutputStream对象 fileOutputStream = new FileOutputStream(filePath,true); //写人一个字节 // fileOutputStream.write('a'); //写入字符串 String str ="hello world"; //str.getBytes()可以把字符串->字节数组 // fileOutputStream.write(str.getBytes()); /* write(byte[]b, int off,int len)将len字节从位于偏移量off的指定数组 */ fileOutputStream.write(str.getBytes(),0,3); } catch (IOException e) { e.printStackTrace(); }finally { try { fileOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } }
文件拷贝
-
实例分析
将c:\JAVA.jpg拷贝到C:\web\JAVA.jpg
分析:我们需要将该JAVA.jpg文件先输入到程序,然后在从程序中输出到磁盘中,包含FileInputStream,和FileInputStream使用
package IO_Outputstream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileCopy {
public static void main(String[] args) {
//完成文件拷贝,将c:\JAVA.jpg拷贝到C:\web\JAVA.jpg
//思路分析
//1. 创建文件的输入流,将文件读入到程序
//2. 创建文件的输出流,将读到的文件数据,写入到指定的文件
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
String srcFilePath = "c:\\JAVA.jpg";//定义输出路径
String destFilePath="C:\\web\\JAVA.jpg";//定义输入路径
try {
fileInputStream = new FileInputStream(srcFilePath);
fileOutputStream= new FileOutputStream(destFilePath);
//定义一个字节数组,提高读取效果
byte[] buf = new byte[1024];
int readlen=0;
while((readlen=fileInputStream.read(buf))!=-1)
{
//读取到后,就写入到文件 通过fileOutputStream
//即,一边读,一边写
fileOutputStream.write(buf,0,readlen);//一定要用这个方法,提高输出速度
}
System.out.println("拷贝成功");
} catch (IOException e) {
e.printStackTrace();
}finally{
//关闭输出流和输入流
if(fileInputStream!=null){
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if ((fileOutputStream!=null)){
try {
fileOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
文件字符流说明
-
FileReader和FileWriter介绍
FileReader和FileWriter是字符输入流,即字符来操作io
-
FileReader相关方法:
- new FileReader(File/String)
- read:每次读取单个字符,返回该字符,如果到文件末尾返回-1
- read(char[]):批量读取多个字符到数组,返回读取到字符数,如果到文件末尾返回-1
-
相关API
- new String(char[]):将char[]转换成String
- new String(char[],off,len):将char[]的指定部分转换成String
-
FileWriter常用方法
- new FileWriter(File/String):覆盖模式,相当于流的指针在首端
- new FileWriter(File/String,true):追加模式,相当于流的指针在尾端
- write(int):写人单个字符
- write(char[]):写入指定数组
- write(char[],off,len):写入指定数组的指定部分
- write(String):写入整个字符串
- write(String,off,len):写入指定字符串的指定部分
- 相关 API: String类:toCharArray:将String转换为char[]
-
注意:
FileWriter使用后,必须关闭(close)或刷新(flush),否则写入不到指定文件
FileReader
-
FileReader和FileWriter
要求:
- 使用FileReader从story.txt读取内容,并显示
- 方法1,单个字符读取,用read()
- 使用FileReader从story.txt读取内容,并显示
-
/*
*单个字符读取文件
*/
@Test
public void readFile01(){
System.out.println("第二种");
String filePath="c:\\story.txt";
// 1.创建FileReader对象
FileReader fileReader = null;
int data=' ';
try {
fileReader = new FileReader(filePath);
//循环读取 使用read,单个字符读取
while((data=fileReader.read())!=-1){
System.out.print((char) data);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
if (fileReader!=null){
try {
fileReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
-
方法2,使用字符数组读取文件 read(buf)
/* *字符数组读取文件 */ @Test public void readFile02(){ String filePath="c:\\story.txt"; // 1.创建FileReader对象 FileReader fileReader = null; int readLen = 0; char[] buf = new char[8]; try { fileReader = new FileReader(filePath); //循环读取 使用read,单个字符读取 while((readLen=fileReader.read(buf))!=-1){ System.out.print(new String(buf,0,readLen)); } } catch (IOException e) { e.printStackTrace(); }finally { if (fileReader!=null){ try { fileReader.close(); } catch (IOException e) { e.printStackTrace(); } } } }
FileWriter
-
案例:使用FileWriter将"风雨之后,定见彩虹"写入note.txt文件中,注意细节
package I0_Writer; import java.io.FileWriter; import java.io.IOException; public class FileWriter_ { public static void main(String[] args) { String FilePath="c:\\note.txt"; //创建FileWriter对象 FileWriter filewriter = null; char[] chars = {'a','b','c'}; try { filewriter = new FileWriter(FilePath); // 1. write(int):写人单个字符 filewriter.write('H'); // 2. write(char[]):写入指定数组 filewriter.write(chars); // 3. write(char[],off,len):写入指定数组的指定部分 filewriter.write("琳琳我".toCharArray(),0,3); // 4. write(String):写入整个字符串 filewriter.write("风雨之后见彩虹"); filewriter.write(" 你好北京"); // 5. write(String,off,len):写入指定字符串的指定部分 filewriter.write("上海北京",0,2); //在数据量大的情况下,用循环操作 } catch (IOException e) { e.printStackTrace(); }finally{ //对于FileWriter,一定要关闭流,或者flush才能正在的把数据写入到文件 try { // filewriter.flush(); //close等于fulsh()+关闭 filewriter.close(); } catch (IOException e) { e.printStackTrace(); } } } }
-
节点流处理流
-
基本介绍
- 节点流可以从一个特定的数据源读写数据,如FileReader,FileWriter, 固定的,灵活性不足
- 文件—>程序(通过节点流)
- 处理流也叫包装流,是"连接"在已存在的流(节点流或处理流)之上,为程序提供更强大的读写功能,如BufferedReader,BufferedWriter 可以对节点流进行包装,也更加灵活,可以是文件,也可以是其他数据源
- 节点流可以从一个特定的数据源读写数据,如FileReader,FileWriter, 固定的,灵活性不足
-
节点流和处理流一览图
图
-
BufferedReader/BufferedWriter
- BufferReader类中,有属性Reader,即可以封装一个节点流,该节点流可以是任意的,只要是Reader子类
- BufferWriter类中和BufferReader类似。
处理流设计模型
- 节点流和处理流的区别和联系
- 节点流是底层流,低级流,直接跟数据源相接
- 处理流(包装流)包装节点流,即可以消除不同节点流的实现差异,也可以提供更方便的方法来完成输入输出(源码理解)
- 处理流也叫包装流对节点流进行包装,使用了修饰器设计模式,不会直接与数据源相连(模拟修饰器设计模式)
- 处理流的功能主要体现在以下两个方面
- 性能的提高:主要以增加缓冲的方式来提高输入输出的效率
- 操作的便捷:处理流可能提供了一系列便捷的方法来一次输入输出大批量的数据,使用更加灵活方便
BufferedReader
- 处理流-BufferedReader和BufferedWriter
- BufferedReader和BufferedWriter属于字符流,是按照字符来读取数据的(最好用文本文件)
- 关闭处理流,只需要关闭外层节点流
- 应用案例
- 使用BufferedReader读取文本文件,并显示在控制台
package IO_reader;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
/*
演示bufferedreader应用
*/
public class BufferedReader_ {
public static void main(String[] args) throws IOException {
String filePath="c:\\ab.txt";
//创建bufferedReader
BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
//读取
String line;//按行读取,效率高
//说明
//1.bufferedReader.readLine() 是按行读取文件
//2.当返回null时,表示文件读取完毕
while((line=bufferedReader.readLine())!=null){
System.out.println(line);
}
//关闭流,这里注意,只需要关闭BufferedReader,因为底层会自动的去关闭节点流
bufferedReader.close();
}
}
BufferedWriter
- 应用案例
2. 使用BufferedWriter 将"hello,xxx"写入到文件中
public class BufferedWrite1 {
public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
String filePath="e:\\ok.txt";
//创建BufferWritered
//说明
//1. new FileWriter(filePath,true) 表示以追加的方式写人
//2.new FileWriter(filePath) 表示以覆盖的方式写入
new BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath));
//new BufferedWriter
bufferedWriter.write("hello, 韩顺的");
bufferedWriter.newLine();//插入一个和系统相关的换行
bufferedWriter.write("hello, 韩顺的");
bufferedWriter.newLine();//插入一个和系统相关的换行
bufferedWriter.write("hello, 韩顺的");
//说明:关闭外层流即可,传入的 new FileWriter(filePath),会在底层流关闭
bufferedWriter.close();
}
}
Buffered拷贝
- 应用案例
-
综合使用BufferedReader和BufferedWriter完成文本文件的拷贝
public class BufferedCopy_(){ public static void main(String[] args){ //说明 //1.BufferedReader 和BufferedWriter 是按照字符读取 //2.不要用去操作二进制文件,可能造成文件损失 String srcFilePath = "e:\\a.java"; String destFilePath = "e:\\a2.java"; BufferedReader br = null; BufferedWriter bw = null; String line; try{ br = new BufferedReader(new FileReader(srcFilePath)); bw = new BufferedWriter(new FileWriter(destFilePath)); //说明:readLine 读取一行内容,但是没有换行 while((line = br.readLine())! = null){ //没读取一行就写入 bw.write(line); //插入一个换行 bw.newLine(); } System.out.println("拷贝完成"); } catch(IOException e){ e.printStackTrace(); } finally{ //关闭流 try{ if(br!=null){ br.close(); } if(bw!=null){ bw.close(); } }catch(IOExcption e){ e.printStackTrace(); } } } }
Buffed字节处理流
- 处理流-BufferedInputStream和BufferedOutputStream
- BufferedOutputStream是字节流,实现缓冲的输出流,可以将多个字节写入底层输出流中,而不必对每次字节写入调用底层系统
- BufferedInputStream是字节流,在创建BufferedInputStream时,会创建一个内部缓冲区数组
字节处理流拷贝文件
-
应用案例
- 要求编写完成图片,音乐的拷贝,使用Buffered…流(图片音乐是二进制)
package IO_Outputstream; import java.io.*; /* 演示BufferedOutputStream和BufferedOutputStream 字节流使用他们可以完成二进制文件拷贝 也可以操作文本文件 */ public class BufferedCopy02 { public static void main(String[] args) { String srcFilePath="c:\\JAVA.jpg"; String destFilePath="c:\\web\\wen.jpg"; //创建BufferedOutputStream对象和BufferedInputStream对象 BufferedInputStream bis = null; BufferedOutputStream bos = null; try { //因为FileInputStream是InputStream的子类 bos= new BufferedOutputStream(new FileOutputStream(destFilePath)); bis=new BufferedInputStream(new FileInputStream(srcFilePath)); //循环读取文件,并写入到destFilePath byte[] bytes = new byte[1024]; int len = 0; while ((len= bis.read(bytes))!=-1){ bos.write(bytes,0,len); } System.out.println("拷贝成功"); } catch (IOException e) { e.printStackTrace(); }finally{ //关闭流,关闭外层流 if(bis!=null){ try { bis.close(); } catch (IOException e) { e.printStackTrace(); } } if(bos!=null){ try { bos.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
- 处理流-BufferedInputStream和BufferedOutputStream
对象处理流
-
对象流-ObjectInputStream和ObjectOutputStream (仍然是处理流)
- 看一个需求
- 将int num = 100 这个 int 数据保存到文件中,注意不是100数字,而是int 100,并且,能够从文件中直接恢复int 100
- 将Dog dog = new Dog(“小黄”,3)这个dog对象保存到文件中,并且能够从文件中恢复
- 上面的要求,就是能够将基本数据类型或者对象进行序列化和反序列化操作
- 序列化和反序列化
- 序列化就是保存数据时,保存数据的值和数据类型
- 反序列化就是恢复数据时,恢复数据的值和数据类型
- 需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之一:
- Serializable //标记接口,推荐!!,里面无任何方法
- Externalizable //该接口有方法需要实现,推荐使用Seralizable接口
-
基本介绍
- 功能:提供了对基本类型或者对象类型的序列化和反序列化的方法
- ObjectOutputStream提供序列化功能
- ObjectInputStream提供反序列功能
ObjectOutputStream
- 应用案例
-
使用ObjectOutputStream序列化基本数据类型和一个Dog对象(name,age),并保存到data.dat
package IO_Inputstream; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; import java.io.Serializable; /* 演示ObjectOutputStream的使用,完成数据的序列化 */ public class ObjectOutputStream_ { public static void main(String[] args) throws IOException { //序列化后,保存的文件格式,不是纯文本而是按照他的格式来保存 String filePath="c:\\data.dat"; ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath)); //序列化数据到c:\\data.dat oos.write(100);//int->Integer(实现了Serialzable) oos.writeBoolean(true);//boolean->Boolean(实现了Serialzable) oos.writeChar('a');//char->Character (实现了Serialzable) oos.writeDouble(9.5);//double->Double(实现了Serialzable) oos.writeUTF("xxx");//String(实现了Serialzable) //保存一个dog对象 oos.writeObject(new dog("旺财",12)); oos.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; } }
ObjectInputStream
-
应用案例
- 使用ObjectInputStream读取data.dat并反序列化恢复数据
package IO_Inputstream; import IO_Outputstream.dog; import java.io.FileInputStream; import java.io.IOException; import java.io.ObjectInputStream; public class ObjectInputStream_ { public static void main(String[] args) throws IOException, ClassNotFoundException { //序列化后,保存的文件格式,不是纯文本而是按照他的格式来保存 String filePath="c:\\data.dat"; ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath)); //读取 //1.读取反序列化的顺序需要和你保存数据序列化的顺序一致 //2.否则会出现异常 System.out.println(ois.readInt()); System.out.println(ois.readBoolean()); System.out.println(ois.readChar()); System.out.println(ois.readDouble()); System.out.println(ois.readUTF()); Object dog = ois.readObject(); System.out.println(dog.getClass()); System.out.println(dog);//底层object->Dog //特别重要的细节 //1.如果我们希望调用Dog的方法,需要向下转型 //2.需要我们将Dog类的定义,拷贝到可以引用的位置 dog dog2 = (dog) dog; System.out.println(dog2.getName()); //关闭流,关闭外层流即可 ois.close(); } }
dog类
package IO_Outputstream; import java.io.Serializable; public class dog implements Serializable { private String name; private int age; public dog(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } @Override public String toString() { return "dog{" + "name='" + name + '\'' + ", age=" + age + '}'; } }
-
对象处理流使用细节
- 注意事项和细节说明
- 读写顺序要一致
- 要求实现序列化或反序列化对象,需要实现Serializable
- 序列化的类中建议添加SerialVersionUID,为了提高版本兼容性
- 序列化对象时,默认将里面所有属性都进行序列化,但除了static或transient修饰的成员
- 序列化对象时,要求里面属性的类型也需要实现序列化接口
- 序列化具备可继承性,也就是如果某类已经实现了序列化,则它的所有子类也默认实现了序列化
标准输入输出流
-
标准输入输出流
- 介绍
类型 默认设备 System.in InputStream 键盘 System.out PrintStream 显示器
package standard;
public class InputAndOutput {
public static void main(String[] args) {
//System类的public final static InputStream in = null;
//System.in 编译类型 InputStream
//System.in 运行类型 BufferedInputStream
//表示的是标准输入 键盘
System.out.println(System.in.getClass());
//1.System.out public final static Printstream out = null;
//2.编译类型 PrintStream
//3.运行类型PrintStream
//4.表示标准输出 显示器
System.out.println(System.out.getClass());
}
}
乱码引出转换流
- 转换流-InputStreamReader和OutputStreamWriter
- 先看一个文件乱码,引出学习转换流必要性
package transformation;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class CodeQuestion {
public static void main(String[] args) throws IOException {
//1.创建字符输入流BufferedReader[处理流]
//2使用BufferedReader 对象读取a.txt
//3.默认情况下,读取文件是按照utf-8编码
String filePath = "c:\\a.txt";
BufferedReader br = new BufferedReader(new FileReader(filePath));
String s = br.readLine();
System.out.println("读取到的内容:"+s);
br.close();
}
}
如果将a.txt转换为ANSI,则会出现乱码
InputStreamReader
-
转换流-InputStreamReader和OutputStreamWriter
- 介绍
- InputStreamReader:Reader的子类,可以将InputStream(字节流)包装成Reader(字符流)
- OutputStreamWriter:Writer的子类,实现将OutputStream(字节流)包装成Writer(字符流)
- 当处理纯文本数据时,如果使用字符流效率更高,并且可以有效解决中文问题,所以建议将字节流转换为字符流
- 可以再使用时指定编码格式比如(utf-8,gbk,gb2312,ISO8859-1等)
- 介绍
-
应用案例
- 编码将字节流FileInputStream包装成字符流InputStreamReader,对文件进行读取按照utf-8格式,进而在包装成BufferedReader
package transformation; import java.io.*; /* *演示使用InputStreamReader 转换流解决中文乱码问题 * 将字节流FileInputStream 转换成字符流InputStreamReader,指定编码gbk/utf-8 */ public class InputStreamReader_ { public static void main(String[] args) throws IOException { String filePath="c:\\a.txt"; //1.把FileInputStream转成 InputStreamReader //InputStreamReader isr = new InputStreamReader(new FileInputStream(filePath),"gbk"); //3.把InputStreamReader传入BufferedReader //BufferedReader br = new BufferedReader(isr); //将2和3合在一起 BufferedReader br = new BufferedReader(new InputStreamReader new FileInputStream(filePath),"gbk")); //4.读取 String s = br.readLine(); System.out.println("读取内容="+s); //5.关闭外层流 br.close(); } }
OutputStreamWriter
-
应用案例
- 编程将字节流FileOutputStream包装成字符流OutputStreamWriter,对文件进行写入按照gbk
package transformation; import java.io.*; public class OutputStreamWriter_ { public static void main(String[] args) throws IOException { String filePath="c:\\a.txt"; String charset="gbk"; OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(filePath),charset); osw.write("问进ie"); osw.close(); System.out.println("按照"+charset+"保存文件成功"); } }
PrintStream
-
打印流 PrintStream(字节流)和PrintWriter(字符流)
- 应用实例,打印流只有输出流,没有输入流
/* PrintStream是字节打印流/输出流 */ package PrintStream_; import java.io.IOException; import java.io.PrintStream; public class PrintStream01 { public static void main(String[] args) throws IOException { PrintStream out = System.out; //默认情况下,PrintStream输出数据的位置是标准输出,即显示器 out.print("john,hello"); out.write("问进杰".getBytes()); out.close(); //我们可以去修改打印流输出的位置/设备 //1.输出修改成到"c:\\f1.txt"; //2."hello,阿松大就会输出到c:\\f1.txt" System.setOut(new PrintStream("c:\\f1.txt")); System.out.println("hello,阿松大"); } }
PrintWriter
package PrintStream_; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; public class PrintWriter_ { public static void main(String[] args) throws IOException { PrintWriter printWriter = new PrintWriter(new FileWriter("c:\\f2.txt")); printWriter.print("hi 北京"); printWriter.close();//flush+关闭流,才会将数据写入到文件 } }
配置文件引出Properties
-
Properties类
- 看一个需求
如下一个配置文件mysql.properties
ip=192.168.0.13
user=root
pwd=12345
请问编程读取ip,user和pwd的值是多少
- 分析
- 传统方法
- 使用Properties类可以方便实现
-
传统方法
package properties; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; public class Properties01 { public static void main(String[] args) throws IOException { //读取mysql.properties文件,并且得到ip,user和pwd BufferedReader br= new BufferedReader(new FileReader("src\\mysql.properties")); String line =""; while((line=br.readLine())!=null){//循环读取 String[] splits = line.split("="); System.out.println(splits[0]+"值是"+splits[1]); }/// br.close(); } }
-
基本介绍
-
专门用于读写配置文件的集合类
配置文件的格式:
键=值
键=值
-
注意:键值对不需要空格,值不需要用引号引起来。默认类型是String
-
Properties的常用方法
- load:加载配置文件的键值对到Properties对象
- list:将数据显示到指定设备
- getProperty(key):根据键获取值
- setProperty(key,value):设置键值对到Properties对象
- store:将Properties中的键值对存储到配置文件,在idea中,保存信息到配置文件,如果含有中文,会存储为unicode码
-
-
应用案例
-
使用Properties类完成对mysql.properties的读取
package properties; import java.io.FileReader; import java.io.IOException; import java.util.Properties; public class Properties02 { public static void main(String[] args) throws IOException { //使用Properties类来读取mysql.properties 文件 //1.创建Properties对象 Properties properties = new Properties(); //2.加载指定配置文件 properties.load(new FileReader("src\\mysql.properties")); //3.把k-v显示控制台 properties.list(System.out); //4.根据key获取对应的值 String user = properties.getProperty("user"); String pwd = properties.getProperty("pwd"); System.out.println("用户名="+user); System.out.println("密码是="+pwd); } }
-
使用Properties类添加key-val到新文件mysql2.properties中
package properties;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
public class Properties03 {
public static void main(String[] args) throws IOException {
//使用Properties类来创建配置文件,修改配置文件内容
Properties properties = new Properties();
//创建
properties.setProperty("charset","utf8");
properties.setProperty("user","汤姆");//保存是中文的unicode码值
properties.setProperty("pwd","abc111");
//将k-v存储文件中即可
properties.store(new FileOutputStream("src\\mysql2.properties"),null);
System.out.println("保存配置成功");
}
}
- 使用Properties类完成对mysql.properties的读取,并修改某个key-val
package properties;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
public class Properties03 {
public static void main(String[] args) throws IOException {
//使用Properties类来创建配置文件,修改配置文件内容
Properties properties = new Properties();
//创建
//1.如果该文件没有key就是创建
//2.如果该文件有key就是修改替换
properties.setProperty("charset","utf8");
properties.setProperty("user","汤姆");//保存是中文的unicode码值
properties.setProperty("pwd","88888");//修改密码
//将k-v存储文件中即可
properties.store(new FileOutputStream("src\\mysql2.properties"),null);
System.out.println("保存配置成功");
}
}

GitCode 天启AI是一款由 GitCode 团队打造的智能助手,基于先进的LLM(大语言模型)与多智能体 Agent 技术构建,致力于为用户提供高效、智能、多模态的创作与开发支持。它不仅支持自然语言对话,还具备处理文件、生成 PPT、撰写分析报告、开发 Web 应用等多项能力,真正做到“一句话,让 Al帮你完成复杂任务”。
更多推荐
所有评论(0)