重要声明:本文章仅仅代表了作者个人对此观点的理解和表述。读者请查阅时持自己的意见进行讨论。

1、序

在 Java 编程中,I/O流的操作是必须学会的一项技能。无论是文件的复制粘贴,还是上传下载,无论是文本的读取写入,还是音视频的播放,都离不开I/O流的加持。I/O流如此重要,怎么能不了解它!本文将带你了解在Java里,如何自如的操控各种流。

2、理解

网上教程千千万,学校教材万千千,无数遍的使用水流来比喻Java里的I/O流。这无疑是一个非常恰当合适的比喻,但依旧不能解开每个人对流的疑问,当然也包括本文,不一定能被每个人理解,但希望哪怕一个人能够理解。

我也将使用水流来作比喻。现在,要将一个湖里的所有水全部转移到另一个水库里面,怎么办?当然是用抽水机啊,要么就用桶不同的挑嘛。为了能够更好地结合程序来理解,咱们假设选择了使用桶挑水过去的方案。

随即便产生了下面图案:

有了这张图,对Java里I/O的理解就会更加简单一点。见名知意,为啥叫I/O流,是因为在java中,流的操作是通过 两个类的协同操作进行完成的。

这两个分别是:

I: InputStream 输入流

O: OutputStream 输出流

下面分别进行简述:

(1)、InputStream 输入流

输入流和输出流都是相对于程序来进行称呼的。脱离了程序,不能确定某个流就是输入或输出流,下图中“桶”就相当于是程序,那么输入流是什么,一目了然:

可见,从湖泊A 到桶里的这部分水流,就可以说是输入流,但你不能单纯的认为就是这一通水就是输入流,而应该理解为:整个湖里的水,在放入桶的这个行为过程中,这时这些水对于这个桶来说是输入流。

所以同样的,在程序里,数据流在往程序里跑时这个数据流叫做输入流,承载这个数据跑到程序里面的类,是InputStream。

(2)、OutputStream 输出流

与输入流相似,想必你看了上面的输入流,你对输出流可能也有那个概念了,只不过是反其道而行之的,如图所示:

从桶里,往湖泊B倒水,这个行为过程中,所有的湖泊里的水,这可理解为输出流。在程序里,数据流在往程序外跑时,这个流叫做输出流,承载这个数据跑到外面去的类,是OutputStream。

上诉的输入流,输出流都是对于程序来说的,把桶比作是这个运输水的程序,所以在阐述是都是以“桶”为对象来阐述的。

3、代码加入

(1)、InputStream 输入流

首先讲述InputStream输入流的代码应用。InputStream是一个abstract的抽象类,抽象类是不能直接实例化对象的,所以,Java为我们贴心的实现了许许多多的、用于处理各种场景的输入流类,比较常用的FileInputStream可见名知意,它是专门为读取文件而生的文件输入流承载对象。下面是文件输入流的使用案例:

// 为了保证程序的正常,请在D盘下建立文件:file.txt,文件内容:File Inputstream test.

// FileInputStream 在 java.io 包下,如果使用文本编辑器编写代码,记得导包:import java.io.FileInputStream;

public class Test {

public static void main(String[] args) throws Exception {

// 使用指定文件构建文件来构建文件输入流。

FileInputStream fileInputStream = new FileInputStream("D:/file.txt");

// 就如同上图要把一个湖泊里面的水全部传到另一个湖泊,中间借助了一个“桶”来帮助。

// 并且,上面将“桶”比喻为整个程序。

// 现在要摈弃:将“桶”比喻为整个程序。这个概念了。

// 实际上“桶”只能充当程序里的一个变量。

// 这个变量每次能容纳一定容量的数据。

// 这里定义 datas 数组。是一个每次只能容纳4字节的“小桶”。

byte[] datas = new byte[4];

// 但是我们不能确定是不是每次重复用这只“桶”去舀水的时候都能把桶舀满。

// 就比如上边图中,当桶儿把湖泊A里的水快舀完时,有一个人提着桶去舀最后一桶水,发小并不能舀满

// 一整桶水,他索性舀了多少就带走多少了。

// 而在程序里,程序是是的,它必须要你告诉他每次舀了多少水,

// 特别是在最后一次没能舀满一“桶”水时,这个标记了舀了多少水的字段就必不可少了。

// 定义一个字段表示每次舀了多少水。

int size = 0;

// 舀水一次可能完不成,毕竟我们桶只有这么大,所以要来来回回不同的舀,即循环进行。

// 有人可能说,你定义一个超大的桶,不就可以一次搞定了。

// 答:可以是可以,但是要明白,这个过程中是要把数据保存在你电脑的内存条上的,假如你的文件有100GB,你又定义了一个100GB的桶

// 而你的电脑内存一共才16GB,程序一运行就会内存溢出的,直接报错了。

// 所以桶的大小,要根据电脑内存有多大,读取行为发生的频率大不大来自己权衡的一个数值。

// 下面开始循环读取

while (size != -1) {

// 当文件读取完成后, read 方法会返回 -1来表示已经读取完成了,所以,只要不是 -1 就一定表示数据还能继续读取。

// 输入流的读取的方法会返回当前实际读取了多少数据的大小,正合适告诉我们舀了多少水。

size = fileInputStream.read(datas);

// 此时 datas 里面的数据就已经是舀到的数据了。

// 拿到数据构建字符串:

String str = new String(datas);

// 输出结果:

System.out.print(str);

}

// 当循环完成,也就表示读取完成,水舀完了。

// 不要忘了最后调用输入流的关闭方法,你要是不调用关闭方法,就如同占着茅坑不拉屎是一样的道理。

fileInputStream.close();

}

}

