一,IO流的概念

IO就是Input和Output的简写,也就是输入和输出的含义。
IO流就是指读写数据时像流水一样从一端流到另外一端,因此得名为“流”。

二、基本分类

(1)按照读写数据的基本单位不同,分为 字节流 和 字符流。
其中字节流主要指以字节为单位进行数据读写的流,可以读写任意类型的文件。
其中字符流主要指以字符(2个字节)为单位进行数据读写的流,只能读写文本文件。
(2)按照读写数据的方向不同,分为 输入流 和 输出流(站在程序的角度)。
其中输入流主要指从文件中读取数据内容输入到程序中,也就是读文件。
其中输出流主要指将程序中的数据内容输出到文件中,也就是写文件。
(3)按照流的角色不同分为节点流和处理流。
其中节点流主要指直接和输入输出源对接的流。
其中处理流主要指需要建立在节点流的基础之上的流。

三、IO流的框架结构(*)

字节(Byte):字节是通过网络传输信息(或在硬盘或内存中存储信息)的单位。字节是计算机信息技术用于计量存储容量和传输容量的一种计量单位,1个字节等于8位二进制,它是一个8位的二进制数,是一个很具体的存储空间。

字符(char):人们使用的记号,抽象意义上的一个符号。 ‘1’, ‘中’, ‘a’, ‘$’, ‘¥’, ……一个字符(1char = 2byte = 16bit),java的char是unicode编码,占两个字节,一个字节占计算机里的8位(bit),按二进制换算,它的范围是-128 to 127。

在程序中所有的数据都是以流的方式进行传输或保存的,程序需要数据的时候要使用输入流读取数据,而当程序需要将一些数据保存起来的时候,就要使用输出流完成。
程序中的输入输出都是以流的形式保存的,流中保存的实际上全都是字节文件。

