Java IO流 - 字节流的使用详细介绍

文章目录

    • IO流的基本介绍
    • 字节流的使用
      • 文件字节输入流
        • 创建字节输入流
        • 每次读取一个字节
        • 每次读取一个数组
        • 一次读取全部字节
      • 文件字节输出流
        • 创建字节输出流
        • 写入文件输出流
      • 文件拷贝练习

IO流的基本介绍

IO流的概述:

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

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

在这里插入图片描述

IO流的分类:

按方向分类:

  • 输入流
  • 输出流

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

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

总结流的四大类:

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

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

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

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

在这里插入图片描述

字节流的使用

在这里插入图片描述

文件字节输入流

创建字节输入流

文件字节输入流: 实现类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); // 97System.out.println((char) a); // a// 一次输入一个字节System.out.println(inp.read()); // 98System.out.println(inp.read()); // 99System.out.println(inp.read()); // 100System.out.println(inp.read()); // 49System.out.println(inp.read()); // 50System.out.println(inp.read()); // 51// 无字节可读返回-1System.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// 无字节可读返回-1System.out.println(inp.read()); // -1
}

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

并且循环改进优化代码

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}
}

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

读取的性能得到了提升

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


一次读取全部字节

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

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

例如读取如下图这样一个文件

在这里插入图片描述

方式一:

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

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();}
}

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

任何文件的底层都是字节,拷贝是一字不漏的转移字节,只要前后文件格式、编码一致没有任何问题。
总结: 字节流适合拷贝文件, 但是不适合进行中文的输出输出

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/252360.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

字节流(IO流)概述、字节流(写入/输出)数据(3种)和换行、追加写入、异常处理办法、字节缓冲流、字节流复制图片视频案例

目录 IO流概述和分类字节流写入数据(OutputStream)FileOutputStream字节流写数据的3种方式 字节流写入数据的两个小问题字节流写数据如何换行字节流如何实现追加写入 字节流写入数据加入异常处理字节流读取数据(InputStream)FileI…

字节流

字节流 根据数据的流向分为:输入流和输出流。 输入流 :把数据从其他设备上读取到内存中的流。输出流 :把数据从内存 中写出到其他设备上的流。 格局数据的类型分为:字节流和字符流。字节流 :以字节为单位&#xff0c…

1、字节流详解

文章目录 一、字节流1、字节输出流:OutputStream2、字节输入流:InputStream3、使用字节流复制数据4、字节缓冲流 一、字节流 文件字节流 字节流的两个抽象父类:字节输出流:OutputStream和字节输入流:InputStream 1、字…

PS美工教程:制作真实水面倒影效果详细步骤

倒影效果是电商海报和广告类海报常用的表现手法,倒影可以填充画面的空白区域和营造真实的视觉感受,给受众带来更好的视觉体验。 在海报合成中倒影效果可谓是必不可少的存在,那今天潇洒模具学院的老师就教大家通过PS自带的功能打造出真实的环…

CSS图片倒影效果

