IO流

水流 特点
连续性 逝者如斯夫,不舍昼夜;
方向性 一江春水向东流。水往低处流。百川东到海,何时复西归?少壮不努力,老大徒伤悲!
源头尽头 唯有源头活水来;覆水难收

Java里的IO也有这样的特点。

IO:数据从硬盘流向内存(Input),或者从内存流向硬盘(Output)。

IO流分类:

按照流的流向来分:输入流、输出流。
|-输入流:读入内存。
|-输出流:写出到硬盘等设备。

按操作数据单元分:字节流、字符流
|-字节流:8位
|-字符流:16位

按流的角色分:节点流、处理流。
|-节点流:特定的IO设备(如硬盘),也叫低级流
|-处理流:经过封装的流,也叫高级流、包装流,可以消除不同节点流的差异(典型的装饰器模式)

Java的IO流有40多个类,高抽象层的基类有四个:

字节流 字符流
输入流 InputStream Reader
输出流 OutputStream Writer

字节流

字节流:100100011010100010

可以操作所有文件,包括文本文件、视频、音频、压缩文件等等都可以用字节流读写。

两个重要的抽象类:

(1)抽象类 java.io.OutputStream,是输出字节流的所有类的超类

|--API方法摘要:
|--|--void write(byte[] b) 将 b.length 个字节从指定的 byte 数组写入此输出流。
|--|--abstract void write(int b) 将指定的字节写入此输出流。
|--|--void close() 关闭此输出流并释放与此流有关的所有系统资源。

(2)抽象类 java.io.InputStream,是输入字节流的所有类的超类

|--API方法摘要:
|--|--abstract int read()从输入流中读取数据的下一个字节。
|--|--int read(byte[] b) 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b 中。
|--|--void close() 关闭此输入流并释放与该流关联的所有系统资源。

FileOutputStream写文件

// 文件输出流。完整地说,是文件字节输出流。
public class FileOutputStream extends OutputStream

步骤:
1.创建流对象
2.调用write方法,把数据写入文件
3.释放资源

import java.io.*;
public class 文件字节输出流 {public static void main(String[] args) {File file = new File("文件字节输出流.txt"); // 创建文件对象try {// (1)构造:通过文件对象创建文件输出流对象FileOutputStream fos = new FileOutputStream(file);// (2)写入文件// (2.1)write(int b) 将"单个字节"写入到文件中for (int i = 49; i < 97; i++) {fos.write(i);fos.write(' ');}// (2.2)write(byte[] b) 将"字节数组"中的数据全部写入文件byte[] buffer = "I Love Java,你呢?".getBytes();fos.write(buffer);// (3)关闭流fos.close();} catch (IOException e) {e.printStackTrace();}}
}

追加:

使用构造方法:FileOutputStream(File file, boolean append)

            // 构造:通过文件对象创建文件输出流对象// 附加第二个参数true,指定进行文件追加,默认为不追加fos = new FileOutputStream(file, true);

回车换行:

CR(carriage return),回车,\r
LF(line feed),换行,\n

windows:\r\n
linux或unix:\n
mac:\r

FileInputStream读文件

public class FileInputStream extends InputStream
import java.io.*;
public class 文件字节输入流 {static final int C_CONDITION = 2;public static void main(String[] args) {try {File file = new File("testRead.dat"); // 创建文件对象// 【1】创建输入流对象,相当于打开文件FileInputStream fis = new FileInputStream(file);if (C_CONDITION == 1) {// 【2】.read():读取单个字节for (int i = 0; i < file.length(); i++) {// 循环读取"字节",转为字符输出,英文没问题int read = fis.read();char ch = (char) read;System.out.print(ch);}System.out.println();} else {// 【2】.read(byte[] b):读取文件中的数据到字节数组// 根据文件的字节长度创建字节数组long len = file.length();byte[] buf = new byte[(int) len];fis.read(buf);// 利用字节数组创建字符串String str = new String(buf);System.out.println(str);}// 【3】关闭流fis.close();} catch (FileNotFoundException fnfe) {System.out.println("文件打开失败。");} catch (IOException ioe) {ioe.printStackTrace();}}
}

复制文件

package ahjava.io;
import java.io.*;
public class 复制文件 {public static void main(String[] args) {字节流复制文件();}static void 字节流复制文件() {File srcFile = new File("testRead.dat"); // 源文件对象File destFile = new File("testCopy.java"); // 目标文件对象if (destFile.exists()) {// 判断目标文件是否存在,存在则删除destFile.delete();}// 目标文件不存在才复制try {destFile.createNewFile();// 创建文件输入/输出流对象FileInputStream fis = new FileInputStream(srcFile);FileOutputStream fos = new FileOutputStream(destFile);// 创建字节数组,作为临时缓冲byte[] buf = new byte[128];System.out.println("开始复制文件...");int len = -1;// 循环从文件输入流中读取数据while ((len = fis.read(buf)) != -1) {System.out.println(len);// 写入到文件输出流中fos.write(buf, 0, len);}System.out.println("文件复制成功!");fis.close(); // 关闭流fos.close();} catch (IOException e) {e.printStackTrace();}}
}

上面的代码有哪些风险?

改进版:

    static void 字节流复制文件2() {// 1.close()提取到finally中// 2.提取FilexxxStream对象// 3.初始化(否则不准close)// 4.close()时加判空语句FileInputStream fis = null;FileOutputStream fos = null;File srcFile = new File("testRead.dat"); // 源文件对象File destFile = new File("testCopy.java"); // 目标文件对象if (destFile.exists()) {// 判断目标文件是否存在,存在则删除destFile.delete();}// 目标文件不存在才复制try {destFile.createNewFile();fis = new FileInputStream(srcFile);fos = new FileOutputStream(destFile);// 创建字节数组,作为临时缓冲byte[] buf = new byte[128];System.out.println("开始复制文件...");int len = -1;// 循环从文件输入流中读取数据while ((len = fis.read(buf)) != -1) {System.out.println(len);// 写入到文件输出流中fos.write(buf, 0, len);}System.out.println("文件复制成功!");// 关闭流} catch (IOException e) {e.printStackTrace();} finally {if (fis != null) {try {fis.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}fis = null;}if (fos != null) {try {fos.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}fos = null;}}}

又臭又长!

Java 7异常处理写法:

try后面增加括号,其中定义流对象,该流对象仅在try中有效,执行完毕自动释放,不需要写finally。

try(流对象){
} catch (IOException e) {
}

具体代码如下:

    static void 字节流复制文件3() {File srcFile = new File("testRead.dat"); // 源文件对象File destFile = new File("testCopy.java"); // 目标文件对象if (destFile.exists()) {// 判断目标文件是否存在,存在则删除destFile.delete();}// try(流对象)try (FileInputStream fis = new FileInputStream(srcFile);FileOutputStream fos = new FileOutputStream(destFile)) {destFile.createNewFile();// 创建字节数组,作为临时缓冲byte[] buf = new byte[128];System.out.println("开始复制文件...");int len = -1;// 循环从文件输入流中读取数据while ((len = fis.read(buf)) != -1) {System.out.println(len);// 写入到文件输出流中fos.write(buf, 0, len);}System.out.println("文件复制成功!");// 关闭流} catch (IOException e) {e.printStackTrace();}}

*Java9异常处理写法

觉得try里的代码太繁琐,try()中可以引入外部的变量:

FileInputStream fis = new FileInputStream(srcFile);
FileOutputStream fos = new FileOutputStream(destFile);
try  (fis;fos){...}
// ↑ 理想状态,代码并不能这么写

然而,fis、fos本身需要抛异常,如果直接try...catch,这两个变量会变成另外的try中的局部变量;
如果把声明提取到try之外,try (fis;fos)又需要变量是final的

        FileInputStream fis = null;FileOutputStream fos = null;try {fis = new FileInputStream(srcFile);fos = new FileOutputStream(destFile);} catch (FileNotFoundException e1) {e1.printStackTrace();}try  (fis;fos) {

CopyFile.java:20: 错误: 用作 try-with-resources 资源的变量 fis 既不是最终变量, 也不是实际上的最终变量
try (fis;fos) {
^
CopyFile.java:20: 错误: 用作 try-with-resources 资源的变量 fos 既不是最终变量, 也不是实际上的最终变量
try (fis;fos) {

所以,fis和fos需要往外抛出异常,外部调用的地方又需要捕获异常。比不用此功能还要麻烦。可运行代码如下:

import java.io.*;
public class CopyFile{public static void main(String[] args) {try {copyJDK9();} catch (FileNotFoundException e) {e.printStackTrace();}}static void copyJDK9() throws FileNotFoundException {File srcFile = new File("testRead.dat");File destFile = new File("testCopy.java");if (destFile.exists()) {destFile.delete();}FileInputStream fis = new FileInputStream(srcFile);FileOutputStream fos = new FileOutputStream(destFile);try  (fis;fos) {destFile.createNewFile();byte[] buf = new byte[128];System.out.println("start copy...");int len = -1;while ((len = fis.read(buf)) != -1) {System.out.println(len);fos.write(buf, 0, len);}System.out.println("success");} catch (IOException e) {e.printStackTrace();}}
}

转载于:https://www.cnblogs.com/tigerlion/p/11179223.html

Java基础教程——字节流相关推荐

  1. Java基础教程:反射基础

    Java基础教程:反射基础 引入反射 反射是什么 能够动态分析类能力的程序称为反射. 反射是一种很强大且复杂的机制. Class类 在程序运行期间,Java运行时系统始终为所有对象维护一个被称为运行时 ...

  2. Java基础教程:多线程基础(3)——阻塞队列

    Java基础教程:多线程基础(3)--阻塞队列 快速开始 引入问题 生产者消费者问题是线程模型中的经典问题:生产者和消费者在同一时间段内共用同一存储空间,生产者向空间里生产数据,而消费者取走数据. 模 ...

  3. Java基础教程:面向对象编程[2]

    Java基础教程:面向对象编程[2] 内容大纲 访问修饰符 四种访问修饰符 Java中,可以使用访问控制符来保护对类.变量.方法和构造方法的访问.Java 支持 4 种不同的访问权限. default ...

  4. Java基础教程(12)--深入理解类

    一.方法的返回值   当我们在程序中调用方法时,虚拟机将会跳转到对应的方法中去执行.当以下几种情况发生时,虚拟机将会回到调用方法的语句并继续向下执行: 执行完方法中所有的语句: 遇到return语句: ...

  5. Java基础教程:Lambda表达式

    Java基础教程:Lambda表达式 引入Lambda Java 是一流的面向对象语言,除了部分简单数据类型,Java 中的一切都是对象,即使数组也是一种对象,每个类创建的实例也是对象.在 Java ...

  6. Java基础教程:注解

    Java基础教程:注解 本篇文章参考的相关资料链接: 维基百科:https://zh.wikipedia.org/wiki/Java%E6%B3%A8%E8%A7%A3 注解基础与高级应用:http: ...

  7. Java基础教程-刘刚-专题视频课程

    Java基础教程-2704人已学习 课程介绍         Java基础教程是一套入门Java开发语言的课程,它是由浅入深的介绍Java基础内容,包括Java介绍.基本类型及运算符.控制执行流程.字 ...

  8. java基础教程(一)

    Java 开发环境配置 在进行Java开发之前,需要先安装Java开发工具包(JDK)和集成开发环境(IDE).以下是Java开发环境的配置和搭建步骤: 下载JDK:访问Oracle官方网站,选择适合 ...

  9. java基础教程之实现一键分享朋友圈

     java最新技术,实现一键分享朋友圈,下面给大家演示一下 作为十余年java老司机,根据多年经验,自己录制的学习视频,我往对你们有所帮助, 有技术问题或者面试方面交流的可以加我微信renlliang ...

  10. Java基础教程-10-多线程

    Java基础教程-10-多线程 1. 多线程 我们在之前,学习的程序在没有跳转语句的前提下,都是由上至下依次执行,那现在想要设计一个程序,边打游戏边听歌,怎么设计? 要解决上述问题,咱们得使用多进程或 ...

最新文章

  1. 程序员也需要工匠精神
  2. linux下递归修改目录/文件权限命令
  3. C++ Primer 5th笔记(chap 10)泛型算法 :特定容器算法list
  4. java面向对象编程知识点总结
  5. 检测到在集成的托管管道模式下不适用的 ASP.NET 设置。
  6. easyui带表单的弹窗效果制作
  7. 【最全解析】1050 螺旋矩阵 (25分)
  8. 前端学习(1066):ES6里面的三个注意点1
  9. mysql数据存储和函数_MySQL数据库——存储和函数
  10. 解决:Gitlab上出现“You won‘t be able to pull or push project code via SSH until you add an SSH key to you
  11. Symbol()类型的定义及特点
  12. windows系统 Git Server git服务器自己搭建 (基于 Gitblit or Gogs )
  13. Atitit 发帖机实现(2)---usrQBN2243 文本解析到对象协议规范
  14. 大白话解析模拟退火算法、遗传算法
  15. 华为电脑Linux进pe,华为笔记本(HuaWei)如何进入BIOS设置U盘启动?
  16. 巨量创意signature
  17. 斯坦福发布3D街景数据集:8个3D城市模型+2500万图像+1.18亿图像配对
  18. 漫画:用木兰从军说外观模式
  19. 客户端单周发版下的多分支自动化管理与实践
  20. hdf知道这些就够了

热门文章

  1. python如何筛选数据_python如何在列表、字典中筛选数据
  2. defunct 进程占用端口_纯干货:23个服务器常见问题处理方法!
  3. asp.net mvc mysql 开源项目_【开源项目SugarSite】ASP.NET MVC+ Layui+ SqlSugar+RestSharp项目讲解...
  4. cmake 交叉编译_如何使用CMake编译RTT微内核
  5. 【LeetCode】205 Isomorphic Strings (c++实现)
  6. 食品安全和大数据物联网有什么关系
  7. TensorFlow 变量共享: get_variable
  8. 比特币技术Base58
  9. BZOJ2769 : YY的快速排序
  10. 使用CHM文档 采集随笔(续)