[

](https://blog.csdn.net/u012566290/article/details/50351312)
03 IO流的框架图.png
image.png

四、相关流的详解

(一) FileWriter类(重点)

(1)基本概念

java.io.FileWriter类主要用于将文本内容写入到文本文件。

(2)常用的方法

image.png

(3)基本实现

  1. package Task_neuedu;
  2. import java.io.FileWriter;
  3. public class FileReaderTest {
  4. public static void main(String[] args) {
  5. //若文件不存在,则该流会新建空的文件
  6. //若文件存在,则该流会清空文件里的内容
  7. //根据参数名,构造一个对象
  8. FileWriter fw=new FileWriter("d:/aa.txt");
  9. //将文本内容写到文件
  10. fw.write('a');
  11. //关闭流
  12. fw.close();
  13. }
  14. }

示例图:
无标题.png
加上异常机制:

  1. package Task_neuedu;
  2. import java.io.FileWriter;
  3. import java.io.IOException;
  4. public class FileReaderTest {
  5. public static void main(String[] args) {
  6. //创造一个对象
  7. FileWriter fw= null;
  8. try {
  9. //若文件不存在,则该流会新建空的文件
  10. //若文件存在,则该流会清空文件里的内容
  11. // fw = new FileWriter("d:/aa2.txt");
  12. //使用这个方法,若文件存在,则保留文件内容
  13. //若文件不存在,则创建新的空文件
  14. fw=new FileWriter("d:/aa2.txt",true);
  15. //将文本内容写到文件
  16. fw.write("你好 io流");
  17. } catch (IOException e) {
  18. e.printStackTrace();
  19. }
  20. finally {
  21. if (null!=fw) {
  22. try {
  23. fw.close();
  24. } catch (IOException e) {
  25. e.printStackTrace();
  26. }
  27. }
  28. }
  29. }
  30. }

写入char数组的内容
image.png

  1. fw.write("你好 io流");
  2. char [] arr={'h','e','l','l','o'};
  3. fw.write(arr,1,2); //e l l写入到文件
  4. System.out.println("写入成功!");

(二)FileReader类(重点)

(1)基本概念

java.io.FileReader类主要用于从文本文件读取文本数据内容。

(2)常用的方法

image.png

(3)基本方法的使用

  1. package Task_neuedu;
  2. import java.io.FileNotFoundException;
  3. import java.io.FileReader;
  4. import java.io.IOException;
  5. public class FileReaderTest2 {
  6. public static void main(String[] args) {
  7. FileReader fr= null;
  8. try {
  9. /*单个读取
  10. fr = new FileReader("d:/aa2.txt");
  11. int a= 0;
  12. try {
  13. a = fr.read();
  14. } catch (IOException e) {
  15. e.printStackTrace();
  16. }
  17. System.out.println((char)a);
  18. */
  19. fr=new FileReader("d:/aa2.txt");
  20. /* 遍历读取,直到读取到最后一个字符
  21. int res=0;
  22. while ((res=fr.read())!=-1){
  23. System.out.println((char)res);
  24. 缺点:以单个字节为单位进行拷贝时,也就是每读取一个字节就写入一个字节
  25. 文件稍大时(如一个50M的视频),拷贝的效率很低
  26. }*/
  27. //定义一个一定长度数组存放读入的数据
  28. char [] arr2=new char[10];
  29. int res2= fr.read(arr2,1,3); //读取到arr2中,存储的位置是1号索引位置到3号索引位置
  30. for (char res:arr2){
  31. System.out.println(res); //遍历输出存储进arr2的内容
  32. }
  33. //int res=fr.read(arr2);将内容全部存储到数组中,内存不够,则存储前面一部分内容
  34. } catch (IOException e) {
  35. e.printStackTrace();
  36. }
  37. finally {
  38. if (null!=fr){
  39. try {
  40. fr.close(); //关闭流
  41. } catch (IOException e) {
  42. e.printStackTrace();
  43. }
  44. }
  45. }
  46. }
  47. }

(三)文件字符流实现文件的拷贝

(1),基本拷贝—拷贝:

注意看看字符流实现文件拷贝的缺点!
FileReader: java.io.FileReader类主要用于从文本文件读取文本数据内容。
FileWriter: java.io.FileWriter类主要用于将文本内容写入到文本文件。

拷贝文件:
(1)先读取文本文件内容
(2)写入到另一文本文件
(3)完成拷贝

  1. package Task_neuedu;
  2. import java.io.FileReader;
  3. import java.io.FileWriter;
  4. import java.io.IOException;
  5. /*文件字符流实现文件的拷贝*/
  6. public class FileCharCopyTest {
  7. public static void main(String[] args) {
  8. //创建FileReader对象与d:/aa2.txt关联,aa2.txt为输入源文件
  9. FileReader fr= null;
  10. //创建FileReader对象与d:/b.txt关联,b.txt为输出目标文件
  11. FileWriter fw= null;
  12. try {
  13. fr = new FileReader("d:/aa2.txt"); //读取源文件
  14. fw = new FileWriter("d:/b.txt"); //输出目标文件
  15. //把读取的内容写入到文件中
  16. System.out.println("拷贝中...");
  17. int res;
  18. while ((res=fr.read())!=-1){ //不断地从输入流当中读取内容,往输入流当中写入内容
  19. fw.write(res);
  20. }
  21. System.out.println("拷贝成功");
  22. } catch (IOException e) {
  23. e.printStackTrace();
  24. }
  25. finally {
  26. if (null!=fw){
  27. try {
  28. fw.close(); //慢创建的先关闭
  29. } catch (IOException e) {
  30. e.printStackTrace();
  31. }
  32. }
  33. if (null!=fr){
  34. try {
  35. fr.close(); //先创建的慢关闭
  36. } catch (IOException e) {
  37. e.printStackTrace();
  38. }
  39. }
  40. }
  41. }
  42. }

(四)文件字节流实现文件的拷贝

首先,看一下例子,如果用字符流的方式对图片进行拷贝,则拷贝失败,拷贝的图片“您的照片已损坏”
说明字符流只能对文本内容进行读取操作,而其他内容用字节流来操作。
image.png
==》文件字节流实现文件的拷贝,文件字节流的概念和基本方法在案例底下有介绍!FileInputStream和FileOutputStream.

  1. package Task_neuedu;
  2. import java.io.*;
  3. public class FileStreamTest {
  4. public static void main(String[] args) {
  5. //创建FileInputStream与d:/io框架图.jpg关联
  6. FileInputStream fi= null;
  7. FileOutputStream fo=null;
  8. try {
  9. fi = new FileInputStream("d:/io框架图.jpg");
  10. //创建FileOutputStream与d:/io框架副本.jpg关联
  11. fo=new FileOutputStream("d:/io框架图副本.jpg");
  12. System.out.println("开始拷贝。。。");
  13. //读取输入的流写入到输出流中
  14. //以单个字节为单位进行拷贝时,也就是每读取一个字节就写入一个字节
  15. //缺点:文件稍大时,拷贝的效率很低
  16. int res=0;
  17. while ((res= fi.read())!=-1){
  18. fo.write(res);
  19. }
  20. System.out.println("拷贝成功!");
  21. } catch (IOException e) {
  22. e.printStackTrace();
  23. }
  24. //关闭输入输出流
  25. try {
  26. if (null != fo) {
  27. fo.close();
  28. }
  29. if(null!=fi) {
  30. fi.close();
  31. }
  32. } catch (IOException e) {
  33. e.printStackTrace();
  34. }
  35. }
  36. }

(1)两种拷贝方式的缺点:

方式一:

  1. //以单个字节为单位进行拷贝时,也就是每读取一个字节就写入一个字节
  2. //缺点:文件稍大时(如一个50M的视频),拷贝的效率很低
  3. int res=0;
  4. while ((res= fi.read())!=-1){
  5. fo.write(res);
  6. }

方式一的方式好比买50个鸡蛋,每次买一个鸡蛋回到家,再去买一个鸡蛋,跑五十次,你说效率低不低?
方式二:

  1. /* 方式二,使用一个缓冲区都一次性把数据装回去
  2. 比第一种方式快了很多
  3. 缺点:每次都要准备很大的框去装鸡蛋,比较吃内存,物理内存没那么多
  4. 若文件过大时,无法申请与文件大小一样的缓冲区
  5. */
  6. int available = fi.available(); //获取文件大小,单位:字节
  7. byte [] bytes=new byte[available]; //用byte数组装数据
  8. int read = fi.read(bytes);
  9. System.out.println(available);
  10. System.out.println(read);
  11. fo.write(bytes);
  12. System.out.println("拷贝成功!");

如果要是装一万个鸡蛋,去哪找这么大的框?

(2)方式三(推荐,分批运数据!)

  1. /*方式三:给适当大小的缓冲区,分批次买鸡蛋
  2. *
  3. * */ byte [] bytes=new byte[1024];
  4. int res=0;
  5. if ((res=fi.read())!=-1){
  6. fo.write(bytes,0,res); //res就是读取的字节,读取到最后一个字节时返回负一
  7. }
  8. System.out.println("拷贝成功");

(五)FileOutputStream类(重点)

(1)基本概念

java.io.FileOutputStream类主要用于将图像数据之类的原始字节流写入到输出流中。

(2)常用的方法

image.png

(六) FileInputStream类(重点)

(1)基本概念

java.io.FileInputStream类主要用于从输入流中以字节流的方式读取图像数据等。

(2)常见的方法

image.png

  1. package Task_neuedu;
  2. import java.io.*;
  3. public class FileStreamTest {
  4. public static void main(String[] args) {
  5. long l1=System.currentTimeMillis();
  6. //创建FileInputStream与d:/io框架图.jpg关联
  7. FileInputStream fi= null;
  8. FileOutputStream fo=null;
  9. try {
  10. fi = new FileInputStream("d:/01.IO流的概念和分类.pcwlenv");
  11. //创建FileOutputStream与d:/io框架副本.jpg关联
  12. fo=new FileOutputStream("d:/01.IO流的概念和分类2.pcwlenv");
  13. System.out.println("开始拷贝。。。");
  14. //读取输入的流写入到输出流中
  15. /* 方式一:
  16. 使用这种方式,效率低下,一个字节一个字节读
  17. int res=0;
  18. while ((res= fi.read())!=-1){
  19. fo.write(res);
  20. }*/
  21. /* 方式二,使用一个缓冲区都一次性把数据装回去
  22. 比第一种方式快了很多
  23. 缺点:每次都要准备很大的框去装鸡蛋,比较吃内存,物理内存没那么多
  24. 若文件过大时,无法申请与文件大小一样的缓冲区
  25. int available = fi.available(); //获取大小,单位:字节
  26. byte [] bytes=new byte[available]; //用byte数组装数据
  27. int read = fi.read(bytes);
  28. System.out.println(available);
  29. System.out.println(read);
  30. fo.write(bytes);
  31. System.out.println("拷贝成功!");*/
  32. /*方式三:给适当大小的缓冲区,分批次买鸡蛋
  33. *
  34. * */ byte [] bytes=new byte[1024];
  35. int res=0;
  36. if ((res=fi.read())!=-1){
  37. fo.write(bytes,0,res); //res就是读取的字节,读取到最后一个字节时返回负一
  38. }
  39. System.out.println("拷贝成功");
  40. } catch (IOException e) {
  41. e.printStackTrace();
  42. }
  43. //关闭输入输出流
  44. try {
  45. if (null != fo) {
  46. fo.close();
  47. }
  48. if(null!=fi) {
  49. fi.close();
  50. }
  51. } catch (IOException e) {
  52. e.printStackTrace();
  53. }
  54. long l2=System.currentTimeMillis();
  55. System.out.println("使用字节流拷贝文件:"+(l2-l1)+"毫秒");
  56. }
  57. }

(七)缓冲流BufferedOutputStream类(重点)

(1)基本概念

java.io.BufffferedOutputStream类主要用于描述缓冲输出流,此时不用为写入的每个字节调用底层
系统。

(2)常用的方法

image.png

(八)BufferedInputStream类(重点)

(1)基本概念

java.io.BufffferedInputStream类主要用于描述缓冲输入流。

(2)常用的方法

image.png

(九)缓冲流实现文件的拷贝(开发一般就用这个)

  1. package Task_neuedu;
  2. import java.io.BufferedInputStream;
  3. import java.io.*;
  4. public class BufferdByteCopy {
  5. public static void main(String[] args) {
  6. BufferedInputStream bis = null;
  7. BufferedOutputStream bos = null;
  8. try {
  9. //创建一个BufferdInputStream对象输入文件
  10. bis = new BufferedInputStream(new FileInputStream("d:/01.IO流的概念和分类.pcwlenv"));
  11. //创建一个BufferdInputStream对象读取文件
  12. bos = new BufferedOutputStream(new FileOutputStream("d:/01.IO流的概念和分类3.pcwlenv"));
  13. System.out.println("拷贝中>>>...");
  14. //创建一个缓冲区
  15. byte[] bytes = new byte[1024];
  16. int res = 0;
  17. if ((res = bis.read()) != -1) {
  18. bos.write(bytes, 0, res); //把读取的数据存储到bytes中,写入一段读一段~缓冲区起到中介的作用
  19. }
  20. System.out.println("拷贝成功!");
  21. } catch (IOException e) {
  22. e.printStackTrace();
  23. } finally {
  24. }
  25. //关闭流
  26. if (null != bos) {
  27. try {
  28. bos.close();
  29. } catch (IOException e) {
  30. e.printStackTrace();
  31. }
  32. }
  33. if (null != bis) {
  34. try {
  35. bis.close();
  36. } catch (IOException e) {
  37. e.printStackTrace();
  38. }
  39. }
  40. }
  41. }

可以使用Sytem的方法测试效率———Long l2 = System.currentTimeMillis();

(十)BufferedWriter类(重点)

(1)基本概念
java.io.BufffferedWriter类主要用于写入单个字符、字符数组以及字符串到输出流中。

(2)常用的方法

image.png

(十一) BufferedReader类(重点)

(1)基本概念

java.io.BufffferedReader类用于从输入流中读取单个字符、字符数组以及字符串。

(2)常用的方法

image.png
缓冲字节流实现拷贝!—文本文件

  1. package Task_neuedu;
  2. import java.io.*;
  3. public class BufferdBye {
  4. public static void main(String[] args) {
  5. BufferedReader br= null;
  6. BufferedWriter bw= null;
  7. try {
  8. //构造缓冲流对象写入数据
  9. br = new BufferedReader(new FileReader("d:/aa2.txt"));//装饰模式
  10. //构造缓冲字节流读取数据
  11. bw = new BufferedWriter(new FileWriter("d:/a.txt"));
  12. System.out.println("开始拷贝");
  13. //不断地从输入流中读取数据到输出流
  14. String str=null;
  15. if((str=br.readLine())!=null){
  16. bw.write(str);
  17. bw.newLine();
  18. }
  19. System.out.println("拷贝完成");
  20. } catch (IOException e) {
  21. e.printStackTrace();
  22. } finally {
  23. if (null!=bw){
  24. try {
  25. bw.close();
  26. } catch (IOException e) {
  27. e.printStackTrace();
  28. }
  29. }
  30. if (null!=br){
  31. try {
  32. br.close();
  33. } catch (IOException e) {
  34. e.printStackTrace();
  35. }
  36. }
  37. }
  38. }
  39. }

缓冲字符流~读取字符串
image.png
bw.newLine(); //当前系统中的行分隔符是\r\n

(十二) PrintStream类

(1)基本概念

java.io.PrintStream类主要用于更加方便地打印各种数据内容。

(2)常用的方法

image.png

(十三) PrintWriter类

(1)基本概念

java.io.PrintWriter类主要用于将对象的格式化形式打印到文本输出流。

(2)常用的方法

image.png

  • 案例题目

不断地提示用户输入要发送的内容,若发送的内容是”bye”则聊天结束,否则将用户输入的内容写
入到文件d:/a.txt中。
要求使用BufffferedReader类来读取键盘的输入 System.in代表键盘输入
要求使用PrintStream类负责将数据写入文件

  1. package Task_neuedu;
  2. /*优化前*/
  3. import java.io.*;
  4. public class BufferdStreamBye {
  5. public static void main(String[] args) {
  6. BufferedReader br= null;
  7. PrintStream bw= null;
  8. try {
  9. //构造缓冲字符流对象写入
  10. br = new BufferedReader(new InputStreamReader(System.in));
  11. //构造缓冲字符流对象读取
  12. bw = new PrintStream(new FileOutputStream("d:/a2.txt"));
  13. while (true) {
  14. System.out.println("请输入内容");
  15. String str = br.readLine();
  16. if ("bye".equals(str)) { //匹配
  17. System.out.println("聊天结束!");
  18. break;
  19. }
  20. else {//否则输入到a.txt当中
  21. bw.print(str);}
  22. }
  23. } catch (IOException e) {
  24. e.printStackTrace();
  25. } finally {
  26. if (null!=br){
  27. try {
  28. br.close();
  29. } catch (IOException e) {
  30. e.printStackTrace();
  31. }
  32. }
  33. if (null!=bw){bw.close();}
  34. }
  35. }
  36. }
  1. package Task_neuedu;
  2. //优化
  3. import java.io.*;
  4. import java.text.SimpleDateFormat;
  5. import java.util.Date;
  6. public class BufferdStreamBye {
  7. public static void main(String[] args) {
  8. BufferedReader br= null;
  9. PrintStream bw= null;
  10. try {
  11. //构造缓冲字符流对象写入
  12. br = new BufferedReader(new InputStreamReader(System.in));
  13. //构造缓冲字符流对象读取
  14. bw = new PrintStream(new FileOutputStream("d:/a2.txt"));
  15. boolean flag=true;
  16. while (true) {
  17. System.out.println("请"+(flag?"张三":"李四")+"输入内容");
  18. String str = br.readLine();
  19. if ("bye".equals(str)) { //匹配
  20. System.out.println("聊天结束!");
  21. break;
  22. }
  23. else {//否则输入到a.txt当中
  24. Date date=new Date();
  25. SimpleDateFormat sdf=new SimpleDateFormat("YYYY-MM-DD hh:mm:ss ");
  26. String format = sdf.format(date);
  27. bw.println(format+" "+(flag?"张三说:":"李四说:")+str);
  28. flag=!flag;
  29. }
  30. }
  31. } catch (IOException e) {
  32. e.printStackTrace();
  33. } finally {
  34. if (null!=br){
  35. try {
  36. br.close();
  37. } catch (IOException e) {
  38. e.printStackTrace();
  39. }
  40. }
  41. if (null!=bw){bw.close();}
  42. }
  43. }
  44. }

image.png

(十八) OutputStreamWriter类

(1)基本概念

java.io.OutputStreamWriter类主要用于实现从字符流到字节流的转换。

(2)常用的方法

image.png

(十九) InputStreamReader类

(1)基本概念

java.io.InputStreamReader类主要用于实现从字节流到字符流的转换。

(2)常用方法

image.png

(二十)字符编码

(1)编码表的由来

计算机只能识别二进制数据,早期就是电信号。为了方便计算机可以识别各个国家的文字,就需要
将各个国家的文字采用数字编号的方式进行描述并建立对应的关系表,该表就叫做编码表。

(2)常见的编码表

  • ASCII:美国标准信息交换码, 使用一个字节的低7位二位进制进行表示。
  • ISO8859-1:拉丁码表,欧洲码表,使用一个字节的8位二进制进行表示。
  • GB2312:中国的中文编码表,最多使用两个字节16位二进制为进行表示。
  • GBK:中国的中文编码表升级,融合了更多的中文文字符号,最多使用两个字节16位二进制位表示。
  • Unicode:国际标准码,融合了目前人类使用的所有字符,为每个字符分配唯一的字符码。所有的

文字都用两个字节16位二进制位来表示。

(3)编码的发展

面向传输的众多 UTF(UCS Transfer Format)标准出现了,UTF-8就是每次8个位传输数据,而
UTF-16就是每次16个位。这是为传输而设计的编码并使编码无国界,这样就可以显示全世界上所
有文化的字符了。
Unicode只是定义了一个庞大的、全球通用的字符集,并为每个字符规定了唯一确定的编号,具体
存储成什么样的字节流,取决于字符编码方案。推荐的Unicode编码是UTF-8和UTF-16。
UTF-8:变长的编码方式,可用1-4个字节来表示一个字符。
image.png

(二十一)DataOutputStream类(了解)

(1)基本概念

java.io.DataOutputStream类主要用于以适当的方式将基本数据类型写入输出流中。

(2)常用的方法

image.png
image.png

(二十二) DataInputStream类(了解)

(1)基本概念

java.io.DataInputStream类主要用于从输入流中读取基本数据类型的数据。

(2)常用的方法

image.png
image.png
注意write()和writeInt()的区别。

(二十三)ObjectOutputStream类(重点)

(1)基本概念

  • java.io.ObjectOutputStream类主要用于将一个对象的所有内容整体写入到输出流中。
  • 只能将支持 java.io.Serializable 接口的对象写入流中。
  • 类通过实现 java.io.Serializable 接口以启用其序列化功能。
  • 所谓序列化主要指将一个对象需要存储的相关信息有效组织成字节序列的转化过程。 ——序列化
  • image.png

    (2)常用的方法

    image.png
    基本实现 ```java package Task13;

import java.io.Serializable;

public class User implements java.io.Serializable { private static final long serialVersionUID = 5048249014317513427L; private String name; //用户名 private int Phone; //手机号 private String password; //密码

  1. public User(String name, int phone, String password) {
  2. this.name = name;
  3. Phone = phone;
  4. this.password = password;
  5. }
  6. public User() {
  7. }
  8. public String getName() {
  9. return name;
  10. }
  11. public void setName(String name) {
  12. this.name = name;
  13. }
  14. public int getPhone() {
  15. return Phone;
  16. }
  17. public void setPhone(int phone) {
  18. Phone = phone;
  19. }
  20. public String getPassword() {
  21. return password;
  22. }
  23. public void setPassword(String password) {
  24. this.password = password;
  25. }

}

  1. ```java
  2. package Task13;
  3. import java.io.FileOutputStream;
  4. import java.io.IOException;
  5. import java.io.ObjectOutputStream;
  6. public class ObjectOutputStreamTest {
  7. public static void main(String[] args) {
  8. ObjectOutputStream objs= null;
  9. try {
  10. objs = new ObjectOutputStream(new FileOutputStream("d:/a.txt"));
  11. User user=new User("林一",1234567888,"nihao9090");
  12. objs.writeObject(user);
  13. System.out.println("写入成功!");
  14. } catch (IOException e) {
  15. e.printStackTrace();
  16. } finally {
  17. if (null!=objs){
  18. try {
  19. objs.close();
  20. } catch (IOException e) {
  21. e.printStackTrace();
  22. }
  23. }
  24. }
  25. }
  26. }

(二十五) ObjectInputStream类(重点)

( 1)基本概念

java.io.ObjectInputStream类主要用于从输入流中一次性将对象整体读取出来。
所谓反序列化主要指将有效组织的字节序列恢复为一个对象及相关信息的转化过程。

(2)基本方法

image.png

  1. //方法的基本使用
  2. package Task_neuedu;
  3. import java.io.FileInputStream;
  4. import java.io.IOException;
  5. import java.io.ObjectInputStream;
  6. public class ObjectInputStreamTest {
  7. public static void main(String[] args) {
  8. ObjectInputStream objsi= null;
  9. try {
  10. //创建ObjectInputStreamTest与d:/a.txt关联,与序列化的文件对应
  11. objsi = new ObjectInputStream(new FileInputStream("d:/a.txt"));
  12. Object str= objsi.readObject();
  13. System.out.println("读取到的对象是"+str);
  14. } catch (IOException e) {
  15. e.printStackTrace();
  16. } catch (ClassNotFoundException e) {
  17. e.printStackTrace();
  18. } finally {
  19. if (null!=objsi) {
  20. try {
  21. objsi.close();
  22. } catch (IOException e) {
  23. e.printStackTrace();
  24. }
  25. }
  26. }
  27. }
  28. }

image.png
案例:
HJLM7SB98ZBV_`B73W]_4YN.jpg

  1. package Ch12_Neuedu;
  2. import java.io.Serializable;
  3. public class product implements Serializable {
  4. private static final long serialVersionUID = 7459814710836750155L;
  5. private int id;
  6. private String name;
  7. private String categories;
  8. private double price;
  9. public product() {
  10. }
  11. public product(int id, String name, String categories, double price) {
  12. this.id = id;
  13. this.name = name;
  14. this.categories = categories;
  15. this.price = price;
  16. }
  17. public int getId() {
  18. return id;
  19. }
  20. public void setId(int id) {
  21. this.id = id;
  22. }
  23. public String getName() {
  24. return name;
  25. }
  26. public void setName(String name) {
  27. this.name = name;
  28. }
  29. public String getCategories() {
  30. return categories;
  31. }
  32. public void setCategories(String categories) {
  33. this.categories = categories;
  34. }
  35. public double getPrice() {
  36. return price;
  37. }
  38. public void setPrice(double price) {
  39. this.price = price;
  40. }
  41. @Override
  42. public String toString() {
  43. return "product{" +
  44. "id=" + id +
  45. ", name='" + name + '\'' +
  46. ", categories='" + categories + '\'' +
  47. ", price=" + price +
  48. '}';
  49. }
  50. }
  1. package Ch12_Neuedu;
  2. import ch9.Array;
  3. import com.sun.org.apache.bcel.internal.generic.IF_ACMPEQ;
  4. import java.io.*;
  5. import java.util.ArrayList;
  6. public class productTest {
  7. public static void main(String[] args) {
  8. ObjectOutputStream o1= null;
  9. ObjectInputStream o2= null;
  10. try {
  11. //添加产品
  12. product iphone=new product(123,"iphone","telephone",4888.0);
  13. product ipad=new product(234,"ipad","ipad",5088.0);
  14. product macbook=new product(345,"macbook","computer",10688.0);
  15. product watch=new product(345,"iwatch","watch",4799.0);
  16. //使用集合存储对象 List<product> str=new ArrayList<>();
  17. ArrayList <product> str=new ArrayList<>();
  18. //创建ObjectOutputStream与对象关联,进行序列化
  19. o1 = new ObjectOutputStream(new FileOutputStream("d:/a.txt"));
  20. str.add(iphone);
  21. str.add(ipad);
  22. str.add(macbook);
  23. str.add(watch);
  24. //将对象序列化到d:/a.txt中
  25. o1.writeObject(str);
  26. System.out.println("写入成功!");
  27. System.out.println("反序列化中......");
  28. //创建ObjectInputStream与对象关联,进行反序列化
  29. o2 = new ObjectInputStream(new FileInputStream("d:/a.txt"));
  30. ArrayList<product> list =(ArrayList<product>) o2.readObject();
  31. System.out.println("读取到的对象是:");
  32. System.out.println("---------------------------------------------------------");
  33. for (product list2:list) {
  34. System.out.println(list2+" ");
  35. }
  36. } catch (IOException e) {
  37. e.printStackTrace();
  38. } catch (ClassNotFoundException e) {
  39. e.printStackTrace();
  40. } finally {
  41. try {
  42. if (o1!=null){
  43. o1.close();}
  44. } catch (IOException e) {
  45. e.printStackTrace();
  46. }
  47. try {
  48. if (o2!=null){
  49. o2.close();}
  50. } catch (IOException e) {
  51. e.printStackTrace();
  52. }
  53. }
  54. }
  55. }

#来自大佬的答案:

(1)仅供参考!
AGEKH)9VR({Z27$U9UP979U.jpg
KG}9LI~B~9V%{Q{815COXYI.jpg
面向对象,对于对象的存储使用集合。

(3)序列化版本号

  • 序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,
  • JVM会把传来的字节流中的serialVersionUID与本地相应实体类的serialVersionUID进行比较,如
  • 果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常
  • (InvalidCastException)。

    (4)transient关键字

  • transient是Java语言的关键字,用来表示一个域不是该对象串行化的一部分。当一个对象被串行

化的时候,transient型变量的值不包括在串行化的表示中,然而非transient型的变量是被包括进
去的。
用该关键字修饰则不会再被序列化,不会写入到文件中。

(5)经验的分享

  • 当希望将多个对象写入文件时,通常建议将多个对象放入一个集合中,然后将集合这个整体看做一

个对象写入输出流中,此时只需要调用一次readObject方法就可以将整个集合的数据读取出来,
从而避免了通过返回值进行是否达到文件末尾的判断。

(二十四) RandomAccessFile类

(1)基本概念

java.io.RandomAccessFile类主要支持对随机访问文件的读写操作。

(2)常用的方法

image.png
image.png

笔试考点*

(1)IO基本概念

image.png

(2) 既然有了字节流,为什么还要有字符流?

问题本质想问:不管是⽂件读写还是⽹络发送接收,信息的最⼩存储单元都是字节,那为什么
I/O 流操作要分为字节流操作和字符流操作呢?
回答:字符流是由 Java 虚拟机将字节转换得到的,问题就出在这个过程还算是⾮常耗时,并
且,如果我们不知道编码类型就很容易出现乱码问题。所以, I/O 流就⼲脆提供了⼀个直接操作
字符的接⼝,⽅便我们平时对字符进⾏流操作。如果⾳频⽂件、图⽚等媒体⽂件⽤字节流⽐᫾
好,如果涉及到字符的话使⽤字符流⽐᫾好。
(3)BIO\NIO\AIO的区别

image.pngimage.png