运行这个程序,最后输出:File Inputstream test.

加上代码中的注释,相信理解起来非常简单。这是一个非常典型的代码编写方式,所有的输入流几乎都是这样的代码流程来进行数据的读取。

(2)、OutputStream 输出流

输入流是讲数据从程序的外部读入到程序的内部,那么输出流就是将数据从程序的内部输出到程序的外部,上面使用了一个简单的程序将外部文件“file.txt”的内容读取到了程序内部并显示,现在,我们要在程序内部设定好一个字符串,然后输出到文件中,同输入流一样,这里也采用文件相关的“FileOutputStream”文件输出流,来完成数据的输出。示列代码如下:

public class Test {

public static void main(String[] args) throws Exception {

// 准备好要输出的数据内容。

String str = "File OutputStream test.";

// 构建文件输出流:

FileOutputStream fileOutputStream = new FileOutputStream("D:/outFile.txt");

// 无论是流的输出,还是流的读取,它们操作的数据都是 byte 的二进制数据。

// 而定义的准备用于输出数据是字符串,所以,需要先从字符串转换成 byte 二进制数据。

byte[] datas = str.getBytes();

// 将数据写到输出流。

fileOutputStream.write(datas);

// 这一步很重要。

// 上面一行代码是将数据写入到了一个磁盘缓存区,内容其实(可能)还没有真的被写入到文件里。

// 这一行代码的调用,可以强制的将数据从缓存区强制的写入的文件中,所以为了保证效果,务必每次在 “关闭” 输出流前

// 记住要调用一次该方法。

fileOutputStream.flush();

// 最后不要忘了关闭输出流。

fileOutputStream.close();

}

}

运行程序,会在磁盘D盘下多出一个 outFile.txt 文件,打开这个文件,就可以看到文件内容:File OutputStream test.

你发现这个输出流并没有像输入流那样去循环的进行输出。是的,因为这里是为了让咱们快速理解输出流的使用方式,只是单独的进行单向输出,而且输出的只有几个字,我们能确定它的大小不是很大。为什么上面输入流读取的文件也很小,而我们也是用循环读取?因为我们只是在测试学习,知道这个文件不大,实际开发中,你永远不知道你要读取的文件有多大,对于我们不知道的事物,我们应该采取兼容性最大的程序代码方式去编写。所以输入时往往使用循环来读取。

现在了解了输入流,输出流,最有魅力的地方不是单独使用它们,而是将它们结合起来使用,达到更加强悍的功能。耳熟能详的的复制功能,就可以通过输入流,输出流的相互配合完成。

4、结合使用

将输入流,输出流结合起来,学会I/O流的一个关键环节,任何输出流,输入流都可以相互结合,而不一定只能是文件的输入流对上文件的输出流。假如现在我们有一个 1GB 大小的 视频文件《video.mp4》在D盘根目录,要把它复制到 E盘下。示列代码如下:

public class Test {

public static void main(String[] args) throws Exception {

// 视频文件路径。

String videoFile = "D:/video.mp4";

// 建立输入流

FileInputStream fileInputStream = new FileInputStream(videoFile);

// 准备一个小“桶”每次舀这么多数据。

byte[] datas = new byte[1024];

// 每次舀水的量

int size = 0;

// ---------------------------------------------------------------

// 准备输出文件路径

String targetFile = "E:/video.pm4";

// 建立输出流

FileOutputStream fileOutputStream = new FileOutputStream(targetFile);

// 循环的使用“小桶”舀。

while (size != -1) {

// 舀

size = fileInputStream.read(datas);

// 舀到数据,往目标倒。

// 因为我们使用 size 标记每次舀了多少水,所以这里写的时候,也要讲“桶里”有多少水这个信息

// 告诉写出的位置,这样就能拿在桶里拿到正确的数据量。

fileOutputStream.write(datas, 0, size);

}

// 完成操作,关闭输入流,关闭输出流

fileInputStream.close();

fileOutputStream.close();

// 提示完成

System.out.println("复制完成!");

}

}

执行程序,将会把D盘下的文件复制一份在E盘下,这样就完成了文件的复制,同时对文件输入流,输出流有了更深刻的印象。在Java里,流的操作中心都是围绕

read读的方法,和write写的方法,无论怎么样,只要搞清楚各个类是用来干嘛的以及明白数据流向的方向,就能轻松的理解流的操作了。

