文章目录

    • 1. 概念
    • 2. 分类
    • 3. 应用实例
      • 3.1 文件流
      • 3.2 缓冲流
      • 3.3 转换流
      • 3.4 标准输入输出流
      • 3.5 打印流
      • 3.6 数据流
      • 3.7 对象流
      • 3.8 随机存取文件流
  • 4. Java NIO

1. 概念

Input,从硬盘读取数据到内存

Output,将内存中的数据输出到硬盘

  • 代表数据源对象或者接收数据的接收端对象
  • 本质是数据传输,根据传输的特性将流抽象为各种类,方便直观的进行数据操作
  • 作用是建立数据源与目的地的数据输送通道

2. 分类

根据数据流向分为输入流、输出流

按照数据单位分为字节流 8bit(非文本)、字符流 16bit

根据角色分为节点流(直接作用于文件上也称为文件流)、处理流(作用在已有流的基础上,对已存在的流进行包装)

  • 四个抽象基类,子类根据具体情况分派角色
  1. 处理数据单位划分
名称 特性 实例
字节流 每次读写一个字节,有中文时会出现乱码 InputStream/OutputStream
字符流 每次读写两个字节(一个字符),可正确显示中文 Reader/Write
  1. 功能划分
名称 特性 实例
节点流 从特定节点读写数据 FileInputStream
处理流 对已存在的流的连接与封装,通过封装的流的功能进行读写 BufferReader

3. 应用实例

流的操作一般分为4步

  1. File类的实例化
  2. 相应流的实例化
  3. 读入/写出操作
  4. 资源关闭

3.1 文件流

  • File类
  • FileInputStream/FileOutputStream以字节方式读写文件
  • FileReader/FileWrite以字符方式读写文件
  • 将硬盘文件以字符流形式读入内存
File file = new File("hello.txt");
try {if (!file.exists()){file.createNewFile();}
} catch (IOException e) {e.printStackTrace();
}//创建字符读取流
FileReader reader = null;
try {reader = new FileReader(file);//数据读入,若到文件末尾返回-1int data = reader.read();while (data!=-1){System.out.print((char) data);//类似迭代器循环data = reader.read();}
} catch (FileNotFoundException e) {e.printStackTrace();
} catch (IOException e) {e.printStackTrace();
} finally {//关闭流,必须手动关闭,未关闭会导致内存泄漏等问题try {if (reader!=null) {reader.close();}} catch (IOException e) {e.printStackTrace();}
}
FileReader fileReader = null;
File file = new File("hello.txt");fileReader = new FileReader(file);char[] ch = new char[5];int len;
while ((len = fileReader.read(ch)) != -1) {//这里注意 i<len 否则数组五个空间覆盖时只会覆盖前三个,后面输出还是五个,会带着上一个数组中的后两个元素for (int i = 0; i < len; i++) {System.out.print(ch[i]);}
}
if (fileReader!=null){fileReader.close();
}
  • 将内存文件写出到硬盘,纯文本文件使用字符流,非文本文件使用字节流
   /** 写出的话文件不存在会自动帮我们创建* 存在的话会对原有文件进行覆盖,因为默认追加append是false*/FileWriter fileWriter = null;File file = new File("hello.txt");
//        fileWriter = new FileWriter(file);//表示是否在原有文件内容后进行追加写入fileWriter = new FileWriter(file,true);String str = "abcdefg";fileWriter.write(str + "\n");fileWriter.write(str);if (fileWriter != null) {fileWriter.close();}
//图片视频是字节数据,需要使用字节流处理,字符流转为字节流即将char 改为 byte
//复制图片
//使用字节流复制文本文件是可以的,但也只是单纯的复制,在内存中读的时候会出现乱码File img1 = new File("1.jpg");
File img2 = new File("2.jpg");FileInputStream inputStream = new FileInputStream(img1);
FileOutputStream outputStream = new FileOutputStream(img2);byte[] b = new byte[10];
int len;
while ((len=inputStream.read(b))!=-1){for (int i = 0; i < len; i++) {System.out.println(b[i]);outputStream.write(b[i]);}
}
inputStream.close();
outputStream.close();

