1. 本周学习总结
1.1 以你喜欢的方式(思维导图或其他)归纳总结多流与文件相关内容。
- 输入流:从流中读数据;输出流:往流中写数据
- 字节流(Stream):以字节为基本处理单位;字符流(Reader、Writer):以字符为基本处理单位。字符流的底层还是字节流
- 字节流所有类的父类是InputStream和OutputStream,子类包括文件流、数据流等等,用完字符流要记得关闭或者强制写出,否则会有数据丢失
- 字符流所有类的父类是Reader和Writer,用完字符流也要记得关闭或者强制写出,否则会有数据丢失
- InputStreamReader和OutPutStreamWriter可以按照指定编码字节流和字符流之间进行转换,是解决乱码问题的一种方式
- 运用缓冲流可以加快文件读取时间,但要记得关闭或者强制写出,否则会有数据丢失
- 使用组合过滤流可以为流增加额外的功能,一般在编写代码是都使用组合过滤流
- 对象流直接对java中的对象进行操作,简单,方便,易于思考,但要注意要将其序列化
2. 面向系统综合设计-图书馆管理系统或购物车
2.1 简述如何使用流与文件改造你的系统。文件中数据的格式如何?
本次我改造的是图书馆管理系统,主要存储图书编号,书名,作者姓名,图书数量这几个数据,将原本存储在列表中的用户信息、图书馆信息存入文件中,每进行一次增、删、改,就调用write()方法对文件中的内容进行更新
2.2 简述系统中文件读写部分使用了流与文件相关的什么接口与类?为什么要用这些接口与类?
主要用到了InputStream
、OutputStream
父类下的ObjectInputStream
、ObjectOutputStream
、FileInputStream
和FileOutPutStream
子类,还用到了Serializable
接口,使用对象流操作起来更加方便、快捷,也易于思考,使用Serializable
接口保证了对象的序列化,确保能把对象写入流中以及能正确从流中读取对象。
2.3 截图读写文件相关代码。关键行需要加注释。
上一次的作业中我使用map存储图书馆信息的,但是这一次作业觉得用ArrayList存储也可以,实现图书馆信息的增、删、改这些方法也挺方便的,所以这次的作业在加入文件前对上次的作业进行了修改
Library类:
MyLibrary类:
运行结果:
3. 代码量统计
3.1 统计本周完成的代码量
周次 | 总代码量 | 新增代码量 | 总文件数 | 新增文件数 |
---|---|---|---|---|
2 | 343 | 343 | 10 | 10 |
3 | 498 | 498 | 8 | 8 |
5 | 788 | 788 | 26 | 26 |
6 | 536 | 536 | 16 | 16 |
7 | 776 | 776 | 9 | 9 |
8 | 846 | 846 | 4 | 4 |
9 | 668 | 668 | 12 | 12 |
10 | 501 | 501 | 7 | 7 |
11 | 394 | 394 | 13 | 13 |
12 | 903 | 903 | 19 | 19 |
13 | 1332 | 1332 | 17 | 17 |
4. 流与文件学习指导(底下的作业内容全部都是选做)
1. 字符流与文本文件:使用 PrintWriter(写),BufferedReader(读)
1.1 生成的三个学生对象,使用PrintWriter的println方法写入student.txt,每行一个学生,学生的每个属性之间用|作为分隔。使用Scanner或者BufferedReader将student.txt的数据读出。(截图关键代码,出现学号)
关键代码截图:
运行结果:
1.2 生成文件大小多少(使用右键文件属性查看)?分析该文件大小
文件大小:44字节
分析:每个数字、字母、“|”符号为1字节,换行符为2字节
行数 | 字符数 |
---|---|
1 | 15 |
2 | 14 |
3 | 15 |
1.3 如果调用PrintWriter的println方法,但在后面不close。文件大小是多少?为什么?
文件大小:0字节
修改后的代码:
运行结果:
原因:PrintWriter内部使用了缓冲区,用close()方法之后会自动将缓冲区中的剩下内容写到文件中,如果用完文件不调用close()方法关闭的话,数据会在缓冲区上丢失
2. 缓冲流
2.1 使用PrintWriter往文件里写入1千万行(随便什么内容都行),然后对比使用BufferedReader与使用Scanner从该文件中读取数据的速度(只读取,不输出),使用哪种方法快?截取测试源代码,出现学号。请详细分析原因?提示:可以使用junit4对比运行时间
测试源代码:
运行结果:
原因:BufferedReader的缓冲区比Scanner的缓冲区大,所以使用BufferedReader读取文件时操作文件的次数就比使用Scanner来的少,速度自然就更快
2.2 将PrintWriter换成BufferedWriter,观察写入文件的速度是否有提升。记录两者的运行时间。试分析原因。
运行结果:
原因:BufferedWriter使用了缓冲区,它是缓冲区满之后一次性将缓冲区中的内容写到文件中,而PrintWriter没有使用缓冲区,每一次都往文件中直接写数据,速度自然比使用BufferedWriter慢
3. 字符编码
3.1 现有EncodeTest.txt 文件,包含一些中文,该文件使用UTF-8编码。使用FileReader与BufferedReader将EncodeTest.txt的文本读入并输出。是否有乱码?为什么会有乱码?如何解决?(截图关键代码,出现学号)
关键代码截图:
运行结果:
有乱码
原因:Eclipse默认使用GBK编码、解码,而EncodeTest.txt使用UTF-8编码,将UTF-8编码的字符使用GBK来解码,会造成乱码
解决方法:1.改变Eclipse的工作环境 2.用InputStreamReader
来指定编码方式
解决方法1:
解决方法2:
解决后的运行结果:
3.2 编写方法convertGBK2UTF8(String src, String dst)
,可以将以GBK编码的源文件src转换成以UTF8编码的目的文件dst。
关键代码截图:
运行结果:
4. 字节流、二进制文件:DataInputStream, DataOutputStream、ObjectInputStream
4.1 参考DataStream目录相关代码,尝试将三个学生对象的数据写入文件,然后从文件读出并显示。(截图关键代码,出现学号)
关键代码截图:
运行结果:
4.2 这里生成的文件和题目1生成的文件有何不一样?生成的文件有多大?分析该文件大小?将该文件大小和题目1生成的文件对比是大了还是小了,为什么?存储数据的时候,到底是二进制文件比较节省空间还是文本文件比较节省空间?使用二进制存储文件有何好处?
文件大小:65字节
分析:int型4字节,double型8字节,名字每个字符1个字节,字符串结束标识符2个字节
行数 | 字节数 |
---|---|
1 | 22 |
2 | 21 |
3 | 22 |
该文件和题目1生成的文件相比大了,因为题目1以字符串存入文件中,每个字符都是一字节,本题以具体的类型存入文件中,int型4字节,double型8字节,所以相比较而言文件会比较大。在存储的数据量较小时,用文本文件更省空间,存储的数据量很大时,使用二进制文件存储会更深空间
使用二进制存储文件的好处:
- 二进制文件比较节省空间
- 计算机都是以二进制格式存储数据的,用二进制存储数据省去了格式转换的时间
- 使用二进制文件存储一些比较精确的数据时不会造成有效位的丢失
4.3 使用wxMEdit的16进制模式(或者其他文本编辑器的16进制模式)打开student.data,分析数据在文件中是如何存储的。
4.4 使用ObjectInputStream(读), ObjectOutputStream(写)读写学生。(截图关键代码,出现学号) //参考ObjectStreamTest目录
代码截图:
运行结果:
5. Scanner基本概念组装对象
5.1 编写public static List<Student> readStudents(String fileName)
从fileName指定的文本文件中读取所有学生,并将其放入到一个List中。应该使用那些IO相关的类?说说你的选择理由。
代码截图:
运行结果:
本次代码中选择了BufferedReader
,InputStreamReader
,FileInputStream
三种IO相关的类,使用InputStreamReader搭配FileInputReader来实现文件的读取,使用BufferedReader来加快文件读取的效率