IO流的基本介绍:

IO流的概述:

i 表示intput,是数据从硬盘文件读入到内存的过程,称之输入,负责读。

o 表示output,是内存程序的数据从内存到写出到硬盘文件的过程,称之输出,负责写。




IO流的分类:

按方向分类:

  • 输入流
  • 输出流

按流中的数据最小单位分为:按流中的数据最小单位分为:

  • 字节流: 可以操作所有类型的文件(包括音视屏图片等)
  • 字符流: 只能操作纯文本的文件(包括java文件, txt文件等)

总结流的四大类:总结流的四大类:

  • 字节输入流:以内存为基准,来自磁盘文件/网络中的数据以字节的形式读入到内存中去的流称为字节输入流。

  • 字节输出流:以内存为基准,把内存中的数据以字节写出到磁盘文件或者网络中去的流称为字节输出流。

  • 字符输入流:以内存为基准,来自磁盘文件/网络中的数据以字符的形式读入到内存中去的流称为字符输入流。

  • 字符输出流:以内存为基准,把内存中的数据以字符写出到磁盘文件或者网络介质中去的流称为字符输出




字节流的使用字节流的使用




步骤:

1、文件字节输入流

2、创建字节输入流

3、文件字节输入流: 实现类FileInputStream


作用:以内存为基准,把磁盘文件中的数据以字节的形式读取到内存中去。


构造器如下:

构造器 说明
public FileInputStream(File file) 创建字节输入流管道与源文件对象接通
public FileInputStream(String pathname) 创建字节输入流管道与源文件路径接通


示例代码:

"""

public static void main(String[] args) throws FileNotFoundException {
// 写法一: 创建字节输入流与源文件对象接通
InputStream inp = new FileInputStream(new File("/file-io-app/src/test.txt"));

}

"""

"""

public static void main(String[] args) throws FileNotFoundException {
// 写法二: 创建字节输入流管道与源文件路径接通
InputStream inp = new FileInputStream("/file-io-app/src/test.txt");

}

"""

每次读取一个字节

方法名称 说明
read() 每次读取一个字节返回,如果字节已经没有可读的返回-1

例如我们读取的记事本文件中内容是: abcd123



"""

public static void main(String[] args) throws Exception {
InputStream inp = new FileInputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt");
int a = inp.read();
System.out.println(a); // 97
System.out.println((char) a); // a
// 一次输入一个字节
System.out.println(inp.read()); // 98
System.out.println(inp.read()); // 99
System.out.println(inp.read()); // 100
System.out.println(inp.read()); // 49
System.out.println(inp.read()); // 50
System.out.println(inp.read()); // 51
// 无字节可读返回-1
System.out.println(inp.read()); // -1

}

"""


我们可以通过循环遍历出文件中的字节


"""

public static void main(String[] args) throws Exception {
InputStream inp = new FileInputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt");
int b;
while ((b = inp.read()) != -1) {
System.out.print((char) b); // abcd123
}

}

"""


每次读取一个字节存在以下问题

  • 性能较慢

  • 读取中文字符输出无法避免乱码问题。


每次读取一个数组

方法名称 说明
read(byte[] buffer) 每次读取一个字节数组, 返回读取了几个字节,如果字节已经没有可读的返回-1

定义一个字节数组, 用于接收读取的字节数

例如下面代码中, 文件中的内容是: abcd123, 每次读取三个字节, 每一次读取都会覆盖上一次数组中的内容, 但是第三次读取只读取了一个字符, 所以只覆盖了上一次读取的字符数组的第一个元素, 结果是: 312



"""

public static void main(String[] args) throws Exception {
InputStream inp = new FileInputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt");
// 定义一个长度为3的字节数组
byte[] arr = new byte[3]; // 第一次读取一个字节数组
int len1 = inp.read(arr);
System.out.println("读取字节数: " + len1); // 读取字节数: 3
// 对字节数组进行解码
String res1 = new String(arr);
System.out.println(res1); // abc // 第二次读取一个字节数组
int len2 = inp.read(arr);
System.out.println("读取字节数: " + len2); // 读取字节数: 3
// 对字节数组进行解码
String res2 = new String(arr);
System.out.println(res2); // d12 // 第三次读取一个字节数组
int len3 = inp.read(arr);
System.out.println("读取字节数: " + len3); // 读取字节数: 1
// 对字节数组进行解码
String res3 = new String(arr);
System.out.println(res3); // 312 // 无字节可读返回-1
System.out.println(inp.read()); // -1

}

"""


