欢迎大家来到IT世界,在知识的湖畔探索吧!
1.文件基础知识
什么是文件?
文件,我们并不陌生。文件是保存数据的地方。比如大家经常使用的word文档,txt文件,excel文件等,都是文件。它既可以保存一张图片,也可以保存声音、视频……
- 文件流
- 文件在程序中是以流的形式来操作的:
流:数据在数据源(文件)和程序(内存)之间经历的路径
输入流:数据从数据源(文件)到程序(内存)之间的路径
输出流:数据从程序(内存)到数据源(文件)之间的路径
2.常用的文件操作
2.1创建文件
- 创建文件对象相关构造器和方法
- 相关方法:
- new File(String pathname)//根据路径构建一个File对象new File(File patent,String child)//根据父目录文件+子路径构建 new File(String parent,String child)//根据父目录+子路径构建
例子:应用案例演示:FileCreate
package li.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) { } //方式一 new File(String pathname)//根据路径构建一个File对象 @Test public void creat01() { String filePath = "d:\\news1.txt"; File file = new File(filePath);//在内存中创建一个File对象 try { file.createNewFile();//创建文件 System.out.println("文件创建成功"); } catch (IOException e) { e.printStackTrace(); } } //方式二 new File(File patent,String child)//根据父目录文件+子路径构建 //例如:d:\\news.txt,父目录文件就是 d:\\ @Test public void creat02() { File parenFile = new File("d:\\"); String fileName = "news2.txt"; //这里的file对象,在java程序中只是一个java对象而已 //只有执行了createNewFile方法,才会真正地在磁盘创建文件 File file = new File(parenFile, fileName); try { file.createNewFile();//创建文件 System.out.println("创建成功~"); } catch (IOException e) { e.printStackTrace(); } } //方式三 new File(String parent,String child)//根据父目录+子路径构建 @Test public void creat03() { String parentPath = "d:\\"; //这里的两个 \\,其中有一个是转义符号,或者直接用 d:/ String filePath = "news3.txt"; File file = new File(parentPath, filePath); try { file.createNewFile(); System.out.println("创建文件成功"); } catch (IOException e) { e.printStackTrace(); } }}
欢迎大家来到IT世界,在知识的湖畔探索吧!
2.2获取文件的相关信息
- getName()
- getAbsolutePath()
- getParent()
- length()
- exists()
- isFile()
- isDirectory()
例子:
欢迎大家来到IT世界,在知识的湖畔探索吧!package li.io.file; import org.junit.jupiter.api.Test; import java.io.File; public class FileInformation { public static void main(String[] args) { } //获取文件的信息 @Test public void info() { //先创建文件对象 File file = new File("d:\\news1.txt"); //调用相应方法,得到对应信息 //文件名字-getName() System.out.println("文件名字="+file.getName());//文件名字=news1.txt //文件的绝对路径-getAbsolutePath() System.out.println("文件的绝对路径="+file.getAbsolutePath());//文件的绝对路径=d:\news1.txt //文件的父级目录-getParentFile() System.out.println("文件的父级目录="+file.getParentFile());//文件的父级目录=d:\ //文件的大小(字节)-length() System.out.println("文件的大小(字节)="+file.length());//文件的大小(字节)=12 Hello World! //文件是否存在-exists() System.out.println("文件是否存在="+file.exists());//文件是否存在=true //是否为文件-isFile() System.out.println("是否为文件="+file.isFile());//是否为文件=true //是否为目录-isDirectory() System.out.println("是否为目录="+file.isDirectory());//是否为目录=false }}
2.3目录的操作和文件删除
- mkdir():创建一级目录
- mkdirs():创建多级目录
- delete():删除空目录或者文件
例子:
package li.io.file; import org.junit.jupiter.api.Test; import java.io.File; public class Directory_ { public static void main(String[] args) { } //判断 d:\\news1.txt是否存在,如果存在就删除 @Test public void m1() { String filePath = "d:\\news1.txt"; File file = new File(filePath); if (file.exists()) { if (file.delete()) { System.out.println(filePath + "删除成功"); } else { System.out.println("删除失败..."); } } else { System.out.println("该文件不存在..."); } } //判断 d:\\demo02 是否存在,存在就删除,否则就提示不存在 //这里我们需要体会到,在java中,目录也被当做文件 @Test public void m2() { String filePath = "d:\\demo02"; File file = new File(filePath); if (file.exists()) { if (file.delete()) { System.out.println(filePath + "删除成功");//d:\demo02删除成功(先在d盘下创建一个名为 demo02的目录) } else { System.out.println("删除失败..."); } } else { System.out.println("该目录不存在..."); } } //判断d:\\demo\\a\\b\\c目录是否存在,如果存在就提示已经存在,否则创建 @Test public void m3() { String directoryPath = "d:\\demo\\a\\b\\c"; File file = new File(directoryPath); if (file.exists()) { System.out.println("该目录已经存在"); } else { if (file.mkdirs()) {//多级目录使用 mkdirs方法,一级目录使用 mkdir System.out.println(directoryPath + "创建成功..."); } else { System.out.println("创建失败..."); } } }}
3.IO流原理及流的分类
3.1Java IO流原理
- I/O是Input/Output的缩写,I/O技术是非常实用的技术,用于处理数据传输。如读/写文件,网络通讯等
- Java程序中,对于数据的输入/输出操作以”流(Stream)“的方式进行
- java.io包下提供了各种“流”类和接口,用以获取不同种类的数据,并通过方法输入或输出数据
- 输入input:读取外部数据(磁盘、光盘等存储设备的数据)到程序(内存)中
- 输出output:将程序(内存)数据输出到磁盘、光盘等存储设备中
3.2流的分类
- 按操作数据单位不同分为:字节流(8bit)、字符流(按字符)
- 字节流适用于二进制文件,字符流适用于文本文件
- 按数据流的流向不同分为:输入流、输出流
- 按流的角色不同分为:节点流、处理流(也叫包装流)
抽象基类 |
字节流 |
字符流 |
输入流 |
InputStream |
Reader |
输出流 |
OutputStream |
Writer |
1)Java的IO流共涉及到40 多个类,实际上非常规则,都是从如上4个抽象基类派生的
InputStream、OutputStream、Reader、Writer都是抽象类,在使用的时候要去创建它们的实现子类
2)由这四个类派生出来的子类名称都是以其父类名作为子类名后缀
4.常用的类
InputStream抽象类是所有类字节输入流的超类
InputStream常用的子类:
- FileInputStream:文件输入流
- BufferedInputStream:缓冲字节输入流
- ObjectInputStream:对象字节输入流
4.1文件字节流输入流-FileInputStream
InputStream抽象类是所有类字节输入流的超类
InputStream常用的子类:
- FileInputStream:文件字节输入流
- BufferedInputStream:缓冲字节输入流
- ObjectInputStream:对象字节输入流
常用方法:
输入流的唯一目的是提供通往数据的通道,程序可以通过这个通道读取文件中的数据。
read方法提供了一个从输入流读取数据的基本方法,read方法的格式如下:
返回值 |
方法 |
说明 |
int |
read( ) |
从输入流中读取数据的下一个字节 |
int |
read(byte[ ] b) |
从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。以整数形式返回读取的字节数。 |
int |
read(byte[ ] b, int off, int len) |
将输入流中最多 len 个数据字节读入 byte 数组。尝试读取 len 个字节,但读取的字节也可能小于该值。以整数形式返回实际读取的字节数。 |
void |
close( ) |
关闭流 |
注:read方法在从输入流中读取源中的数据时,如果到达源的末尾,便会返回-1。
FileInputStream流顺序地读取文件,只要不关闭流,每次调用read方法就顺序的读取源中其余的内容,直至源的末尾或流被关闭。
例子:
欢迎大家来到IT世界,在知识的湖畔探索吧!package li.io.inputstream_; import org.junit.jupiter.api.Test; import java.io.FileInputStream;import java.io.IOException; //演示FileInputStream的使用(字节输入流 文件-->程序)public class FileInputStream_ { public static void main(String[] args) { } /** * 演示读取文件 * read():单个字节的读取,效率较低 */ @Test public void readFile01() { String filePath = "d:\\hello.txt"; int readData = 0; FileInputStream fileInputStream = null; try { //创建了FileInputStream对象,用于读取文件 fileInputStream = new FileInputStream(filePath); //read()方法:从该输入流读取一个字节的数据。 如果没有输入可用,此方法将阻止。 //如果返回-1,则表示达到文件的末尾,表示读取完毕 while ((readData = fileInputStream.read()) != -1) { System.out.print((char) readData);//转成char显示,因此如果文件里面有中文字符(每个中文字符占三个字节),显示的时候就会出现乱码 } } catch (IOException e) { e.printStackTrace(); } finally { //关闭文件流,释放资源 try { fileInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } /** * 使用read(byte[] b)读取文件,提高效率 */ @Test public void readFile02() { String filePath = "d:\\hello.txt"; //字节数组 byte[] buf = new byte[8];//一次读取8个字节 int readLen = 0; FileInputStream fileInputStream = null; try { //创建了FileInputStream对象,用于读取文件 fileInputStream = new FileInputStream(filePath); //read(byte[] b)方法:从该输入流读取最多b.length字节的数据到字节数组。 //如果返回-1,则表示达到文件的末尾,表示读取完毕 //如果读取正常,返回实际读取的字节数 while ((readLen = fileInputStream.read(buf)) != -1) { System.out.print(new String(buf, 0, readLen));//显示 } } catch (IOException e) { e.printStackTrace(); } finally { //关闭文件流,释放资源 try { fileInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } }}
4.2文件字节输出流-FileOutputStream
常用方法:
例子:FileOutputStream应用实例1
要求:请使用FileOutputStream在a.txt文件中写入“hello,world”。如果文件不存在,就先创建文件。
(注意:前提是目录已经存在)
package li.io.outputstream_; import org.junit.jupiter.api.Test; import java.io.FileOutputStream;import java.io.IOException; public class FileOutputStream_ { public static void main(String[] args) { } /** * 演示使用FileOutputStream将数据写到文件中,如果该文件不存在,则先创建文件 */ @Test public void writeFile() { String filePath = "d:\\a.txt"; //创建FileOutputStream对象 FileOutputStream fileOutputStream = null; try { //得到一个FileOutputStream对象 /* 如果是以new FileOutputStream(filePath)的方式创建对象, 则当写入内容时,会覆盖原来的内容 如果是以new FileOutputStream(filePath,true)的方式创建对象, 则当写入内容时,是在旧内容的末尾追加新内容 */ fileOutputStream = new FileOutputStream(filePath,true);//以追加的形式去添加新内容 //写入一个字节 //fileOutputStream.write('H'); //写入字符串 String str = "Hello,Jack!"; //String的getBytes方法可以将字符串转为字符数组 // fileOutputStream.write(str.getBytes()); /* write(byte[] b,int off,int len) 将len长度的字节从位于偏移量off的指定字节输入写入此文件输出流 */ fileOutputStream.write(str.getBytes(), 0, 4); } catch (IOException e) { e.printStackTrace(); } finally { try { fileOutputStream.close(); } catch (IOException e) { e.printStackTrace(); } } }}
追加前:
追加后:
4.2.1FileInputStream&&FileOutputStream
应用实例2:文件拷贝
要求:完成文件拷贝,将d:\Koala.png拷贝到d:\Koala222.png
在完成程序时,为防止读取的文件过大,应该是每读取部分数据,就写入到指定文件,这里使用循环。
package li.io.outputstream_; import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException; public class FileCopy { public static void main(String[] args) { //完成文件拷贝,将c:\\Koala.png拷贝到d:\\ /* 思路分析: 1.创建文件的输入流,将文件读入到程序 2.创建文件的输出流,将读取到的文件数据写入指定的文件 */ String srcFilePath = "d:\\Koala.png"; String destFilePath = "d:\\Koala222.png"; FileInputStream fileInputStream = null; FileOutputStream fileOutputStream = null; try { fileInputStream = new FileInputStream(srcFilePath); fileOutputStream = new FileOutputStream(destFilePath, true); //定义一个字节数组,提高效率 byte[] buf = new byte[1024];//1K int readLen = 0; while ((readLen = fileInputStream.read(buf)) != -1) { //读取到后,就通过 fileOutputStream写入到文件 //即,是一边读一边写) fileOutputStream.write(buf, 0, readLen);//一定要使用这个方法 } System.out.println("拷贝成功~"); } catch (IOException e) { e.printStackTrace(); } finally { //关闭输入流和输出流,释放资源 try { if (fileInputStream != null) { fileInputStream.close(); } if (fileOutputStream != null) { fileOutputStream.close(); } } catch (IOException e) { e.printStackTrace(); } } }}
4.3文件字符流FileReader&FileWriter
FileReader和FileWriter是字符流,即按照字符来操作IO
4.3.1FileReader
FileReader相关方法:
构造方法:
public FileReader(String fileName) throws FileNotFoundException//在给定从中读取数据的文件名的情况下创建一个新 FileReader。//fileName - 要从中读取数据的文件的名称
public FileReader(File file) throws FileNotFoundException//在给定从中读取数据的 File 的情况下创建一个新 FileReader。//file - 要从中读取数据的 File
常用方法:
public int read() throws IOException//每次读取单个字符,返回该字符,如果到文件末尾返回-1 public int read(char[] ) throws IOException//批量读取多个字符到数组,返回读取到的字符数,如果到文件末尾就返回-1 public void close() throws IOException//关闭该流并释放与之关联的所有资源。
相关API:
- new String(char[]):将char[]转换成String
- new String(char[],off,len):将char[]的指定部分转换成String
例子:使用FileReader从story.txt读取内容,并显示
先在d盘根目录下下新建一个story.txt文件,放入内容
package li.io.reader_; import org.junit.jupiter.api.Test; import java.io.FileReader;import java.io.IOException; public class FileReader_ { public static void main(String[] args) { } /** * 1.使用public int read() throws IOException * 每次读取单个字符,返回该字符,如果到文件末尾返回-1 */ @Test public void readerFile01() { String filePath = "d:\\story.txt"; FileReader fileReader = null; int data = 0; //1.创建一个FileReader对象 try { fileReader = new FileReader(filePath); //循环读取 使用reader():每次读取单个字符,返回该字符,如果到文件末尾返回-1 while ((data = fileReader.read()) != -1) { System.out.print((char) data);//将int类型强转为char类型 } } catch (IOException e) { e.printStackTrace(); } finally { try { if (fileReader != null) { fileReader.close(); } } catch (IOException e) { e.printStackTrace(); } } } /** * 2.public int read(char[] ) throws IOException * 批量读取多个字符到数组,返回读取到的字符数,如果到文件末尾就返回-1 */ @Test public void readerFile02() { String filePath = "d:\\story.txt"; FileReader fileReader = null; int readLen = 0; char[] buf = new char[8];//每读取8个字符输出一次 //1.创建一个FileReader对象 try { fileReader = new FileReader(filePath); //循环读取 使用reader(char[]):批量读取多个字符到数组,返回读取到的字符数, // 如果到文件末尾就返回-1 while ((readLen = fileReader.read(buf)) != -1) { System.out.print(new String(buf, 0, readLen));//将char[]的指定部分转换成String } } catch (IOException e) { e.printStackTrace(); } finally { try { if (fileReader != null) { fileReader.close(); } } catch (IOException e) { e.printStackTrace(); } } }}
4.3.2FileWriter
FileWriter常用方法:
构造方法:
public FileWriter(String fileName) throws IOException//根据给定的文件名构造一个 FileWriter 对象。//fileName - 一个字符串,表示与系统有关的文件名。
public FileWriter(String fileName,boolean append) throws IOException//根据给定的文件名以及指示是否附加写入数据的 boolean 值来构造 FileWriter 对象。//fileName - 一个字符串,表示与系统有关的文件名。//append - 一个 boolean 值,如果为 true,则将数据写入文件末尾处,而不是写入文件开始处。//(即覆盖和追加)
public FileWriter(File file) throws IOException//根据给定的 File 对象构造一个 FileWriter 对象。//file - 要写入数据的 File 对象。
常用方法:
public void write(int c)://写入单个字符 public void write(char[] cbuf)://写入字符数组 public abstract void write(char[] cbuf, int off, int len)://写入字符数组的指定部分 public void write(String str)://写入字符串 public void write(String str,int off, int len)://写入字符串的指定部分 public void flush() throws IOException//刷新该流的缓冲。 public void close() throws IOException//关闭此流,但要先刷新它
相关API:String类:toCharArray:将String转换成char[]
注意:FileWriter使用后,必须要关闭(close)或刷新(flush),否则写入不到指定的文件!
例子:
package li.io.writer_; import java.io.FileWriter;import java.io.IOException; public class FileWriter_ { public static void main(String[] args) { String filePath = "d:\\note.txt"; FileWriter fileWriter = null ; char[] chars = {'a','b','c'}; //创建FileWriter对象 try { //覆盖模式写入,覆盖是建立在执行close()之后 fileWriter = new FileWriter(filePath); //public void write(int c):写入单个字符 fileWriter.write('H'); //public void write(char[] cbuf):写入字符数组 fileWriter.write(chars); //public abstract void write(char[] cbuf, int off, int len):写入字符数组的指定部分 fileWriter.write("小猫想睡觉".toCharArray(),0,2); //public void write(String str):写入字符串 fileWriter.write("你好北京~"); //public void write(String str,int off, int len):写入字符串的指定部分 fileWriter.write("上海天津",0,2); } catch (IOException e) { e.printStackTrace(); }finally { //对应FileWriter,一定要关闭流,或者flush才能真正地白数据写入到文件中 try { fileWriter.close(); } catch (IOException e) { e.printStackTrace(); } } }}
在数据量大的情况下,可以使用循环操作
思考:为什么关闭流(close)或者flush才能真正地把数据写入文件中?
IO缓冲流的flush()和close()方法说明及写入文件
fileWriter.close 和fileWriter.flush的区别:
实际上,当我们写好new FileWriter ,进行下一步的操作,将数据写入文本的时候,这时的数据并没有写入文本,而是存在了计算机中的流中。这也是JAVA能够在Windows 系统中调用文本流的作用。而如果在这里我们使用fileWriter.flush,是可以将存储在计算机流中的数据放入fileWriter对象的,但是如果我们之后再想加入数据的时候,也就是说我们将写入数据这句话放在fileWriter.flush之后的话,之后输入的数据就不会放入到note.txt中去。
再说一说fileWriter.close, 我们可以去查询close的定义,很明确的写了 先刷新一次,然后关闭数据流。也就是说close是包含了两步,flush 和close 这两步。flush 刷新后,流可以继续使
4.4节点流和处理流
4.4.1基本介绍
- 节点流可以从一个特定的数据源读写数据,如FileReader、FileWriter
- 数据源就是存放数据的地方,比如文件、数组、字符串、管道等
- 处理流(也叫包装流)是“连接”在已经存在的流(节点流或者处理流)之上,为程序提供更为强大的读写功能,也更加灵活,如BufferedReader、BufferedWriter
- 节点流和处理流的区别和联系:
- 节点流是底层流(低级流),直接和数据源相连接。
- 处理流(包装流)对节点流进行了包装,既可以消除不同节点流的实现差异,也可以提供更方便的方法来完成输入输出。
- 处理流对节点流进行了包装,使用了修饰器的设计模式,不会直接与数据源相连接。
- 处理流特点:
- 1.性能的提高:主要以增加缓冲的方式来提高输入输出的效率。
- 2.操作的便捷:处理流提供了一系列便捷的方法来一次输入输出大批量的数据,使用更加灵活方便。
4.4.2模拟包装流-修饰器模式
Reader_:
package li.io; /** * 模拟包装流的修饰器模式 */public abstract class Reader_ {//抽象类 public void readFile() {} public void readString() {}}
FileReader_:
package li.io; public class FileReader_ extends Reader_ {//模拟节点流 public void readFile() { System.out.println("对文件进行读取..."); }}
StringReader_:
package li.io; public class StringReader_ extends Reader_ {//模拟节点流 public void readString() { System.out.println("读取字符串..."); }}
BufferedReader_:
package li.io; /** * 模拟处理流(包装流) */public class BufferedReader_ extends Reader_ { private Reader_ reader_;//属性是Reader_类型 public BufferedReader_(Reader_ reader_) { this.reader_ = reader_; } public void readFile(){//封装一层 reader_.readFile(); } //让方法更加灵活,比如多次读取文件,或者加缓冲byte[]... public void readFile(int num) { for (int i = 0; i < num; i++) { reader_.readFile(); } } //又如扩展readString方法,例如批量处理字符串数据... public void readString(int num) { for (int i = 0; i < num; i++) { reader_.readString(); } }}
Test_:
package li.io; public class Test_ { public static void main(String[] args) { BufferedReader_ bufferedReader_ = new BufferedReader_(new FileReader_()); bufferedReader_.readFile(3); bufferedReader_.readFile(); BufferedReader_ bufferedReader02_ = new BufferedReader_(new StringReader_()); bufferedReader02_.readString(2); }}
4.4.3字符处理流-BufferedReader&BufferedWriter
- BufferedReader和BufferedWriter属于字符流,是按照字符来读取数据的
- 在关闭流时,只需要关闭外层流(即包装流)即可
- BufferedReader构造方法:
BufferedReader常用方法:
public int read() throws IOException//读取单个字符。//作为一个整数(其范围从 0 到 65535 (0x00-0xffff))读入的字符,如果已到达流末尾,则返回 -1 public int read(char[] cbuf) throws IOException//一次读取一个字节数组//cbuf - 目标缓冲区//读取的字符数,如果已到达流的末尾,则返回 -1 public void close() throws IOException//关闭该流并释放与之关联的所有资源。 public String readLine() throws IOException//读取一个文本行。通过下列字符之一即可认为某行已终止:换行 (’\n’)、回车 (’\r’) 或回车后直接跟着换行。//包含该行内容的字符串,不包含任何行终止符,如果已到达流末尾,则返回 nu
- BufferedWriter构造方法:
BufferedWriter常用方法:
void write(char ch);//写入单个字符。 void write(char []cbuf,int off,int len)//写入字符数据的某一部分。 void write(String s,int off,int len)//写入字符串的某一部分。 void newLine()//写入一个行分隔符。 void flush();//刷新该流中的缓冲。将缓冲数据写到目的文件中去。 void close();//关闭此流,在关闭前会先刷新
应用案例1:使用BufferedReader读取文本文件,并显示在控制台
package li.io.reader_; import java.io.BufferedReader;import java.io.FileReader; //演示BufferedReader的使用public class BufferedReader_ { public static void main(String[] args) throws Exception { String filePath = "d:\\note.txt"; //创建 BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath)); //读取 String line; //readLine():按行读取文件,当返回null时,表示文件读取完毕 while((line = bufferedReader.readLine())!=null){ System.out.println(line); } //关闭流:这里只需要关闭BufferedReader,底层会去自动地关闭节点流 bufferedReader.close(); }}
思考:为什么只需要关闭外层流?
在代码bufferedReader.close();处打上断点,点击force step into,可以看到下图所示:
在底层调用的其实是:传进去的节点流对象的close()方法
这里的in就是我们传入的new FileReader(filePath)
应用案例2:使用BufferedWriter将“一只可爱的小猫咪”写入到文件中
package li.io.writer_; import java.io.BufferedWriter;import java.io.FileWriter;import java.io.IOException; //演示BufferedWriter的使用public class BufferedWriter_ { public static void main(String[] args) throws IOException { String filePath = "d:\\ok.txt"; //创建BufferedWriter对象 BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath)); //写入 bufferedWriter.write("一只可爱的小猫咪"); bufferedWriter.newLine();//插入一个和系统相关的换行 bufferedWriter.write("两只可爱的小猫咪"); bufferedWriter.newLine(); bufferedWriter.write("三只可爱的小猫咪"); bufferedWriter.newLine(); //关闭外层流即可,底层自动关闭穿入的内层流 bufferedWriter.close(); }}
案例3:综合使用 BufferedReader & BufferedWriter 完成文件文本拷贝,注意文件编码。
package li.io.writer_; import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.FileReader;import java.io.FileWriter; public class BufferedCopy_ { public static void main(String[] args) throws Exception { //注意:BufferedReader 和 BufferedWriter都是字符流操作 // 不要去操作二进制文件[声音,视频,doc,pdf等],可能造成文件损坏 String srcFilePath = "d:\\note.txt";//源文件 String destFilePath = "d:\\note2.txt"; String line = null; //创建BufferedReader&BufferedWriter对象 BufferedReader bufferedReader = new BufferedReader(new FileReader(srcFilePath)); BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(destFilePath)); //读入和写出 while ((line = bufferedReader.readLine()) != null) {//每读取一行内容就写入 bufferedWriter.write(line); bufferedWriter.newLine();//换行 } System.out.println("拷贝完毕~"); //关闭两个外层流 bufferedReader.close(); bufferedWriter.close(); }}
4.4.4字节处理流-BufferedInputStream&BufferedOutputStream
- BufferedInputStream
- BufferedInputStream是字节流,在创建BufferedInputStream时会创建一个内部缓冲区数组。
常用方法:
int available()//用于返回输入流中可用的未读字节数,而不会由于下一次为此InputStream的方法的调用而阻塞。 void close()//关闭此输入流并释放与该流关联的所有系统资源。 void mark(int readlimit)//输入流的当前位置做个标记,readlimit参数是输入流在标记位置失效前允许读取的字节数。 boolean markSupported()//测试输入流是否支持mark和reset方法。 int read()//读取一个字节。 int read(byte[] b, int off, int len)//读取多个字节到字节数组b中,参数off是数组偏移量,参数len是读取数据的长度。 void reset()//重置流的当前位置到前面标记的位置。 long skip(long n)//略过流中的数据。若数据不够时,跳过仅有的字节,返回跳过的字节数。
- BufferedOutputStream
- BufferedOutputStream是字节流,实现缓冲的输出流,可以将多个字节写入底层的输出流中,而不必对每次字节写入调用底层系统
应用案例:
要求:编程完成图片/音乐的拷贝(要求使用 BufferedInputStream 和 BufferedOutputStream 流)
package li.io.outputstream_; import java.io.*; /** * 演示使用 BufferedInputStream 和 BufferedOutputStream * 使用它们可以拷贝二进制文件 * 同时也可以拷贝文本文件 */ public class BufferedCopy02 { public static void main(String[] args) { String srcFilePath = "d:\\兰亭序 - 周杰伦.mp3"; String destFilePath = "d:\\ltx-zhou.mp3"; //创建BufferedInputStream 和 BufferedOutputStream对象 BufferedInputStream bis = null; BufferedOutputStream bos = null; try { bis = new BufferedInputStream(new FileInputStream(srcFilePath)); bos = new BufferedOutputStream(new FileOutputStream(destFilePath)); //循环写入并读取 byte[] buf = new byte[1024]; int readLen = 0; //read(byte[]):当返回-1时就表示文件读取完毕 while ((readLen = bis.read(buf)) != -1) { bos.write(buf, 0, readLen); } } catch (IOException e) { e.printStackTrace(); } finally { //关闭外层流 try { if (bos != null) { bos.close(); } if (bis != null) { bis.close(); } } catch (IOException e) { e.printStackTrace(); } } }}
4.4节点流和处理流02
4.4.5对象处理流-ObjectInputStream和ObjectOutputStream
1.序列化和反序列化
例子1:
看一个需求
- 将int num= 100这个int 类型的数据保存到文件中,注意不是100 数字,而是int 100,并且能够从文件中直接恢复int 100
- 将Dog dog = new Dog(“小黄”,3)这个Dog对象保存到文件中,并且能够从文件恢复。
上面的要求,就是能够将 基本数据类型 或者 对象 进行 序列化 和 反序列化操作
- 序列化和反序列化序列化就是在保存数据时,保存数据的值和数据类型反序列化就是在恢复数据时,恢复数据的值和数据类型需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让这个类是可序列化,该类必须实现以下两个接口之一:Serializable //这是一个标记接口,没有方法(推荐)Externalizable //该接口有方法需要实现,因此推荐实现上面的Serializable接口
2. 对象处理流基本介绍与应用
- 功能:提供了对基本类型或对象类型的序列化和反序列化的方法
- ObjectOutputStream提供序列化功能
- ObjectInputStream 提供反序列化功能
例子1:序列化应用
使用ObjectOutputStream序列化 基本数据类型 和一个 Dog对象(name,age),并保存到data.dat文件中。
package li.io.outputstream_; import java.io.FileOutputStream;import java.io.ObjectOutputStream;import java.io.Serializable; //演示ObjectOutputStream的使用,完成数据的序列化public class ObjectOutputStream_ { public static void main(String[] args) throws Exception { //序列化后,保存的文件格式不是纯文本格式,而是按照它自己的格式来保存 String filePath = "d:\\data.dat"; ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath)); //存储 //序列化数据到文件d:\data.dat oos.writeInt(100);//100在底层实现了自动装箱,int ->Integer (Integer实现了Serializable接口) oos.writeBoolean(true);//boolean ->Boolean (Boolean实现了Serializable接口) oos.writeChar('a');// char ->Char (实现了Serializable接口) oos.writeDouble(9.5);//double ->Double (实现了Serializable接口) oos.writeUTF("你好火星");//String(实现了Serializable接口) //保存一个Dog对象 oos.writeObject(new Dog("旺财", 10)); //关闭外层流 oos.close(); System.out.println("数据保存完毕(序列化形式)"); }} //如果需要序列化某个对象,必须实现接口Serializable或者 Externalizable接口class Dog implements Serializable { private String name; private int age; public Dog(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Dog{" + "name='" + name + '\'' + ", age=" + age + '}'; } public String getName() { return name; }}
例子2:反序列化应用
使用ObjectInputStream读取data.dat并且反序列化恢复数据
Dog:
package li.io.outputstream_; import java.io.Serializable; //如果需要序列化某个对象,必须实现接口Serializable或者 Externalizable接口public class Dog implements Serializable { private String name; private int age; public Dog(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return "Dog{" + "name='" + name + '\'' + ", age=" + age + '}'; } public String getName() { return name; }}
ObjectInputStream_:
package li.io.inputstream_; import java.io.FileInputStream;import java.io.IOException;import java.io.ObjectInputStream; import li.io.outputstream_.Dog; public class ObjectInputStream_ { public static void main(String[] args) throws IOException, ClassNotFoundException { //指定反序列化的文件 String filePath = "d:\\data.dat"; ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath)); //读取 //1.读取(反序列化)的顺序要和你保存数据(序列化)的顺序一致,否则会出现异常 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()); //dog的编译类型是Object ,dou的运行类型是 Dog Object dog = ois.readObject(); System.out.println("运行类型=" + dog.getClass());//Dog System.out.println("dog信息=" + dog);//底层 Object->Dog //一些重要细节: //1. 如果我们希望调用Dog的方法,需要向下转型 //2. 需要我们将Dog类的定义拷贝到可以引用的位置然后导入类(将Dog类创建为公共类,重新序列化,再反序列化) Dog dog1 = (Dog) dog; System.out.println(dog1.getName()); //关闭外层流 ois.close(); }}
3.对象处理流使用细节
- 读写顺序要一致
- 要求实现序列化或者反序列化的对象的类,需要实现接口Serializable或者Externalizable
- 序列化的类中建议添加SerialVersionUID,是为了提高版本的兼容性
在完成序列化操作后,如果对序列化对象进行了修改,比如增加某个字段,那么我们再进行反序列化就会抛出InvalidClassException异常,这种情况叫不兼容问题。
解决的方法是:在对象中手动添加一个 serialVersionUID 字段,用来声明一个序列化版本号,之后再怎么添加属性也能进行反序列化,凡是实现Serializable接口的类都应该有一个表示序列化版本标识符的静态变量。
- 序列化对象时,默认将里面的所有属性都进行序列化,但除了static或transient修饰的成员
- 序列化对象时,要求里面属性的类型也需要实现序列化接口
例如:在(实现了Serializable接口的)Dog类中创建一个Master类型的属性master,而Master类没有实现Serializable接口,所以在序列化时,Dog类中的master属性无法序列化,也不能反序列化
- 序列化具有可继承性,也就是说如果某类已经实现序列化,则它的所有子类也已经默认实现了序列化
4.4.6标准输入输出流
不懂这些,你敢说自己知道Java标准输入输出流? – 简书 (jianshu.com)
介绍:
类型 |
默认设备 |
|
System.in 标准输入 |
InputStream |
键盘 |
System.out标准输出 |
PrintStream |
显示器 |
例子1:
package li.io.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());//class java.io.BufferedInputStream-字节处理输入流 // 1. System.out public final static PrintStream out = null; // 2.编译类型 PrintStream // 3.运行类型 PrintStream // 4.表示标准输出显示器--将数据输出到命令行 System.out.println(System.out.getClass());//class java.io.PrintStream - 字节输出流 }}
应用案例1:
传统方法: System.out.println(” “);是使用out对象将数据输出到显示器
应用案例2:
传统方法,Scanner是从标准输入 键盘接收数据
// 给Scanner扫描器传入的就是BufferedInputStream, // 表示的是标准输入--用来读取键盘录入的数据 // 因此 scanner会到键盘去 获取输入的数据 Scanner scanner = new Scanner(System.in); System.out.println("请输入内容:"); //会去键盘去得到输入流 String next = scanner.next(); System.out.println(next); scanner.close();
4.4.7转换流-InputStreamReader和OutputStreamWriter
1.文件乱码问题
先来看一个例子:
在d:\盘的根目录下有一个a.txt文件,内容如下:
现在想把该文件读取到程序中:
package li.io.transformation; import java.io.BufferedReader;import java.io.FileReader;import java.io.IOException; //一个中文乱码问题public class CodeQuestion { public static void main(String[] args) throws IOException { //读取a.txt文件到程序中 //思路: // 1.创建一个字符输入流 这里用 BufferedRead[处理流] // 2.使用 BufferedRead 对象读取 a.txt // 3.在默认情况下,读取文件是按照 UTF-8 编码 String filePath = "d:\\a.txt"; BufferedReader br = new BufferedReader(new FileReader(filePath)); String s = br.readLine(); System.out.println("读取到的内容=" + s); br.close(); }}
在a.txt文件编码为uft-8的时候,输出:
在a.txt文件编码为ANSI的时候,输出:
出现乱码的根本问题是:没有指定文件的编码方式。
2.基本介绍与应用
转换流也是一种处理流,它提供了字节流和字符流之间的转换。
在Java IO流中提供了两个转换流:InputStreamReader 和 OutputStreamWriter,这两个类都属于字符流。
转换流的原理是:字符流 = 字节流 + 编码表
我们需要明确的是字符编码和字符集是两个不同层面的概念。
- encoding是charset encoding的简写,即字符集编码,简称编码。
- charset是character set的简写,即字符集。
编码是依赖于字符集的,一个字符集可以有多个编码实现,就像代码中的接口实现依赖于接口一样。
在转换流中选择正确的编码非常的重要,因为指定了编码,它所对应的字符集自然就指定了,否则很容易出现乱码,所以编码才是我们最终要关心的。
转换流的特点:其是字符流和字节流之间的桥梁。
可对读取到的字节数据经过指定编码转换成字符
可对读取到的字符数据经过指定编码转换成字节
那么何时使用转换流?
当字节和字符之间有转换动作时
流操作的数据需要编码或解码时
Java IO流详解(六)—-转换流(字节流和字符流之间的转换) – 唐浩荣 – 博客园 (cnblogs.com)
- InputStreamReader:
- 如下图,InputStreamReader有一个重要的构造器InputStreamReader(InputStream, Charset):也就是说,我们可以通过这个方法,将传入的字节流转为一个字符流并指定处理的编码方式
- OutputStreamWriter:
- 如下图,OutputStreamWriter也有一个重要的构造器:
- OutputStreamWriter(OutputStream, Charset):即我们也可以通过这个方法,将写出的字节流转为一个字符流并指定处理的编码方式
- 当处理纯文本数据时,若使用字符流效率更高,并且可以有效解决中文问题,所以建议将字节流转换成字符流
- 可以在使用时指定编码格式,比如:uft-8,gbk,gb2312,ISO8859-1等
应用案例1:
编程将字节流FileInputStream转换成(包装成)字符流InputStreamReader,对文件进行读取(按照UTFF-8格式),进而再包装成 BufferedReader
package li.io.transformation; import java.io.BufferedReader;import java.io.FileInputStream; import java.io.InputStreamReader;import java.io.IOException; //演示使用 InputStreamReader 转换流解决中文乱码问题//将字节流转 FileInputStream 换成字符流 InputStreamReader,并指定编码 gbk/utf-8public class InputStreamReader_ { public static void main(String[] args) throws IOException { String filePath = "d:\\a.txt"; // 1.将 FileInputStream流(字节流),转成了 InputStreamReader流(字符流) // 2.指定了gbk编码 InputStreamReader isr = new InputStreamReader(new FileInputStream(filePath), "UTF-8"); // 3. 把 InputStreamReader 传入 BufferedReader BufferedReader br = new BufferedReader(isr); // 4. 读取 String s = br.readLine(); System.out.println("读取内容=" + s); // 5.关闭外层流 br.close(); }}
应用案例2:
编程将字节流FileOutputStream 包装(转换)成字符流OutputStreamWriter,对文件进行写入(按照GBK格式,可以指定其他,比如UTF-8)
package li.io.transformation; import java.io.FileOutputStream;import java.io.OutputStreamWriter;import java.io.IOException; /** * 演示使用 OutputStreamWriter * 将字节流转 FileOutputStream 换成字符流 OutputStreamWriter * 指定处理的编码 gbk/utf-8/utf8 */public class OutputStreamWriter_ { public static void main(String[] args) throws IOException { String filePath = "d:\\a.txt"; String charSet = "GBK"; //创建对象 OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(filePath), charSet); //写入 osw.write("我只是一只小猫咪,我不懂你在说什么"); //关闭外层流 osw.close(); System.out.println("按照 " + charSet + " 保存文件成功~"); }}JAVA 复制 全屏
4.4节点流和处理流03
4.4.8打印流-PrintStream和PrintWriter
打印流只有输出流,没有输入流
1.简单介绍及应用
- PrintStream是字节打印流
例子1:演示PrintStream(字节打印流/输出流)
package li.io.printstream; import java.io.IOException;import java.io.PrintStream; /** * 演示PrintStream(字节打印流/输出流) */public class PrintStream_ { public static void main(String[] args) throws IOException { PrintStream out = System.out; //在默认情况下,PrintStream 输出数据的位置是 标准输出,即显示器 out.print("jack,hello"); /** * public void print(String s) { * if (s == null) { * s = "null"; * } * write(s); * } */ //因为print底层使用的是write,所以我们可以直接调用write进行打印/输出 out.write("Hello北京".getBytes()); out.close(); //我们可以去修改打印流输出的位置/设备 // 1.修改为打印到d:\f1.txt // 2."落霞与孤鹜齐飞,秋水共长天一色" 这句话就会打印到d:\f1.txt里 // 3.System.setOut底层: /** * public static void setOut(PrintStream out) { * checkIO(); * setOut0(out);//native方法 ,修改了 out * } */ System.setOut(new PrintStream("d:\\f1.txt")); System.out.println("落霞与孤鹜齐飞,秋水共长天一色");//打印到d:\f1.txt }}
运行结果:
如上所示:在修改了打印流 输出的位置/设备之后,再调用System.out.println方法,打印/输出的地方就变为指定的文件路径,点击System.setOut方法,可以看到底层是调用了setOut0方法,该方法是本地方法(native)。它会去修改out,即修改输出数据的位置:
- PrintWriter是字符打印流
例子2:
package li.io.printstream; import java.io.FileWriter;import java.io.IOException;import java.io.PrintWriter; /** * 演示PrintWriter的使用方式 */public class PrintWriter_ { public static void main(String[] args) throws IOException { //PrintWriter printWriter = new PrintWriter(System.out); //向PrintWriter构造器中传入一个FileWriter对象 PrintWriter printWriter = new PrintWriter(new FileWriter("d:\\f2.txt")); printWriter.print("hi,北京你好~"); printWriter.close();//flush()+关闭流,才会将数据写入到文件中 }}
4.5Properties类
- 看一个需求:
如下一个配置文件 mysql.properties:
ip=192.168.0.13user=rootpwd=12345
问编程读取ip、user、pwd的值是多少要怎么做?
分析:
- 传统的方法
- 使用Properties类可以方便实现
例子:传统方法
在scr文件夹下创建一个mysql.properties文件,内容为
package li.io.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[] split = line.split("="); System.out.println(split[0] + "值是: " + split[1]); } //关闭 br.close(); }}
如上所示,如果mysql.properties的参数很多,并且要求读取修改其中一项或者n项参数,那么使用传统的读取方法,就需要我们对读取的参数进行条件判断,一旦要读取的参数过多,代码就会变得非常繁琐。这时候就需要使用到Properties类。
4.5.1基本介绍
Properties是Hashtable的子类,是专门用于读写配置文件的集合类:
1)配置文件的格式:
键=值键=值
2)注意:键值对之间不需要有空格,值不需要用引号括起来。默认的类型是String
3)Properties的常见方法:
- load:加载配置文件的键值对到Properties对象
- list:将数据显示到指定设备/流对象
- getProperty(Key):根据键获取值
- setProperty(Key,Value):设置键值对到Properties对象
- store:将Properties中的键值对存储到配置文件中,在idea中,保存信息到配置文件,如果含有中文,会存储为unicode码
应用案例1:使用Properties类完成对mysql.properties 的读取
package li.io.properties_; import java.io.IOException;import java.io.FileReader;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); }}
应用案例2:使用Properties类添加 key-value 到新文件 mysql2.properties 中,并修改某个 key-value
package li.io.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类添加 key-value 到新文件 mysql2.properties 中 //创建对象 Properties properties = new Properties(); //创建 //如果该文件没有key,就是创建 //如果该文件有key,就是修改/替换 /** * Properties类的父类就是 Hashtable ,底层就是 Hashtable的核心方法 * public synchronized V put(K key, V value) { * // Make sure the value is not null * if (value == null) { * throw new NullPointerException(); * } * * // Makes sure the key is not already in the hashtable. * Entry<?,?> tab[] = table; * int hash = key.hashCode(); * int index = (hash & 0x7FFFFFFF) % tab.length; * @SuppressWarnings("unchecked") * Entry<K, V> entry = (Entry<K,V>)tab[index]; * for(; entry != null ; entry = entry.next) { * if ((entry.hash == hash) && entry.key.equals(key)) { * V old = entry.value;//如果key存在,就替换 * entry.value = value; * return old; * } * } * * addEntry(hash, key, value, index);//如果是新的key,就添加新 key * return null; * } */ properties.setProperty("charset", "utf-8"); properties.setProperty("user", "汤姆");//注意:保存的是中文的Unicode码值 properties.setProperty("pwd", "abcd123"); properties.setProperty("pwd", "1111");//替换 //将k-v存储到文件中即可 properties.store(new FileOutputStream("src\\mysql2.properties"), null);//第二个参数是添加注释 System.out.println("保存配置文件成功~"); }}
查询发现 \u6C64\u59C6 对应的中文就是 汤姆
5.IO习题
5.1Homework01
(1)判断d盘下是否有文件夹mytemp,如果没有就创建mytemp
(2)在d:\mytemp目录下,创建文件hello.txt
(3)如果hello.txt已经存在,就提示该文件已经存在,就不要重复创建了
(4)并在hello.txt文件中写入内容”hello,world”.
package li.io.homework; import java.io.File;import java.io.FileOutputStream;import java.io.IOException; public class HomeWork01 { public static void main(String[] args) throws IOException { String filePath = "d:\\mytemp\\hello.txt"; String dictionaryPath = "d:\\mytemp"; //创建对象 File file = new File(dictionaryPath);//目录 File file2 = new File(filePath);//文件 FileOutputStream fileOutputStream = null; if (!file.exists()) {//如果目录不存在 if (file.mkdir()) {//创建目录 System.out.println("创建目录mytemp成功~"); } } else { System.out.println("目录mytemp已存在"); } if (file2.exists()) { System.out.println("hello.txt文件已存在"); //如果文件存在,就写入数据 fileOutputStream = new FileOutputStream(filePath); fileOutputStream.write("hello,world".getBytes()); System.out.println("已写入数据~"); } else { if (file2.createNewFile()) { System.out.println("创建hello.txt文件成功~"); //如果文件存在,就写入数据 fileOutputStream = new FileOutputStream(filePath); fileOutputStream.write("hello,world".getBytes()); System.out.println("已写入数据~"); } } //关闭流 fileOutputStream.close(); }}
5.2Homework02
编程题:要求:使用BufferedReader读取一个文本文件,为每行加上行号,再连同内容一并输出到屏幕上。
package li.io.homework; import java.io.BufferedReader;import java.io.FileReader;import java.io.IOException; public class HomeWork02 { public static void main(String[] args) throws IOException { String filePath = "d:\\story.txt"; String line = ""; int i = 0;//行号 //创建对象 BufferedReader br = new BufferedReader(new FileReader(filePath)); //读取 while ((line = br.readLine()) != null) { System.out.println((++i) + "\t" + line); } //关闭流 br.close(); }}
要求2:如果将文本的编码改为GBK,怎么将其输出到控制台上而不使其乱码?
使用转换流,FileInputStream–>InputStreamReader(指定编码)–>BufferedReader
package li.io.homework; import java.io.*; public class HomeWork02 { public static void main(String[] args) throws IOException { String filePath = "d:\\story.txt"; String line = ""; int i = 0;//行号 //创建对象 BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(filePath),"GBK"));//使用转换流,选择编码为“GBK” //读取 while ((line = br.readLine()) != null) {//循环读取 System.out.println((++i) + "\t" + line); } //关闭流 br.close(); }}
5.3Homework03
编程题:
- 要编写一个dog.properties
- name=tomage=5color=red
- 编写Dog类(name,age,color)创建一个dog对象,读取dog.properties 用相应的内容完成初始化,并输出
- 将创建的Dog对象,序列化到 文件 dog.dat文件
- 再反序列化dog对象
package li.io.homework; import java.io.*;import java.util.Properties; public class HomeWork03 { public static void main(String[] args) throws IOException, ClassNotFoundException { //1.编写dog.properties //创建Properties对象 Properties properties = new Properties(); //在properties对象中添加k-v properties.setProperty("name", "tom"); properties.setProperty("age", "5"); properties.setProperty("color", "red"); //将properties对象的k-v存储到文件中 properties.store(new FileOutputStream("src\\dog.properties"), null); //2.读取dog.properties完成Dog对象 的初始化 int age = Integer.parseInt(properties.getProperty("age")); Dog dog = new Dog(properties.getProperty("name"), age, properties.getProperty("color")); System.out.println(dog); //3.将创建的Dog对象,序列化到 dog.dat文件 String filePath = "d:\\dog.dat"; ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath)); oos.writeObject(dog); //关闭流 oos.close(); System.out.println("Dog序列化完成"); //4.反序列化dog对象 ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filePath)); Dog dog1 = (Dog) ois.readObject(); System.out.println(dog1); //关闭流 ois.close(); System.out.println("反序列化完成"); }} //序列化的类要实现Serializable接口class Dog implements Serializable { private String name; private int age; private String red; public Dog(String name, int age, String red) { this.name = name; this.age = age; this.red = red; } @Override public String toString() { return "Dog{" + "name='" + name + '\'' + ", age=" + age + ", red='" + red + '\'' + '}'; }}JAVA 折叠 复制 全屏
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/36943.html