3.2 缓冲流

  • BufferedInputStream/BufferedOutputStream字节缓冲流
  • BufferedReader/BufferedWrite字符缓冲流
  • flush()方法,缓冲区数据写入流,先调用flush再调用close
  • 处理流的一种是缓冲流Buffered…

真实开发时不会采用基本的文件节点流,因为效率较差,往往采用缓冲流进行处理,提高流的读取写入速度

原因是内部提供了一个8192字节缓冲区常量

   File file1 = new File("1.jpg");File file2 = new File("2.jpg");FileInputStream inputStream = new FileInputStream(file1);FileOutputStream outputStream = new FileOutputStream(file2);//不可直接作用于文件上,只可以作用于已存在的流上BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);//具体读取写入过程byte[] b = new byte[10];int len;while ((len=bufferedInputStream.read(b))!=-1){for (int i = 0; i < len; i++) {bufferedOutputStream.write(b[i]);}}//关闭时先关闭外层流,再关闭内层的流,因为处理流是包着节点流的bufferedInputStream.close();bufferedOutputStream.close();//其实在关闭外层流的同时,内层流也会自动关闭,所以可以省略不写
//        inputStream.close();
//        outputStream.close();

3.3 转换流

  • InputStreamReader字节流中读取字符
  • OutputStreamWrite字符写入字节流
  • 转换流(处理流的一种)

提供字节流和字符流之间的一个转换

解码:字节—>字符(看不懂—>看得懂)

  /** 转换流使用,属于字符流,操作 char 型数组* InputStreamReader 将字节的输入流转换为字符的输入流* OutputStreamWriter 将字符的输出流转换为字节的输出流*/File file = new File("hello.txt");File outhello = new File("outhello.txt");FileInputStream fileInputStream = new FileInputStream(file);FileOutputStream fileOutputStream = new FileOutputStream(outhello);//系统默认字符集看当前IDE设定,实际编码应该按照文件存储时的字符集编码来设定参数InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "UTF-8");OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream,"gbk");char[] ch = new char[20];int len;while ((len = inputStreamReader.read(ch)) != -1) {//           for (int i = 0; i <len ; i++) {//               System.out.println(ch[i]);
//           }String str = new String(ch, 0, len);System.out.print(str);outputStreamWriter.write(str);}inputStreamReader.close();outputStreamWriter.close();

3.4 标准输入输出流

System.in//键盘输入
System.out//控制台输出

3.5 打印流

打印只能是输出

PrintStream
PrintWriter

3.6 数据流

用于读写基本数据类型的变量或字符串

DataInputStream
DataOutputStream

3.7 对象流

对象序列化机制:允许把内存中的Java对象转换成与平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。当其它程序获取了这种二进制流,就可以恢复成原来的Java对象

序列化的好处在于可将任何实现了 Serializable接口的对象转化为字节数据,使其在保存和传输时可被还原
序列化是RMI(Remote Method Invoke-远程方法调用)过程的参数和返回值都必须实现的机制,而RMI是 JavaEE的基础。因此序列化机制是JavaEE平台的基础

如果需要让某个对象支持序列化机制,则必须让对象所属的类及其属性是可序列化的 (基本数据类型都是可序列化的),为了让某个类是可序列化的,该类必须实现如下两个接口之一。否则,会抛出 NotSerializableEXception异常

Serializable
Externalizable

凡是实现 Serializable接口的类都有一个表示序列化版本标识符的静态变量serialVersionUID用来表明类的不同版本之间的兼容性。简言之,其目的是以序列化对象进行版本控制,有关各版本反序列化时是否兼容。

如果类没有显示定义这个静态变量,它的值是Java运行时环境根据类的内部细节自动生成的,一旦类原始类进行调整,则无法再反序列化。