1、String第二个参数可以指定开始位置, 第三个参数可以指定结束位置, 可以用这两个参数解决第三次读取的弊端

2、并且循环改进优化代码



"""

public static void main(String[] args) throws Exception {
InputStream inp = new FileInputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt"); byte[] arr = new byte[3];
int len;
while ((len = inp.read(arr)) != -1) {
String res = new String(arr, 0, len);
System.out.print(res); // abcd123
}

}

"""


每次读取一个数组存在的弊端:

1、读取的性能得到了提升

2、读取中文字符输出无法避免乱码问题。


一次读取全部字节

为解决中文乱码问题我们可以定义一个与文件一样大的字节数组,一次性读取完文件的全部字节。

弊端: 如果文件过大,字节数组可能引起内存溢出。


解决方案一:

自己定义一个字节数组与文件的大小一样大,然后使用读取字节数组的方法,一次性读取完成。


"""

public static void main(String[] args) throws Exception {
File file = new File("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt");
InputStream inp = new FileInputStream(file); // 创建一个与文件大小一样的字节数组
byte[] arr = new byte[(int) file.length()]; // 读取文件, 获取读取的字节长度
int len = inp.read(arr);
System.out.println(len); // 252 // 对字节数组进行解码
String res = new String(arr);
System.out.println(res);
// abcd123我爱Java学习Java.abcd123我爱Java学习Java.abcd123我爱Java学习Java.
// abcd123我爱Java学习Java.abcd123我爱Java学习Java.abcd123我爱Java学习Java.
// abcd123我爱Java学习Java.abcd123我爱Java学习Java.abcd123我爱Java学习Java.

}

"""


方式二:

官方为字节输入流InputStream提供了如下API可以直接把文件的全部数据读取到一个字节数组中



方法名称 说明
readAllBytes() 直接读取当前字节输入流对应的文件对象的全部字节数据, 然后装到一个字节数组返回


"""

public static void main(String[] args) throws Exception {
InputStream inp = new FileInputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt"); // 获取文件的全部字节, 并返回一个字节数组
byte[] arr = inp.readAllBytes();
// 对字节数组进行解码
String res = new String(arr);
System.out.println(res);
// abcd123我爱Java学习Java.abcd123我爱Java学习Java.abcd123我爱Java学习Java.
// abcd123我爱Java学习Java.abcd123我爱Java学习Java.abcd123我爱Java学习Java.
// abcd123我爱Java学习Java.abcd123我爱Java学习Java.abcd123我爱Java学习Java.

}

"""


文件字节输出流

创建字节输出流

文件字节输出流: 实现类FileOutputStream

作用:以内存为基准,把内存中的数据以字节的形式写出到磁盘文件中去的流。



构造器如下:

构造器 说明
FileOutputStream(File file) 创建字节输出流管道与源文件对象接通
FileOutputStream(String filepath) 创建字节输出流管道与源文件路径接通

"""

public static void main(String[] args) throws Exception {
// 写法一: 创建输出流与源文件对象接通
OutputStream oup = new FileOutputStream(new File("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt"));

}

"""



"""

public static void main(String[] args) throws Exception {
// 写法二: 创建输出与源文件路径接通(常用)
OutputStream oup = new FileOutputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt");

}

"""


写入文件输出流

文件字节输出流写数据出去的API:

方法名称 说明
write(int a) 写一个字节出去
write(byte[] buffer) 写一个字节数组出去
write(byte[] buffer , int pos , int len) 写一个字节数组的一部分出去

流的刷新与关闭API:

方法 说明
flush() 刷新流,还可以继续写数据
close() 关闭流,释放资源,但是在关闭之前会先刷新流。一旦关闭,就不能再写数据

注意: 写入数据必须刷新数据, 流使用完成后需要关闭


写一个字节出去



"""

public static void main(String[] args) throws Exception {
OutputStream oup = new FileOutputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt"); oup.write('a');
// 支持写入编码
oup.write(97);
// 汉字占三个字节, 所以该方法不可以写入汉字
// oup.write('我'); // 写数据必须刷新数据
oup.flush();
// 刷新流后可以继续写入数据
oup.write('b');
// 使用完后需要关闭流, 关闭后不能再写入数据
oup.close();

}

"""


写一个字节数组出去


