当前课程知识点:Java程序设计 > 第五章 输入输出 > 5.3.4-读二进制文件 > 读二进制文件
大家好
欢迎回来继续学习
Java语言程序设计
这一节我们学习
如何从二进制文件中读取数据
前面的部分我们曾经看到过例题
向一个二进制文件中
写入int类型的数据
现在我们来看下一个例题
我们从这个二进制文件中
把以前曾经写进去的数据
读取出来然后做加法
现在我们就来看怎么读取
以前曾经写到
文件中去的三个整数
那我们构造一个输入流对象
关联到当初写的
这个二进制文件data1.dat
那这个输入流对象
它必须接到一个DataInputStream
它可以按类型读取
它最底层还是一个FileInputStream
原生字节的输出流
然后是一个缓冲流
最外面接一个能够识别数据类型的DataInputStream流
然后连续调用三次readInt
就把三个整数就读回来了
然后再一个加法非常简单
文件操作放在try块里面
然后用catch块来捕获
逻辑非常简单
运行结果是正确的没有问题
那大家想一下
我们用这个readInt方法的时候
我们知道每次读什么类型的数据
那就没问题
如果不知道里面
存的是什么类型的数据
那也没什么办法了
所以当初这个文件中
写入的是什么数据
一定要自己记住有文档记录
将来还按写的顺序读回来
更多的情况下
我们一般喜欢是在
同一个文件中写同类型的数据
而太会在一个文件中
混合各种类型的数据
写同一个类型的数据
它的二进制数据是等长的
而且读的时候
我们可以循环读这种类型
那么现在如果说
我们写了很多整数
但是我不知道总共有多少个整数
或者说总共有多少个整数
在每次运行的时候
内容并不确定
那个写的程序它采集到多少数据
它就存多少
然后我们在这个读的程序中的
应该就把它全读出来
也就是说不知道
总共有多少个整数
那这个时候怎么办呢
怎么判断要读多少次呢
如果用循环来读的话
这个时候我们可以依赖这个异常
因为这个DataInputStream
读入操作如果遇到了文件尾
你还持续让它读
它就会抛出一个1OException
文件结束异常
那么这样的话
我们就可以把这个循环
读的操作放在try块里面
然后捕获这个文件结束异常
就可以了
接下来这个例题中
我们来通过捕获异常的方式
来判断是否已经读到文件尾了
现在我们将这个读操作
放在一个死循环
或者说永久循环中
看在这个while后面条件是true
所以就是说永远的一直不停的读
那么怎么能一直不停的读啊
遇到文件尾就读不了了
就是用它这样一个特性
把这个操作放在try块中
如果遇到文件尾了
它自然就抛出一个EOFException
然后后面紧接着这catch块
就捕获EOFException
就能够确定文件什么时候结束
那仅仅有这样一对try catch
是不是就够了很完美了呢
大家想想看还是有问题的
因为在读的时候
不仅仅有可能读到文件尾
发生文件结束异常
在中间读的过程中
就有可能发生别的错误
造成文件访问的异常
那么这个时候后边
是不是应该也跟一个catch块
来捕获一个一般的IOException呢
还有一个问题
就是在这个catch里面
它有关闭文件这也是文件操作
这个关闭文件也是有可能
它也可能抛出异常
就是在异常处理块中又抛出异常
那么这个时候怎么办呢
这个时候就不是在try块后面
连续写多个catch块
可以解决的问题了
我们就需要嵌套的try catch结构
所以我们把整个这个读
以及判断读到文件尾
捕获异常这个过程
作为内层的try catch块
在外层还有一个try catch
那么包括了构造文件流对象
也包括了内层的整个try catch
然后在外层的catch里面
捕获这种一般的IOException
这就是一个用嵌套的try catch结构
去捕获各种异常的这样一个例子
我们知道文本文件
其实它也是
以二进制编码的方式存储的
所以从根本上讲
也可以用二进制的流来读取它
接下来我们就看一个例子
我们用二进制的输入流
来读取文本文件中的内容
并且把这些内容显示在显示器上
那么怎么用字节流
来读取文本文件呢
我们来看首先就构造一个
面向字节的输入流
虽然它处理的文件
是我们原来写的纯文本文件
但是这个流只是
一个面向原生字节的流
我们就用read方法
每次读一个字节
用判断它是否返回负1
来确定是否到文件尾了
每读一个字节就将这一个字节
写出去写到哪儿
通过System.out去调用write方法
那也就是写到标准输出设备
就是将我们读进来的信息
都写到显示器上了
这个read方法读一个字节
然后会转换成一个
0-255之间的一个整数
因为它返回的是一个int类型
所以你看我们将它的返回值
赋给一个int
那么write int方法
它写一个字节的低八位
忽略高24位
这里说这低呢
是它权重比较低的那八位
不是说一定是
它的地址比较低的那个八位
因为在不同的系统里面
有的是低位放在低地址
高位放在高地址
有的系统里面会反过来
高位放在低地址
低位放在高地址
所以这里说的低八位
是它权重比较低的八位
或者确切的说最不重要的那八位
就是这样的方法
写一个字节的低八位忽略高24位
所以这个read和write
它正好就对应起来了
在这一节的最后
我要给大家看一个
文件复制的例子
那么为了很简单的用
读一个字节写一个字节的方式
去复制一个文件
那么我们先了解一下
在Java中专门读单个字节
写单个字节的方法
在DataOutputStream这个类中
有一个writeByte方法
这里列出了这个方法的原形
它的参数是一个int类型
那么它的功能就是将你给的参数
这个int参数
它里面的最不重要字节
写到输出流里面去
我们可以简单的用白话说
把它的最低字节写出去
但是为什么说最低字节不严格呢
就是在不同的系统里面
那么到底是高位
存在高地址的字节
低位存在低地址的字节
还是说反过来高位
存在低地址字节
低位存在高地址字节呢
可能不同系统里面会不一样
所以严格来说是将它数值上
或者逻辑上的第一位
写到输出流中去
在DataInputStream类里面
有这个readUnsignedByte
它跟这个writeByte的方法
功能正好对应起来
也列出了方法的原形
大家看一下
它的功能是从输入流中
读取一个字节
存入int的最不重要字节中去
如果不严格的讲
可以说最低字节
但是严格的说应该说
存到它的权重最低的
或者说它最不重要的字节中去
好
接下来我们就来看
这一节最后的这个例子
用读写字节的方式
来复制一个文件
那么不管这个文件是二进制文件
还是文本文件
我们用这种方法都可以实现
很好完整的文件复制
现在我们就用
专门读写字节的方法
来进行文件复制
这个例题也是做文件复制
其实到这儿我们就会看到了
做个文件复制
其实有好多不同的办法
那我们再来看看
这个例题用的是什么办法
这里我们用命令行参数
作为文件名
来构造输入流对象
和输出流对象
那么它们都是可以识别数据类型的
输入的是DataInputStream
输出是DataOutputStream
然后我们就来看开始复制
将这个过程也是放在
嵌套的try catch块中
我们看前面的构造
输入流对象和输出流对象
就已经放在外层的try块里边了
接下来我们要进行复制
那么这个复制我们是
放在这种死循环里面的
遇到文件尾
它会抛出文件结束异常
被内层的catch块捕获
所以读文件复制的过程
在内层的try catch块里面
这次我们每次用这个
readUnsignedByte读进来
然后相应的用writeByte写出去
这样就一个字节一个字节的复制
直到文件结尾
在外层的catch块里面
要捕获比较具体的文件没找到异常
然后接下来在后面
再捕获比较一般的IOException
也就说如果你仅仅
捕获一个IOException的话
太笼统了
最好我们先捕获一个文件
找不到异常
比如打开文件找不到了
这个时候我们可以告诉用户
到底是哪个文件出问题了
然后其他最后兜底的
就是所有前面没捕获到的
属于IO异常的都在这儿捕获
笼统的告诉你IO出问题了
好
这一节我们学习了
如何从一个二进制文件读取数据
并且通过一个文件复制的例子
看到了读和写操作的配合
好
这一节内容就是这些
-1.0-导学
--1.0-导学
-1.1-Java与面向对象程序设计简介
--第一章 Java语言基础知识--1.1-Java与面向对象程序设计简介
-1.2-基本数据类型与表达式
-第一章 Java语言基础知识--1.2-基本数据类型与表达式
-1.3-数组
--1.3.1-数组
-第一章 Java语言基础知识--1.3-数组
-1.4-算法的流程控制
--第一章 Java语言基础知识--1.4-算法的流程控制
-1.5-第一章小结
-第一章编程练习题
-课件
--外部链接
-Java环境配置、Eclipse使用、Helloworld程序详解
--使用eclipse建立Java项目、编写和运行Java程序
-Java数据类型
--Java整数类型
--Java浮点类型
--数据类型实战
--数据类型转换
--Java强制类型转换精度损失示例与表达式中的数据类型转换
-Java数组
-Java变量
--Java的变量
-命令行参数
--命令行参数的介绍
-2.0-导学
--2.0-导学
-2.1-面向对象方法的特性
--第二章 类与对象--2.1-面向对象方法的特性
-2.2-1-类声明与对象创建
--第二章 类与对象--2.2-1-类声明与对象创建
-2.2-2-数据成员
--第二章 类与对象--2.2-2-数据成员
-2.2-3-方法成员
--第二章 类与对象--2.2-3-方法成员
-2.2-4-包
--2.2-4-包
--第二章 类与对象--2.2-4-包
-2.2-5-类的访问权限控制
--第二章 类与对象--2.2-5-类的访问权限控制
-2.3-1-对象初始化
--第二章 类与对象--2.3-1-对象初始化
-2.3-2-内存回收
--第二章 类与对象--2.3-2-内存回收
-2.4-枚举类
--2.4-枚举类
--第二章 类与对象--2.4-枚举类
-2.5-应用举例
--2.5-应用举例
-2.6-第2章小结
-第二章编程练习题
-课件
--第二章课件
-3.0-导学
--3.0-导学
-3.1.1-3.1.2-类继承的概念和语法
--第三章 类的重用--3.1.1-3.1.2-类继承的概念和语法
-3.1.3-隐藏和覆盖
--第三章 类的重用--3.1.3-隐藏和覆盖
-3.2-Object 类
--第三章 类的重用--3.2-Object 类
-3.3-终结类与终结方法
--第三章 类的重用--3.3-终结类与终结方法
-3.4-抽象类
--3.4-抽象类
--第三章 类的重用--3.4-抽象类
-3.5-泛型
--3.5-泛型
--第三章 类的重用--3.5-泛型
-3.6-类的组合
--3.6-类的组合
-3.7-小结
--3.7-小结
-第三章编程练习题
-课件
--课件
-4.0-导学
--导学
-4.1-接口
--接口
--第四章 接口与多态--4.1-接口
-4.2.1-4.2.2-类型转换
--类型转换
--第四章 接口与多态--4.2.1-4.2.2-类型转换
-4.2.3-方法的查找
--方法的查找
--第四章 接口与多态--4.2.3-方法的查找
-4.3-多态的概念
--多态的概念
--第四章 接口与多态--4.3-多态的概念
-4.4-多态的应用举例
--多态的应用举例
--第四章 接口与多态--4.4-多态的应用举例
-4.5-构造方法与多态性
--构造方法和多态性
--第四章 接口与多态--4.5-构造方法与多态性
-4.6-本章小结
--本章小结
-第四章编程作业
-课件
--课件
-5.0-导学
--5.0-导学
-5.1.1-5.1.2-异常处理的概念
--第五章 输入输出--5.1.1-5.1.2-异常处理的概念
-5.1.3-5.1.5-异常的处理
--第五章 输入输出--5.1.3-5.1.5-异常的处理
-5.2-输入输出流的概念
--输入输出流的概念
--第五章 输入输出--5.2-输入输出流的概念
-5.3.1-写文本文件
--写文本文件
--第五章 输入输出--5.3.1-写文本文件
-5.3.2-读文本文件
--读文本文件
--第五章 输入输出--5.3.2-读文本文件
-5.3.3-写二进制文件
--写二进制文件
--第五章 输入输出--5.3.3-写二进制文件
-5.3.4-读二进制文件
--读二进制文件
-5.3.5-File类
--File类
-5.3.6-处理压缩文件
--处理压缩文件
-5.3.7-对象序列化
--对象序列化
-5.3.8-随机文件读写
--随机文件读写
-5.4-本章小结
--本章小结
-课件
--课件
-6.0-导学
--导学
-6.1-Java集合框架介绍
--第六章 对象群体的组织--6.1-Java集合框架介绍
-6.2-主要接口及常用的实现类
--第六章 对象群体的组织--6.2-主要接口及常用的实现类
-6.3-常用算法
--常用算法
-6.4-数组实用方法
-6.5-基于动态数组的类型(Vector, ArrayList)
--基于动态数组的类型(Vector, ArrayList)
-6.6-遍历Collection
-6.7-Map接口及其实现
-6.8-第6章小结
--第6章小结
-课件
--课件
-7.0-导学
--导学
-7.1-绘图
--绘图
-7.2-Swing基础
--Swing基础
-7.3-Swing的层次
--Swing的层次
-7.4-布局管理
--布局管理
-7.5-内部类
--内部类
-7.6-事件处理的基本概念
-7.7-事件派发机制
--事件派发机制
-7.8-顶层容器
--7.8-顶层容器
-7.9-中间层容器(一)
-7.10-中间层容器(二)
-7.11-原子组件(一)
-7.12-原子组件(二)
-7.13-原子组件(三)
-7.14-其它Swing特性
-7.15-第7章小结
-课件
--课件