先看一下效果图 废话不多说直接上代码 <!DOCTYPE html> <html><head><meta charset"utf-8"><title></title><style lang"scss">img {-webkit-box-reflect: below 0px -webkit-linear-gradient(bottom, rgba(25…

3、水面倒影效果

水面倒影效果 概要 我们会使用 Matplotlib 的 pyplot 模块创建图并显示图像&#xff1a; 用以下魔术命令&#xff0c;以便将图像显示在笔记本中而不是在新的显示窗口中&#xff1a; 如果要显示彩色图像&#xff0c;可以使用以下命令将图像从 BGR 转换为 RGB。 最后使用 plt…

CSS3实现倒影效果

css的功能很强大&#xff0c;可以实现很多效果。比如图像的倒影和文字的倒影等&#xff0c;利用的是box-reflect&#xff0c;因为浏览器兼容问题&#xff0c;目前主要采用-webkit-box-reflect来实现&#xff08;谷歌浏览器&#xff09;。 倒影的属性&#xff1a; box-reflect&…

HTML里面设置文本倒影,文字倒影怎么做

现在的文字如果仅仅是在一个平面上,不加任何效果,那就真的是太死板、太单调了,尤其追求艺术的小伙伴们啊,细心的话你就会发现那些神马广告之类的文字都讲究有个性,让人过目不忘的效果,有木有!那么接下来就教大家制作文字效果,就是文字倒影效果制作。广告时间: 人物素描…

倒影(reflections)效果的实现

1、简介 当站在湖畔岸边或者镜子面前的时候&#xff0c;都可以看到倒着的自己&#xff0c;那种效果就叫倒影&#xff0c;或者叫镜面反射。在SPE中也支持这种效果&#xff0c;实现的基本思路是把物体根据反射平面镜像之后再绘制一遍&#xff0c;绘制镜像时有几个问题需要注意&a…

渐变加蒙版做倒影

平面设计是PHOTOSHOP应用最为广泛的领域&#xff0c;无论是我们正在阅读的图书封面&#xff0c;还是大街上看到的招帖、海报&#xff0c;这些具有丰富图像的平面印刷品&#xff0c;基本上都需要PHOTOSHOP软件对图像进行处理。用Photoshop 为图片添加倒影&#xff0c;这个效果不…

联想IBM ThinkPad X201i 笔记本显示屏上方中间的键盘灯不亮解决办法

这款小黑&#xff0c;不记得13年还是14年买的&#xff0c;当年就要7千大洋&#xff0c;那时候觉得很贵咬牙买了下来&#xff0c;今天回头看来贵有贵的道理。因为现在用起来还是很爽&#xff0c;去年安装Win10&#xff0c;然后在上面开发JavaEE项目&#xff0c;很快、畅顺。最近…

ibm 服务器 总显示f1,联想ThinkPad笔记本中F1/F4键盘指示灯一直常亮着如何解决

有不少使用联想ThinkPad笔记本的小伙伴们在使用电脑的时候&#xff0c;发现遇到这样一个情况&#xff0c;就是键盘上的F1/F4键盘状态指示灯常亮&#xff0c;按FNESC组合键也无法取消&#xff0c;按FN和对应的功能键也不行&#xff0c;这可该怎么解决呢&#xff0c;一般是由于热…

联想拯救者 Lenovo Legion 通电自启 插电自启 通电开机 插电开机 Wake on AC

联想拯救者 Lenovo Legion 通电自启 插电自启 通电开机 插电开机 Wake on AC 文章目录 联想拯救者 Lenovo Legion 通电自启 插电自启 通电开机 插电开机 Wake on AC说明一、我的电脑二、详细过程1.BIOS选项2.查阅改BIOS的资料3.修改BIOS失败4.换个思路&#xff1a;不修改BIOS?…

联想键盘sk8821的Fn功能键

1. 联想键盘sk8821的Fn功能键 1.1. 恢复 F1-F12实际功能 F1-F12系统下会默认为快捷键&#xff08;功能键&#xff09;&#xff0c;而非F1-F12实际功能。可能会导致您在使用习惯上的不适应。 键盘驱动安装目录&#xff1a;X:\LX_KEY\Yangtian\Low Profile Keyboard\setup.exe …

如何关闭联想台式机电脑USB键盘的FN功能

如何关闭联想台式机电脑USB键盘的FN功能 现在很多单位配备的联想台式机所配的USB键盘&#xff0c;F1-F12系统下会默认为快捷键&#xff08;功能键&#xff09;&#xff0c;而非F1-F12实际功能。可能会导致您在使用习惯上的不适应。 通过查询联想官网有如下解决方案&#xff0c;…

禁用联想笔记本电脑自带的键盘

最近电脑键盘出现故障&#xff0c;只要一开机&#xff0c;删除键就一直被按着&#xff0c;按其它键后&#xff0c;偶尔就恢复正常状态。被逼无奈&#xff0c;今天拿去电脑维修店&#xff0c;老板说是键盘的问题&#xff0c;需要换键盘。询问价格&#xff0c;说要&#xffe5;30…

杜蕾斯鞋套?又污又高级!

阳历四月雨纷纷&#xff0c;噼里啪啦湿鞋袜。 杜蕾斯专注“防水”九十多年。眼看大家进入了雨季&#xff0c;杜蕾斯上演一出《典中典》&#xff0c;上线经典鞋套。 我怀疑你在招风惹雨&#xff0c;只是我没证据。 穿这个鞋套出门会不会社死不知道&#xff0c;但谁用这玩意儿绝对…

压缩包.zip暴力破解方法

一: 前言 本方法基于虚拟机下的kali系统,软件为kali自带的fcrackzip,有兴趣的童鞋请自行研究下载. 二:方法说明 fcrackzip -help常用参数中文说明&#xff1a; -b 暴力破解模式 -D 使用字典破解模式 -v 就是可以看到更多的信息 -u 用zip去尝试 -l 密码长度 -c 指定掩码类型&…

python暴力破解zip加密文件

前言&#xff1a; 日常工作中&#xff0c;会遇到一些加密的zip文件&#xff0c;但是因为某些原因或者时间过长&#xff0c;密码不知道了。 但是zip文件中文件有很重要很必须。那么&#xff0c;我们试一试万能的Python&#xff0c;暴力破解密码。 一、破解zip加密文件的思路&a…