"""

public static void main(String[] args) throws Exception {
OutputStream oup = new FileOutputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt"); // 定义一个字节数组
byte[] arr = {'a', 98, 'b', 'c'};
// 写入中文, 需要将中文编码成字节数组
byte[] chinese = "中国".getBytes(); // 写入英文字节数组
oup.write(arr);
// 写入中文字节数组
oup.write(chinese); // 关闭流(关闭之前会刷新)
oup.close();

}

"""


写入一个字节数组的一部分


"""

public static void main(String[] args) throws Exception {
OutputStream oup = new FileOutputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt"); // 定义一个字节数组
byte[] arr = {'a', 98, 'b', 'c'};
// 写入数组的第二个和第三个元素
oup.write(arr, 1, 2); // 关闭流(关闭之前会刷新)
oup.close();

}

"""


补充知识:

补充一: 写入内容时, 如果需要换行可将\r\n(window支持输入\n但是有些系统不支持, 为了具备通用性使用\r\n)转为字节数组写入, 实现换行效果

"""

public static void main(String[] args) throws Exception {
OutputStream oup = new FileOutputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt"); // 定义一个字节数组
byte[] arr = {'a', 98, 'b', 'c'};
oup.write(arr);
// 写入换行
oup.write("\r\n".getBytes());
// 写入数组的第二个和第三个元素
oup.write(arr, 1, 2); // 关闭流(关闭之前会刷新)
oup.close();

}

"""


补充二: 当写入文件时, 会先将原来文件清空, 再写入新的数据, 如果我们想在原来文件数据的基础上追加新的数据, 这时候就需要将构造器的第二个参数设置为true


构造器 说明
FileOutputStream(File file,boolean append) 创建字节输出流管道与源文件对象接通,可追加数据
FileOutputStream(String filepath,boolean append) 创建字节输出流管道与源文件路径接通,可追加数据

"""

public static void main(String[] args) throws Exception {
// 设置为true即可
OutputStream oup = new FileOutputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.txt", true);

}

"""


文件拷贝练习文件拷贝练习

需求:

把test.pdf文件复制到其他目录下的newtest.pdf文件中

思路分析:

根据数据源创建字节输入流对象

根据目的地创建字节输出流对象

读写数据,复制视频

释放资源



示例代码:

"""

public static void main(String[] args) {
try {
// 创建要复制文件的字节输入流
InputStream inp = new FileInputStream("/Users/chenyq/Documents/learn_Java/code/file-io-app/src/test.pdf");
// 创建目标路径的字节输出流
OutputStream oup = new FileOutputStream("/Users/chenyq/Documents/newtest.pdf"); // 使用文件输入流获取要复制文件的全部数据的字节数组
byte[] arr = inp.readAllBytes();
// 使用文件输出流将字节数组写入目标文件
oup.write(arr);
System.out.println("复制成功!"); // 释放资源
inp.close();
oup.close();
} catch (IOException e) {
e.printStackTrace();
}

}

"""


疑问: 字节流可以拷贝什么类型的文件?

任何文件的底层都是字节,拷贝是一字不漏的转移字节,只要前后文件格式、编码一致没有任何问题。

总结: 字节流适合拷贝文件, 但是不适合进行中文的输出输出


