Java--IO流(InputStream,OutputStream,拷贝)

迈不过友情╰ 2023-10-17 11:27 95阅读 0赞

一、IO流概述及其分类

1、概念

IO流用来处理设备之间的数据传输

Java对数据的操作是通过流的方式

Java用于操作流的类都在IO包中

流按流向分为两种:输入流,输出流。

流按操作类型分为两种:

字节流 : 字节流可以操作任何数据,因为在计算机中任何数据都是以字节的形式存储的

字符流 : 字符流只能操作纯字符数据,比较方便。

2、IO流常用父类

字节流的抽象父类:

InputStream

OutputStream

字符流的抽象父类:

Reader

Writer

3、IO程序书写

使用前,导入IO包中的类

使用时,进行IO异常处理

使用后,释放资源

4、read()方法读取的是一个字节,为什么返回是int,而不是byte

因为字节输入流可以操作任意类型的文件,比如图片音频等,这些文件底层都是以二进制形式的存储的,

如果每次读取都返回byte,有可能在读到中间的时候遇到111111111

那么这11111111是byte类型的-1,我们的程序是遇到-1就会停止不读了,后面的数据就读不到了,

所以在读取的时候用int类型接收,如果11111111会在其前面补上

24个0凑足4个字节,那么byte类型的-1就变成int类型的255了这样可以保证整个数据读完,而结束标记的-1就是int类型

二、字节数组拷贝

1、int read(byte[] b):一次读取一个字节数组

2、write(byte[] b):一次写出一个字节数组

3、available()获取读的文件所有的字节个数

4、小数组

write(byte[] b)

write(byte[] b, int off, int len)写出有效的字节个数

三、BufferedInputStream和BufferOutputStream拷贝

1、缓冲思想

字节流一次读写一个数组的速度明显比一次读写一个字节的速度快很多,

这是加入了数组这样的缓冲区效果,java本身在设计的时候,

也考虑到了这样的设计思想(装饰设计模式后面讲解),所以提供了字节缓冲区流

2、BufferedInputStream

BufferedInputStream内置了一个缓冲区(数组)

从BufferedInputStream中读取一个字节时

BufferedInputStream会一次性从文件中读取8192个, 存在缓冲区中, 返回给程序一个

程序再次读取时, 就不用找文件了, 直接从缓冲区中获取

直到缓冲区中所有的都被使用过, 才重新从文件中读取8192个

3、BufferedOutputStream

BufferedOutputStream也内置了一个缓冲区(数组)

程序向流中写出字节时, 不会直接写到文件, 先写到缓冲区中

直到缓冲区写满, BufferedOutputStream才会把缓冲区中的数据一次性写到文件里4、小数组的读写和带Buffered的读取哪个更快?

定义小数组如果是8192个字节大小和Buffered比较的话

定义小数组会略胜一筹,因为读和写操作的是同一个数组

而Buffered操作的是两个数组

四、flush和close方法区别

1、close具备刷新功能,在关闭流之前,就会先刷新一次缓冲区,将缓冲区的字节全部刷新到文件上,再关闭,且刷新完之后不能再写了

2、flush具备刷新功能,刷新完之后可以继续写

五、字节流读写中文

字节流读取中文的问题

字节流在读中文的时候有可能会读到半个中文,造成乱码

字节流写出中文的问题

字节流直接操作的字节,所以写出中文必须将字符串转换成字节数组