若类的实例变量做了修改,serialVersionUID可能发生变化。故建议,进行显式声明。

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

/** 序列化时一定要先实现Serializable接口(标识接口)* 必须实现进入的一个全局常量属性,序列版本号,设定唯一标识防止还原识别时混乱,详情见Serializable源码说明*/
public class Person implements Serializable {//序列版本号,自定义一个long类型值public static final long serialVersionUID = 4752525455642L;private String name;private int age;public Person() {}public Person(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}@Overridepublic String toString() {return "Person{" + "name='" + name + '\'' + ", age=" + age + '}';}
}
 /** 将对象读出写入到数据源中* 序列化:ObjectOutputStream保存内存中的Java对象或基本数据类型到磁盘中* 反序列化:ObjectInputStream从磁盘中读取Java对象或基本数据类型到内存中* 对于声明为 static 和 transient无效*///序列化操作ObjectOutputStream objectOutputStream = new ObjectOutputStream(new FileOutputStream("data.dat"));//        objectOutputStream.writeObject("你好世界");
//        //刷新操作
//        objectOutputStream.flush();objectOutputStream.writeObject(new Person("tylt", 18));objectOutputStream.flush();objectOutputStream.close();//反序列化操作ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream("data.dat"));Object readObject = objectInputStream.readObject();//        String str = (String) readObject;
//        System.out.println(str);Person p = (Person) readObject;System.out.println(p);objectInputStream.close();

3.8 随机存取文件流

RandomAccessFile

直接继承Object,既可作为输入流也可输出流

/** r:只读(不会创建文件,只会读取已经存在的文件)* rw:读写* rwd:读写+同步内容更新* rws:读写+同步内容更新+元数据更新*/File img = new File("1.jpg");
File outimg = new File("3.jpg");
RandomAccessFile accessFile = new RandomAccessFile(img,"r");
RandomAccessFile accessOutFile = new RandomAccessFile(outimg,"rw");byte[] b = new byte[1024];
int len;
while ((len=accessFile.read(b))!=-1){for (int i = 0; i < len; i++) {System.out.println(b[i]);accessOutFile.write(b[i]);}}
accessFile.close();
accessOutFile.close();

4. Java NIO

Java NIO(New IO,Non-Blocking IO) NIO将以更加高效的方式进行文件的读写操作,因为IO是面向流的,而NIO是面向缓冲区的

Java API中提供了两套NIO,一套是针对标准输入输出NIO,另一套就是网络编程NIO

早期的Java只提供了一个File类来访问文件系统,但File类的功能比较有限,所提供的方法性能也不高。大多数方法在出错时仅返回失败,并不会提供异常信息。

NIO.2为了弥补这种不足,引入了Path接口,代表一个平台无关的平台路径,描述了目录结构中文件的位置。Path可以看成是File类的升级版本,实际引用的资源也可以不存在。

/** Files、Paths工具类* k*/
Path path = Paths.get("hello.txt");
System.out.println(path);

