前面介绍了如何使用字符流读写文件,并指出字符流工具的处理局限,进而给出随机文件工具加以改进。随机文件工具除了支持访问文件内部的任意位置,更关键的一点是通过字节数组读写文件数据,采取字节方式比起字符方式有下列两个好处:
1、文件长度以字节为单位计量,可以分配等长的字节数组,却无法分配合适长度的字符数组,因此采用字节方式便于从文件中读取数据。
2、字符流工具主要以字符为单位处理数据,意味着它适合用来读写文本文件,不适用于二进制文件(包括图片文件、音频文件、视频文件等等),而字节方式不存在此类限制。
虽说随机文件工具已经实现了以字节方式读写文件,但它更适合大文件的任意位置读写,倘若用于一般文件的处理就显得大材小用了。毕竟杀鸡焉用牛刀,何况牛刀也太笨重了,远不如普通的刀子灵活。可是字符流工具力有不逮,随机文件工具又未恰到好处,难不成还有更方便易用的工具吗?其实文件读写可以抽象为对某个设备的输入输出操作,写文件相当于向文件输出数据,读文件相当于从文件输入数据。类似的操作还有很多,例如打印文件可看作是向打印机输出待打印的文本,敲代码可看作是从键盘输入每个按键对应的字符。Java把这些相关的输入输出操作统一为I/O流,其中字母I表示输入Input,字母O表示输出Output。先前介绍的FileReader和FileWriter属于I/O流中的字符流,而以字节为单位的则是I/O流中的字节流,字节流本身是个大家族,它有两个基类,分别是输入流InputStream和输出流OutputStream,由这两个类派生出丰富多样的输入输出流,各自用于不同的业务场景。
文件字节流是输入输出流当中最常见的一种,它包括文件输出流FileOutputStream和文件输入流FileInputStream,其中FileOutputStream用来将数据写入文件,FileInputStream用来从文件读取数据,并且二者都采取字节数组保存信息。文件输出流的构造方法支持直接填入文件路径,其对象可调用write方法把字节数组写入文件,也可调用close方法关闭文件,用起来FileOutputStream像是File与FileWriter的结合体,当然就更加好用。同时不管是输出流还是输入流,它们都实现了AutoCloseable接口,故而支持try-with-resources方式的资源自动释放。下面是利用文件输出流FileOutputStream写文件的代码例子:

	private static String mFileName = "D:/test/aae.txt";
// 利用文件输出流写入文件。注意FileOutputStream处理的是字节信息
private static void writeFile() {
String str = "白日依山尽,黄河入海流。\n欲穷千里目,更上一层楼。";
// 根据指定路径构建文件输出流对象
try (FileOutputStream fos = new FileOutputStream(mFileName)) {
fos.write(str.getBytes()); // 把字节数组写入文件输出流
// 在try(...)里面创建的输入输出流,程序会在处理完成后自动关闭,所以下面的close方法不必显式调用
//fos.close(); // 关闭文件输出流
} catch (Exception e) {
e.printStackTrace();
}
}

依此类推,文件输入流的构造方法同样支持直接填入文件路径,也拥有read读文件方法和close关闭文件方法,像是File与FileReader的结合体。另外FileInputStream有几个方法值得一提,一个是skip方法,它命令当前位置跳过若干字节,注意该方法跳过的是字节数而非字符数。另一个是available方法,它返回文件当前位置后面的剩余部分大小,刚创建文件输入流对象之时调用available方法,得到的就是文件大小;如果先调用skip方法再调用available方法,得到的数值为文件大小减去跳过的字节数。下面是利用文件输入流读文件的代码例子:

	// 利用文件输入流读取文件
private static void readFile() {
// 根据指定路径构建文件输入流对象
try (FileInputStream fis = new FileInputStream(mFileName)) {
// 分配长度为文件大小的字节数组。available方法返回当前位置后面的剩余部分大小
byte[] bytes = new byte[fis.available()];
fis.read(bytes); // 从文件输入流中读取字节数组
String content = new String(bytes); // 把字节数组转换为字符串
System.out.println("content="+content);
// 在try(...)里面创建的输入输出流,程序会在处理完成后自动关闭,所以下面的close方法不必显式调用
//fis.close(); // 关闭文件输入流
} catch (Exception e) {
e.printStackTrace();
}
}

  

更多Java技术文章参见《Java开发笔记(序)章节目录