写出回车换行 write(“\r\n”.getBytes());

  1. import java.io.BufferedInputStream;
  2. import java.io.BufferedOutputStream;
  3. import java.io.FileInputStream;
  4. import java.io.FileNotFoundException;
  5. import java.io.FileOutputStream;
  6. import java.io.IOException;
  7. public class FileInputStreamClass {
  8. public static void main(String[] args) throws IOException {
  9. /*
  10. 一、IO流概述及其分类
  11. 1、概念
  12. IO流用来处理设备之间的数据传输
  13. Java对数据的操作是通过流的方式
  14. Java用于操作流的类都在IO包中
  15. 流按流向分为两种:输入流,输出流。
  16. 流按操作类型分为两种:
  17. 字节流 : 字节流可以操作任何数据,因为在计算机中任何数据都是以字节的形式存储的
  18. 字符流 : 字符流只能操作纯字符数据,比较方便。
  19. 2、IO流常用父类
  20. 字节流的抽象父类:
  21. InputStream
  22. OutputStream
  23. 字符流的抽象父类:
  24. Reader
  25. Writer
  26. 3、IO程序书写
  27. 使用前,导入IO包中的类
  28. 使用时,进行IO异常处理
  29. 使用后,释放资源
  30. 4、read()方法读取的是一个字节,为什么返回是int,而不是byte
  31. 因为字节输入流可以操作任意类型的文件,比如图片音频等,这些文件底层都是以二进制形式的存储的,
  32. 如果每次读取都返回byte,有可能在读到中间的时候遇到111111111
  33. 那么这11111111是byte类型的-1,我们的程序是遇到-1就会停止不读了,后面的数据就读不到了,
  34. 所以在读取的时候用int类型接收,如果11111111会在其前面补上
  35. 24个0凑足4个字节,那么byte类型的-1就变成int类型的255了这样可以保证整个数据读完,而结束标记的-1就是int类型
  36. 二、字节数组拷贝
  37. 1、int read(byte[] b):一次读取一个字节数组
  38. 2、write(byte[] b):一次写出一个字节数组
  39. 3、available()获取读的文件所有的字节个数
  40. 4、小数组
  41. write(byte[] b)
  42. write(byte[] b, int off, int len)写出有效的字节个数
  43. 三、BufferedInputStream和BufferOutputStream拷贝
  44. 1、缓冲思想
  45. 字节流一次读写一个数组的速度明显比一次读写一个字节的速度快很多,
  46. 这是加入了数组这样的缓冲区效果,java本身在设计的时候,
  47. 也考虑到了这样的设计思想(装饰设计模式后面讲解),所以提供了字节缓冲区流
  48. 2、BufferedInputStream
  49. BufferedInputStream内置了一个缓冲区(数组)
  50. 从BufferedInputStream中读取一个字节时
  51. BufferedInputStream会一次性从文件中读取8192个, 存在缓冲区中, 返回给程序一个
  52. 程序再次读取时, 就不用找文件了, 直接从缓冲区中获取
  53. 直到缓冲区中所有的都被使用过, 才重新从文件中读取8192个
  54. 3、BufferedOutputStream
  55. BufferedOutputStream也内置了一个缓冲区(数组)
  56. 程序向流中写出字节时, 不会直接写到文件, 先写到缓冲区中
  57. 直到缓冲区写满, BufferedOutputStream才会把缓冲区中的数据一次性写到文件里
  58. 4、小数组的读写和带Buffered的读取哪个更快?
  59. 定义小数组如果是8192个字节大小和Buffered比较的话
  60. 定义小数组会略胜一筹,因为读和写操作的是同一个数组
  61. 而Buffered操作的是两个数组
  62. 四、flush和close方法区别
  63. 1、close具备刷新功能,在关闭流之前,就会先刷新一次缓冲区,将缓冲区的字节全部刷新到文件上,再关闭,且刷新完之后不能再写了
  64. 2、flush具备刷新功能,刷新完之后可以继续写
  65. 五、字节流读写中文
  66. 字节流读取中文的问题
  67. 字节流在读中文的时候有可能会读到半个中文,造成乱码
  68. 字节流写出中文的问题
  69. 字节流直接操作的字节,所以写出中文必须将字符串转换成字节数组
  70. 写出回车换行 write("\r\n".getBytes());
  71. * */
  72. fileInputStream();//字节输入流
  73. fileOutputStream();//字节输出流
  74. copyImages();//复制图片
  75. littleArray();
  76. buffer();
  77. writeChinese();
  78. exceptionForjdk16();//jdk1.6以及以前版本处理异常
  79. exceptionForjdk17();//jdk1.7版本处理异常
  80. }
  81. public static void exceptionForjdk17() {
  82. try(FileInputStream fis = new FileInputStream("ccc.txt");
  83. FileOutputStream fos = new FileOutputStream("ddd.txt");
  84. //具备自动关闭流的功能
  85. MyClose myClose = new MyClose();
  86. /*原理
  87. 在try()中创建的流对象必须实现了AutoCloseable这个接口,如果实现了,在try后面的{}
  88. (读写代码)执行后就会自动调用,流对象的close方法将流关掉*/
  89. ){
  90. int b;
  91. while((b = fis.read()) != -1){
  92. fos.write(b);
  93. }
  94. } catch (FileNotFoundException e) {
  95. e.printStackTrace();
  96. } catch (IOException e) {
  97. e.printStackTrace();
  98. }
  99. }
  100. public static void exceptionForjdk16() {
  101. FileInputStream fis = null;
  102. FileOutputStream fos = null;
  103. try{
  104. fis = new FileInputStream("aaa.txt");
  105. fos = new FileOutputStream("bbb.txt");
  106. int b;
  107. while((b = fis.read()) != -1){
  108. fos.write(b);
  109. }
  110. } catch (IOException e) {
  111. e.printStackTrace();
  112. }finally {
  113. try{
  114. if (fis != null)
  115. fis.close();
  116. } catch (IOException e) {
  117. e.printStackTrace();
  118. } finally {
  119. if (fos != null)
  120. try {
  121. fos.close();
  122. } catch (IOException e) {
  123. e.printStackTrace();
  124. }
  125. }
  126. }
  127. }
  128. private static void writeChinese() throws IOException {
  129. FileOutputStream fos = new FileOutputStream("aa.txt");
  130. fos.write("我读书少".getBytes());
  131. fos.close();
  132. }
  133. private static void buffer() throws IOException {
  134. FileInputStream fis = new FileInputStream("a.txt");
  135. FileOutputStream fos = new FileOutputStream("e.txt");
  136. BufferedInputStream bis = new BufferedInputStream(fis);
  137. BufferedOutputStream bos = new BufferedOutputStream(fos);
  138. int b;
  139. while((b=bis.read()) != -1){
  140. bos.write(b);
  141. }
  142. bis.close();
  143. bos.close();
  144. }
  145. private static void littleArray() throws IOException {
  146. System.out.println("==============小数组=============");
  147. FileInputStream fis = new FileInputStream("c.txt");
  148. FileOutputStream fos = new FileOutputStream("d.txt");
  149. // byte[] arr = new byte[2];
  150. byte[] arr = new byte[1024 * 8];//标准写法
  151. int len;
  152. while((len = fis.read(arr)) != -1){ //如果此处忘记加arr,返回的就不是读取的字节个数,而是字节的码表值
  153. fos.write(arr, 0, len);//写入有效文件
  154. }
  155. fis.close();
  156. fos.close();
  157. }
  158. private static void copyImages() throws IOException {
  159. System.out.println("==============拷贝图片=============");
  160. FileInputStream fis = new FileInputStream("11.jpg");
  161. FileOutputStream fos = new FileOutputStream("copy.jpg");
  162. //第一种方法:读一点写一点,效率低下
  163. // int b;
  164. // while((b = fis.read()) != -1){ //不断的读取每一个字节
  165. // fos.write(b); //将字节不断地写出
  166. // }
  167. // fis.close();
  168. // fos.close();
  169. //第二种方法:一次性读出写入,如果内存过大导致内存溢出
  170. FileOutputStream fos1 = new FileOutputStream("copy1.jpg");
  171. byte[] arr = new byte[fis.available()]; //创建与文件一样大小的字节数组
  172. fis.read(arr); //将文件上的字节数据一次性读取到内存中
  173. fos1.write(arr); //将字节数组中的字节数据一次性写到文件上
  174. fis.close();
  175. fos1.close();
  176. }
  177. private static void fileOutputStream() throws IOException {
  178. System.out.println("==============字节输出流=============");
  179. FileOutputStream fis = new FileOutputStream("b.txt",true);
  180. //如果想续写在第二个参数传true
  181. //创建字节流输出对象文件,如果没有自动创建一个;如果有此文件则先将文件清空
  182. fis.write(97); //虽然写出的是一个int数,但是到文件上的是一个字节,会自动去掉前三个8位
  183. // fis.write(98);
  184. // fis.write(99);
  185. fis.write(100);
  186. fis.close();
  187. }
  188. public static void fileInputStream() throws FileNotFoundException, IOException {
  189. System.out.println("==============字节输入流=============");
  190. FileInputStream fis = new FileInputStream("a.txt");
  191. int b;
  192. while((b = fis.read()) != -1){ //文件结束标记为-1
  193. System.out.print(b +" ");
  194. }
  195. fis.close();// 关流释放资源
  196. System.out.println();
  197. }
  198. }
  199. class MyClose implements AutoCloseable{
  200. public void close(){
  201. System.out.println("我调用了close方法");
  202. }
  203. }