Java IO流 - 字节流的使用详细介绍的更多相关文章

  1. Java IO流-字节流

    2017-11-05 17:48:17 Java中的IO流按数据类型分类分为两种,一是字节流,二是字符流.字符流的出现是为了简化文本数据的读入和写出操作. 如果操作的文件是文本文件,那么使用字符流会大 ...

  2. Java—IO流 字节流

    IO流(输入流.输出流),又分为字节流.字符流. 流是磁盘或其它外围设备中存储的数据的源点或终点. 输入流:程序从输入流读取数据源.数据源包括外界(键盘.文件.网络…),即是将数据源读入到程序的通信通 ...

  3. java IO流——字节流

    字节流主要操作byte类型数据,以byte数组为准,主要操作类有InputStream(字节输入流).OutputSteam(字节输出流)由于IputStream和OutputStream都是抽象类, ...

  4. java IO之字节流和字符流-Reader和Writer以及实现文件复制拷贝

    接上一篇的字节流,以下主要介绍字符流.字符流和字节流的差别以及文件复制拷贝.在程序中一个字符等于两个字节.而一个汉字占俩个字节(一般有限面试会问:一个char是否能存下一个汉字,答案当然是能了,一个c ...

  5. Java IO流详解(一)——简单介绍

    文件在程序中是以流的形式来传输的.所以用Java来传输文件就得使用到Java IO流. 1.流的概念和作用 流:代表任何有能力产出数据的数据源对象或者是有能力接受数据的接收端对象<Thinkin ...

  6. 《二》Java IO 流的分类介绍

    一.根据流向分为输入流和输出流: 注意输入流和输出流是相对于程序而言的. 输出:把程序(内存)中的内容输出到磁盘.光盘等存储设备中        输入:读取外部数据(磁盘.光盘等存储设备的数据)到程序 ...

  7. java io流(字节流)复制文件

    java io流(字节流) 复制文件 //复制文件 //使用字节流 //复制文本文件用字符流,复制其它格式文件用字节流 import java.io.*; public class Index{ pu ...

  8. 【转载】JAVA IO 流的总结

    来自http://www.cnblogs.com/oubo/archive/2012/01/06/2394638.html,写的很详细 Java流操作有关的类或接口: Java流类图结构: 流的概念和 ...

  9. Java基础17:Java IO流总结

    更多内容请关注微信公众号[Java技术江湖] 这是一位阿里 Java 工程师的技术小站,作者黄小斜,专注 Java 相关技术:SSM.SpringBoot.MySQL.分布式.中间件.集群.Linux ...

  10. Java IO 流总结篇

    1. 写在前面的话 I/O ,I 是 Input (输入)的缩写,O是Output (输出) 的缩写,众所周知,人与人之间想要沟通交流,就需要讲彼此都能听懂的语言,比如大家都统一说英语. 人类如果想和 ...

随机推荐

  1. Redis 数据类型 Stream

    Redis 数据类型 Stream Redis 常用命令,思维导图 >>> Redis Stream 是 Redis 5.0 版本新增加的数据结构. Redis Stream 主要用 ...

  2. Windows 与 虚拟机VirtualBox 共享挂载

    在自己的电脑上安装了虚拟机后,经常会有需要把Windows这边的文件或文件夹拷贝到虚拟机上,简单记录一下. 如下图,设备--共享文件夹 然后在Windows上创建共享文件夹 执行命令 sudo mkd ...

  3. 用PHPstudy nginx 配置tp6 隐藏访问链接中的index.php

    在server 里面加上如下这个判断就好了 if (!-e $request_filename){ rewrite ^(.*)$ /index.php?s=$1 last; break; 配置在对应网 ...

  4. CS144 计算机网络 Lab1:Stream Reassembler

    前言 上一篇博客中我们完成了 Lab0,使用双端队列实现了一个字节流类 ByteStream,可以向字节流中写入数据并按写入顺序读出数据.由于网络环境的变化,发送端滑动窗口内的数据包到达接收端时可能失 ...

  5. 长连接Netty服务内存泄漏,看我如何一步步捉“虫”解决

    作者:京东科技 王长春 背景 事情要回顾到双11.11备战前夕,在那个风雨交加的夜晚,一个急促的咚咚报警,惊破了电闪雷鸣的黑夜,将沉浸在梦香,熟睡的我惊醒. 一看手机咚咚报警,不好!有大事发生了!电话 ...

  6. Python 变量作用域和列表

    变量作用域 变量由作用范围限制 分类:按照作用域分类 全局(global):在函数外部定义 局部(local):在函数内部定义 变量的作用范围: 全局变量:在整个全局范围有效 全局碧昂量在局部可以使用 ...

  7. Jenkins-Email Extension Plugin邮件配置

    前言:此文为 Jenkins 2.346 版本 一.配置准备 1.安装 Email Extension Plugin 插件 二.配置邮件 Email Extension Plugin 部分 1.进入系 ...

  8. MySQL WorkBench更换界面成中文的方法

    菜单页面更换 文章目录 菜单页面更换 汉化文件的xml文件我放在下面的网盘中了 1.找到MySQL的安装位置, 总结 汉化文件的xml文件我放在下面的网盘中了 1.找到MySQL的安装位置, 具体安装 ...

  9. Prism Sample 15-FilteringEvents

    例14演示了怎样事件聚合器怎样发布与接收信息. 例15增加了一个事件的过滤功能,即设定一个条件,符合的才接收. _ea.GetEvent<MessageSentEvent>().Subsc ...

  10. UIOTOS:一款无门槛的前端0代码搭建工具

    什么是UIOTOS? UIOTOS中文名称前端大师,是一款基于图形技术的前端0代码工具,支持通过连线和嵌套无门槛来搭建各类复杂的的交互界面,包括后台管理系统.组态数据大屏等,实现跟代码开发媲美的效果. ...