I/O流(Input、Output)相关推荐

  1. 关于OSD::mkfs: ObjectStore::mkfs failed with error (5) Input/output error问题的解决

    环境: ceph L版本12.2.1升级到12.2.12 这个问题是由于升级后进行12.2.12环境中的使用ceph-disk 进行osd部署时出现如下问题,执行命令 ceph-disk -v pre ...

  2. 报错解决transmission: Error: Input/Output error和ls: reading directory '': Input/output error

    transmission: Error: Input/Output error 晚上想用transmission下载新的种子时报错:Error: Input/Output error. 我很奇怪,先运 ...

  3. python3 报错 [Errno 5] Input/output error 没有stdout时使用了print

    过程描述 刚不久用 Tornado 写了一个项目,本打算部署在 Nginx 上,但是因为公司的一些原因就没有使用 Nginx,直接在命令行中启动 当我从命令行以后台的方式启动以后,是可以正常访问的 p ...

  4. colab出现input output error问题

    原因是文件太多,清理一下回收站,尝试用先从 !cp path/to/data.csv local.csv 为什么 drive.mount() 有时会失败,并提示"超时"?为什么在通 ...

  5. Debug Tensorflow: TypeError: Cannot convert a symbolic Keras input/output to a numpy array.

    问题 'Cannot convert a symbolic Keras input/output to a numpy array. ' TypeError: Cannot convert a sym ...

  6. Angular中父子组件传值@Input @Output @ViewChild最全面最简单的总结

    父组件传递给子组件: 值传递方式:@Input既可以传递数据也可以传递方法 传递数据(不举例了) 传递方法 // 父组件定义方法 parentRun(){alert('这是父组件的 run 方法'); ...

  7. html5 填表 表单 input output 与表单验证

    1.<output>     Js计算结果 <form οninput="res.value = num1.valueAsNumber*num2.valueAsNumber ...

  8. linux-x86_64 error,Linux-x86_64 Error: 5: Input/output error的问题

    今天朋友的测试库报错, ORA-27072: File I/O error, Linux-x86_64 Error: 5: Input/output error,数据块已经不能正常启动,看到 Linu ...

  9. docker中java应用new FileOutputStream直接报Input/output error

    为什么80%的码农都做不了架构师?>>>    一个docker容器中跑着java应用,是一个定时任务,每天拉取远端文件包存到本机,命名为:decrypt-20181020 就在这一 ...

  10. 硬盘故障时如何强制关机:Input/output error

    如果硬盘可能会出现锁死或坏道的故障,会造成SHELL命令的失效,包括 reboot,powoff,,shutdown,用正常的命令是没法完成重启的. 执行这些命令,会出现如下IO报错: reboot ...

最新文章

  1. JVM怎么判断对象是否存活
  2. seaborn 笔记:load_dataset
  3. [原]Java程序员的JavaScript学习笔记(12——jQuery-扩展选择器)
  4. html js坐标图,javascript – HTML5 Canvas沿着带坐标的路径拖动图像
  5. relation does not exist报错是什么意思_为什么Zookeeper天生就是一副分布式锁的胚子?...
  6. Java大数据处理的流行框架
  7. 隐藏/显示jeecg-boot 后端管理页面的右侧的系统设置
  8. 人走茶凉!三星关闭最后一家中国手机工厂 因为打不过其他国产厂商?
  9. Docker教程:使用docker配置python开发环境
  10. Java基础零碎知识点总结(持续补充)
  11. NDK编译doubango时出现错误:undefined reference to ‘stderr‘
  12. 在eclipse中修改android源码
  13. Java根类--Object类
  14. ST25读FeliCa卡记录
  15. Windows Server 2016 安装.NET Framework 3.5 错误处理
  16. 早晨随笔_早上如何调试
  17. 第一天:2个法则,你的第一桶金可以这么来
  18. java俄罗斯方块七中图形类_俄罗斯方块shell 实现
  19. 微信公众号开发:获取openId和用户信息(完整版)
  20. Python编写数字转换成中文大写

热门文章

  1. python sendkeys用法_Python Selenium 文件上传之SendKeys
  2. 三菱fx2n64mr说明书_FX2N-64MR-DS手册三菱可编程控制器FX2N-64MR-DS使用说明书 - 广州凌控...
  3. Protobuf的奇怪问题解决--Expected top - level statement (e.g message)
  4. 设置win7文件夹背景和图标
  5. Sophos XG Firewall:如何使用Windows Server 2012为企业无线身份验证配置RADIUS
  6. AYITOJ ROUND #1题解
  7. 如何把新加的分区挂载到/根目录
  8. 【FPGA——工具篇】:Xilinx_ISE_12.4安装包下载百度云网盘
  9. 一物一码二维码红包系统介绍
  10. 9.3 开发经验和屁股的关系——《逆袭大学》连载