Center

发表评论

表情:
评论列表 (有 0 条评论,95人围观)

还没有评论,来说两句吧...

相关阅读

    相关 JavaIO:概述

    > 在接触 IO 流前,无论是 变量的声明、数组的创建,又或者是复杂的并发设计还是 Jvm 的性能调优,我们更多的还是和内存打交道。但我们知道计算机组成包括运算器,控制器,存储

    相关 javaIO

    IO流 文件--基本概念 文件是数据源(保存数据的地方)的一种,比如大word文档、jpg文件、MP4文件...都是文件。文件最主要的作用就是保存数据,它既可以保存一张

    相关 JavaIO

    一、流的概念 >        流(stream)的概念源于UNIX中管道(pipe)的概念。在UNIX中,管道是一条不间断的字节流,用来实现程序或进程间的通信,或读写外围设

    相关 JavaIO

    IO流 IO流的分类: 1)按方向划分: a.输入流:读取数据 b.输出流:写输出数 2)按数据类型分: a.字节流(图片文件,音频,视频等等....使用

    相关 javaIO——打印

    本节目标:     1.掌握打印流的操作     2.掌握格式化输出 打印流 在整个IO包中,打印流是输出信息最方便的类,主要包含字节打印流(Print

    相关 javaIO——管道

    本节目标: 了解管道流的操作 管道流 管道流的主要作用是可以进行两个线程间的通讯,分为管道输出流(PipedOutputStream)和管道输入流(PipedInpu

    相关 javaIO(一)

    ![这里写图片描述][70] 按照数据流的方向不同可以分为:输入流和输出流。 按照处理数据单位不同可以分为:字节流和字符流。 按照功能不同可以分为:节点流和处理流。

    相关 JavaIO

    > IO流分为六种概念:输入流、输出流、字节流、字符流、节点流和处理流。 > 可以方便地实现数据的输入/输出操作。 > 不同的输入/输出源(键盘、文件、网络连接等)抽象