java i o是什么流_【Java】I/O流的操作、认识使用相关推荐

  1. java io流_浅谈IO流(一)-流的基本概念以及java的常见流

    对于任何程序设计语言而言,输入输出(Input/Output)系统都是非常核心的功能.程序运行需要数据,数据的获取往往需要跟外部系统进行通信,外部系统可能是文件.数据库.其他程序.网络.IO设备等等. ...

  2. feed流和瀑布流_推荐系统之Feed流UI交互设计

    前面几篇介绍了推荐系统相关的标签.画像.算法.策略,整体上看推荐系统是一个偏工程应用的领域,要想在商业产品中引入推荐系统,利用推荐系统来帮助用户过滤信息,除了构建精准高效的推荐算法外,还需要设计适合特 ...

  3. feed流和瀑布流_什么叫feed流?

    从结构来看,很多社交和资讯类app中,都使用了feed流.例如:微信的朋友圈.今日头条的推荐页.知乎的关注页等,都是此形式. feed流是一个信息出口,想要与他人或资讯建立连接,只需要刷新这一个动作, ...

  4. java8 从数组获取流_从数组到流再到Java 8

    java8 从数组获取流 不久前,我们将一些Eclipse插件项目升级到Java8.此后再也没有回头. 除其他事项外,使用lambda和streams API ,过滤,映射和查找集合中的元素变得更加容 ...

  5. java文件边读边写_[Java教程]node.js 利用流实现读写同步,边读边写

    [Java教程]node.js 利用流实现读写同步,边读边写 0 2017-09-10 13:00:14 //10个数 10个字节,每次读4b,写1blet fs=require("fs&q ...

  6. java抓取网页标题内容_[Java教程]java 网页页面抓取标题和正文

    [Java教程]java 网页页面抓取标题和正文 0 2014-07-10 09:01:30 import java.io.BufferedReader;import java.io.IOExcept ...

  7. java期末判断题题库_(java期末考试选择题题库.doc

    (java期末考试选择题题库 1.分析以下程序: 1)public class x{ 2)public static void main(String[]args){ 3)String ol=new ...

  8. Java格式化日期用斜杠_[java工具类01]__构建格式化输出日期和时间的工具类

    在之前的学习中,我写过一篇关于字符串格式化的,就主要设计到了时间以及日期的各种格式化显示的设置,其主要时通过String类的fomat()方法实现的. 我们可以通过使用不同的转换符来实现格式化显示不同 ...

  9. java中table是什么标签_[Java教程]javascript格式化table标签内容

    [Java教程]javascript格式化table标签内容 0 2015-07-12 20:00:08 项目中遇到这样的需求,一大段文章正文的html代码在手机中显示不全,原因是由于其它有table ...

  10. java技术的核心是哪个_[JAVA]《Java 核心技术》(一)

    1. unicode编码表 utf-8和unicode的互换问题 2. subString(a,b) 获得 [a,b-1]的子串 3. 易犯错误,java没有引用传递 4. ==         比较 ...

最新文章

  1. java 对象 jvm生命_JVM对象的生命周期
  2. 2019年的第三场LiveVideoStackCon有何不同?
  3. [PAT乙级]1007 素数对猜想
  4. 在Linux下查看环境变量
  5. php查看mysql最近执行过的sql_PHP获取MySQL执行sql语句的查询时间
  6. 计算机vfp实验小结,vfp实验1报告心得体会
  7. 浅谈软件需求分析中的参与者
  8. wps里面函数怎么使用_WPS表格中常用文本函数的用法
  9. Oracle数据库存储number类型数据
  10. 计算机本科生优秀毕业论文,本科毕业论文计算机
  11. c# mvc ajax txt auto,ASP.Net MVC和复制div中的自我AJAX更新局部视图/控制器
  12. 7-3 小孩子才做选择,大人全都要 (10 分)
  13. C++中关于数据小数点,取整的方法
  14. php中文拼音模糊,两种php中文字符转拼音问题解决方法
  15. Win10 虚拟桌面的使用
  16. Flutter时间转换工具类
  17. Password verification failed
  18. JSP基本语法、3个编译指令、7个动作指令、9个内置对象
  19. Android新闻客户端实训-Day1类Day2接口基操
  20. 2018CCPC吉林赛区 | 部分题解 (HDU6555 HDU6556 HDU6559 HDU6561)

热门文章

  1. C++17基本教程 第6讲 数组 (tcy)
  2. 哥伦比亚大学 自然语言处理 公开课 授课讲稿 翻译(二)
  3. ThinkPad SL410 安装XP系统需要注意的地方
  4. P1607 [USACO09FEB]Fair Shuttle G
  5. 程序员看看笑话幽默有主减压,整理了一些不错的小幽默分享出来
  6. xdebug linux,linux下配置xdebug
  7. 超强AI对话系统ChatGPT不完全案例指南
  8. STM32项目-STM32智能小车-电子设计大赛-STM32cubemx-STM32f103c8t6STM32串口通信-
  9. PHP标签的模板技术
  10. Deep SDF 、NeuS学习