Java开发笔记(八十八)文件字节I/O流的更多相关文章

  1. Java开发笔记(十八)上下求索的while循环

    循环是流程控制的又一重要结构,“白天-黑夜-白天-黑夜”属于时间上的循环,古人“年复一年.日复一日”的“日出而作.日落而息”便是每天周而复始的生活.计算机程序处理循环结构时,给定一段每次都要执行的代码 ...

  2. Java开发笔记(九十八)利用Callable启动线程

    前面介绍了如何利用Runnable接口构建线程任务,该方式确实方便了线程代码的复用与共享,然而Runnable不像公共方法那样有返回值,也就无法将线程代码的处理结果传给外部,造成外部既不知晓该线程是否 ...

  3. Java开发学习(二十八)----拦截器(Interceptor)详细解析

    一.拦截器概念 讲解拦截器的概念之前,我们先看一张图: (1)浏览器发送一个请求会先到Tomcat的web服务器 (2)Tomcat服务器接收到请求以后,会去判断请求的是静态资源还是动态资源 (3)如 ...

  4. Java学习笔记二十八:Java中的接口

    Java中的接口 一:Java的接口: 接口(英文:Interface),在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明.一个类通过继承接口的方式,从而来继承 ...

  5. 【Java学习笔记之十八】Javadoc注释的用法

    Javadoc注释的用法 Java 文档 // 注释一行/* ...... */ 注释若干行/** ...... */ 注释若干行,并写入 javadoc 文档 通常这种注释的多行写法如下: /*** ...

  6. Java学习笔记(十八)——Java DTO

    [前面的话] 在和技术人员的交流中,各种专业术语会出现,每次都是默默的记录下出现的术语,然后再去网上查看是什么意思.最近做项目,需要使用到DTO,然后学习一下吧. 这篇文章是关于Java DTO的,选 ...

  7. .net开发笔记(十八) winform中的等待框

    winform中很多任务是需要在后台线程(或类似)中完成的,也就是说,经常容易涉及到UI界面与后台工作线程之间的交互.比如UI界面控制后台工作的执行(启动.暂停.停止等),后台工作进度在UI界面上的显 ...

  8. 安卓开发笔记(十八):实现button按钮事件的三种方法

    Android开发中有三种主要的方式用于设置View的点击事件,1.创建内部类:2.主类中实现OnClickListener接口:3.使用匿名内部类.这三种方式都用到了OnClickListener接 ...

  9. Java基础笔记(十八)——多态

    多态表示同一个操作作用在不同对象时,会有不同的结果. 多态可分为编译时多态和运行时多态. 编译时多态:方法重载,编译时就可以确定到底调用哪个方法,可以被看做一个类中的方法多态性. 运行时多态:只有在运 ...

  10. Java学习笔记(十八):static关键字

随机推荐

  1. SQL Server 锁详解

    锁是一种防止在某对象执行动作的一个进程与已在该对象上执行的其他进行相冲突的机制.也就是说,如果有其他人在操作某个对象,那么你旧不能在该对象上进行操作.你能否执行操作取决于其他用户正在进行的操作. 通过 ...

  2. 菜鸟如何反转到资深Web安全工程师

    90后理工男,计算机专业,毕业于985院校,从事Web安全工作,两年多的时间里先后跳槽3家公司,跳槽理由主要有以下几点:加班多.薪资低.工作内容枯燥,不想安于现状,寄希望于通过跳槽找到一个“钱多.活少 ...

  3. python输出彩色字体

    Python终端如何输出彩色字体 实现过程:       终端的字符颜色是用转义序列控制的,是文本模式下的系统显示功能,和具体的语言无关.       转义序列是以ESC开头,即用\033来完成(ES ...

  4. Asp.Net Core 轻松学-10分钟使用EFCore连接MSSQL数据库

    前言     在 .Net Core 2.2中 Microsoft.AspNetCore.App 默认内置了EntityFramework Core 包,所以在使用过程中,我们无需再从 NuGet 仓 ...

  5. VS2017中使用组合项目_windows服务+winform管理_项目发布_测试服务器部署

    前言:作为一名C#开发人员,避免不了常和windows服务以及winform项目打交道,本人公司对服务的管理也是用到了这2个项目的组合方式进行:因为服务项目是无法直接安装到计算器中,需要使用命令借助微 ...

  6. 微服务容错限流Hystrix入门

    为什么需要容错限流 复杂分布式系统通常有很多依赖,如果一个应用不能对来自依赖 故障进行隔离,那么应用本身就处在被拖垮的风险中.在一个高流量的网站中,某个单一后端一旦发生延迟,将会在数秒内导致 所有应用 ...

  7. ArcPy 将mxd格式转换为msd格式

    在控制程序进行地图服务更新时,如果只是修改MXD中的渲染是不行的,需要写脚本将MXD转换为MSD,替换原有的MSD文件,并重新启动地图服务,这样才能读取到新的渲染方式. 附上Python代码: # - ...

  8. redis 特性

    Redis 三大特性: Redis 支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用 Redis 不仅支持简单的 键 * 值 类型的数据,  还提供list.set.z ...

  9. SqlServer 递归查询

    --查询部门及下属部门列表 WITH TEMP --递归 AS (SELECT Id, Code, Name, ParentId FROM [dbo].[AspSysDepartments] --查询 ...

  10. ubuntu安装rpm的方法

    Ubuntu的软件包格式是deb,如果要安装rpm的包,则要先用alien把rpm转换成deb. sudo apt-get install alien #alien默认没有安装,所以首先要安装它 su ...