文件在网络上或不同设备之间是怎么传输的,在Java程序中又是怎么来实现文件的传输,带着这两个问题,来了解一下Java中的IO流相关类及操作。

一、什么是流及流的用途

  流是一组有顺序,有起点和终点的字节的集合,是对数据传输的总称和抽象。简单说流就是在不同设备之间进行数据传输。流的本质是数据传输,JDK为了方便开发者操作流,根据数据传输的各种特性,将流抽象为多种类,从而更加方便直观的操作。

二、流的分类

  根据处理的数据类型的不同,可将IO流分为字节流和字符流;根据IO流的流向又可将其分为输入流和输出流。一般来说,如果没有指出按什么分类,IO流的分类默认按处理数据的类型分为:字符输入流、字符输出流、字节输入流及字节输出流。

三、字符流和字节流的区别

  字符流的由来: 因为数据编码不同,而有了对字符进行高效操作的流对象。字符流本质是基于字节流读取,并查询指定的码表。

l  读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。

l  处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。

结论:只要是处理纯文本数据,优先考虑使用字符流。 除此之外都使用字节流。

四、 输入流和输出流

  输入和输出相对于内存而言,输入读入内存,输出从内存输出。对输入流只能进行读操作,对输出流只能进行写操作。

五、 流对象

 1) 字符输入流   Reader

  1. Reader 是所有的输入字符流的父类,它是一个抽象类;
  2. CharReader、StringReader 是两种基本的介质流,它们分别将Char 数组、String中读取数据。PipedReader 是从与其它线程共用的管道中读取数据;
  3. BufferedReader 很明显就是一个装饰器,它和其子类负责装饰其它Reader 对象;
  4. FilterReader 是所有自定义具体装饰流的父类,其子类PushbackReader 对Reader 对象进行装饰,会增加一个行号;
  5. InputStreamReader 是一个连接字节流和字符流的桥梁,它将字节流转变为字符流。FileReader 可以说是一个达到此功能、常用的工具类,在其源代码中明显使用了将FileInputStream 转变为Reader 的方法。我们可以从这个类中得到一定的技巧。Reader 中各个类的用途和使用方法基本和InputStream 中的类使用一致。后面会有Reader 与InputStream 的对应关系。

 2)字符输出流   Writer

  1. Writer 是所有的输出字符流的父类,它是一个抽象类;
  2. CharArrayWriter、StringWriter 是两种基本的介质流,它们分别向Char 数组、String 中写入数据。PipedWriter 是向与其它线程共用的管道中写入数据;
  3. BufferedWriter 是一个装饰器为Writer 提供缓冲功能;
  4. PrintWriter 和PrintStream 极其类似,功能和使用也非常相似;
  5. OutputStreamWriter 是OutputStream 到Writer 转换的桥梁,它的子类FileWriter 其实就是一个实现此功能的具体类(具体可以研究一SourceCode)。功能和使用和OutputStream 极其类似,后面会有它们的对应图。

 3)字节输入流   InputStream

  1. InputStream 是所有的输入字节流的父类,它是一个抽象类;
  2. ByteArrayInputStream、StringBufferInputStream、FileInputStream 是三种基本的介质流,它们分别从Byte 数组、StringBuffer、和本地文件中读取数据。PipedInputStream 是从与其它线程共用的管道中读取数据,与Piped 相关的知识后续单独介绍;
  3. ObjectInputStream 和所有FilterInputStream 的子类都是装饰流(装饰器模式的主角)。

 4)字节输出流   OutputStream

  1. OutputStream 是所有的输出字节流的父类,它是一个抽象类;
  2. ByteArrayOutputStream、FileOutputStream 是两种基本的介质流,它们分别向Byte 数组、和本地文件中写入数据。PipedOutputStream 是向与其它线程共用的管道中写入数据;
  3. ObjectOutputStream 和所有FilterOutputStream 的子类都是装饰流。

六、转换流

 

1)具体实现对象类

  1. InputStreamReader        字节到字符的桥梁
  2. OutputStreamWriter       字符到字节的桥梁

注意:这两个流对象是字符体系中的成员,本身是字符流,所以在构造的时候需要传入字节流对象。

 2)特点:

  1. 字符流和字节流之间的桥梁
  2. 可对读取到的字节数据经过指定编码转换成字符
  3. 可对读取到的字符数据经过指定编码转换成字节

 3)什么时候使用转换流

  1. 当字节和字符之间有转换动作时;
  2. 流操作的数据需要编码或解码时。

七、File

  File类是对文件系统中文件以及文件夹进行封装的对象,可以通过面向对象的思想来操作文件和文件夹。 File类保存文件或目录的各种元数据信息,包括文件名、文件长度、最后修改时间、是否可读、获取当前文件的路径名,判断指定文件是否存在、获得当前目录中的文件列表,创建、删除文件和目录等方法。

八、RandomAccessFile

  该对象并不是流体系中的一员,其封装了字节流,同时还封装了一个缓冲区(字符数组),通过内部的指针来操作字符数组中的数据。 该对象特点:
 1)该对象只能操作文件,所以构造函数接收两种类型的参数:a.字符串文件路径;b.File对象。
 2)该对象既可以对文件进行读操作,也能进行写操作,在进行对象实例化时可指定操作模式(r,rw)
  注意:该对象在实例化时,如果要操作的文件不存在,会自动创建;如果文件存在,写数据未指定位置,会从头开始写,即覆盖原有的内容。 可以用于多线程下载或多个线程同时写数据到文件。
  看完了上面的总结,不知道亲是否对IO流的操作有个整体的印象,接下来还是通过代码来体现一下面向对象的思想吧。

  1. package cn.dolphin.io;
  2.  
  3. import java.io.BufferedInputStream;
  4. import java.io.BufferedOutputStream;
  5. import java.io.BufferedReader;
  6. import java.io.BufferedWriter;
  7. import java.io.File;
  8. import java.io.FileInputStream;
  9. import java.io.FileOutputStream;
  10. import java.io.FileReader;
  11. import java.io.FileWriter;
  12. import java.io.IOException;
  13. import java.io.InputStreamReader;
  14. import java.io.OutputStreamWriter;
  15. import java.io.PrintStream;
  16. //import java.io.PrintWriter;
  17.  
  18. /**
  19. * Java中IO操作的演示
  20. *
  21. * @author Cyanide
  22. * @version v1.0.0
  23. * @since v1.0.0
  24. *
  25. */
  26. public class FileDemo {
  27. public static void main(String[] args) throws IOException {
  28. // createFile();
  29. // copyText1();
  30. // copyText2();
  31. // copyText3();
  32. // copyText4();
  33. // copyText5();
  34. // copyBinary1();
  35. // copyBinary2();
  36. // copyBinary3();
  37. //copyBinary4();
  38. //codec();
  39. printFlow();
  40. }
  41.  
  42. // -------------------------------------------------//
  43. // 基本类输入输出流对象及高效缓冲流对象 //
  44. // -------------------------------------------------//
  45. /**
  46. * File类的文件目录创建及删除操作演示
  47. *
  48. * @throws IOException
  49. */
  50. static void createFile() throws IOException {
  51. File f1 = new File("file.txt");
  52. File f2 = new File("directory");
  53. // 在当前项目目录中创建文件,需要处理异常。
  54. f1.createNewFile();
  55. // 在当前项目目录中创建目录
  56. f2.mkdir();
  57. // 删除创建的目录的文件
  58. f1.delete();
  59. f2.delete();
  60. }
  61.  
  62. /**
  63. * 文本文件的复制操作,基本实现,每读一个字符写一次。
  64. *
  65. * @throws IOException
  66. */
  67. static void copyText1() throws IOException {
  68. // 创建FileReader对象,抛出FileNotFoundException。
  69. FileReader fileReader = new FileReader("file.txt");
  70. // 创建FileWriter对象,抛出IOException。
  71. FileWriter fileWriter = new FileWriter("copies.txt");
  72. int num = 0;// fileReader.read()读到文件末尾返回-1。
  73. while ((num = fileReader.read()) != -1) {
  74. fileWriter.write(num);
  75. }
  76. fileWriter.close();
  77. fileReader.close();
  78. // 点评:效率低下,因此会采用第二种方式进行拷皮。
  79. }
  80.  
  81. /**
  82. * 文本文件的复制操作,每读1024个字符写一次。
  83. *
  84. * @throws IOException
  85. */
  86. static void copyText2() throws IOException {
  87. FileReader fileReader = new FileReader("file.txt");
  88. FileWriter fileWriter = new FileWriter("copies.txt");
  89. // length每次读出字符的实际长度
  90. int length = 0;
  91. char[] chs = new char[1024];
  92. while ((length = fileReader.read(chs)) != -1) {
  93. // 注意:fileReader.read()将读到的字符存入数组,如果最后
  94. // 一次读到字符长度不足字符数组长度时,未覆盖索引处字符也会
  95. // 读出,因此指定 length,读多少,写多少。
  96. fileWriter.write(chs, 0, length);
  97. }
  98. fileWriter.close();
  99. fileWriter.close();
  100. // 点评:效率比copyText1()高出很多,但还有更好的。
  101. }
  102.  
  103. /**
  104. * 文本文件的复制操作,高效缓存读写,每次一个字符。
  105. *
  106. * @throws IOException
  107. */
  108. static void copyText3() throws IOException {
  109. BufferedReader bufferedReader = new BufferedReader(new FileReader(
  110. "file.txt"));
  111. BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(
  112. "copies.txt"));
  113. int num = 0;
  114. while ((num = bufferedReader.read()) != -1) {
  115. bufferedWriter.write(num);
  116. }
  117. bufferedWriter.close();
  118. bufferedReader.close();
  119. }
  120.  
  121. /**
  122. * 文本文件的复制操作,高效缓存读写,每次读1024个字符。
  123. *
  124. * @throws IOException
  125. */
  126. static void copyText4() throws IOException {
  127. BufferedReader bufferedReader = new BufferedReader(new FileReader(
  128. "file.txt"));
  129. BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(
  130. "copies.txt"));
  131. int length = 0;
  132. char[] chs = new char[1024];
  133. while ((length = bufferedReader.read(chs)) != -1) {
  134. bufferedWriter.write(chs, 0, length);
  135. }
  136. bufferedWriter.close();
  137. bufferedReader.close();
  138. }
  139.  
  140. /**
  141. * 文本文件的复制操作,高效缓存读写,每次读一行,特有方法读写。
  142. *
  143. * @throws IOException
  144. */
  145. static void copyText5() throws IOException {
  146. BufferedReader bufferedReader = new BufferedReader(new FileReader(
  147. "file.txt"));
  148. BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(
  149. "copies.txt"));
  150. String str = null;
  151. while ((str = bufferedReader.readLine()) != null) {
  152. bufferedWriter.write(str);
  153. // readLine()方法读取不带换行,所以需要写入换行。
  154. bufferedWriter.newLine();
  155. bufferedWriter.flush();
  156. }
  157. bufferedWriter.close();
  158. bufferedReader.close();
  159. }
  160.  
  161. /**
  162. * 二进制文件的复制操作,基本实现,每读一个字节写一次。
  163. *
  164. * @throws IOException
  165. */
  166. static void copyBinary1() throws IOException {
  167. FileInputStream fileInputStream = new FileInputStream("file.bmp");
  168. FileOutputStream fileOutputStream = new FileOutputStream("copies.bmp");
  169. int num = 0;
  170. while ((num = fileInputStream.read()) != -1) {
  171. fileOutputStream.write(num);
  172. }
  173. fileInputStream.close();
  174. fileOutputStream.close();
  175. }
  176.  
  177. /**
  178. * 二进制文件的复制操作,每读1024个字节写一次。
  179. *
  180. * @throws IOException
  181. */
  182. static void copyBinary2() throws IOException {
  183. FileInputStream fileInputStream = new FileInputStream("file.bmp");
  184. FileOutputStream fileOutputStream = new FileOutputStream("copies.bmp");
  185. int length = 0;
  186. byte[] bytes = new byte[1024];
  187. while ((length = fileInputStream.read(bytes)) != -1) {
  188. fileOutputStream.write(bytes, 0, length);
  189. }
  190. fileInputStream.close();
  191. fileOutputStream.close();
  192. }
  193.  
  194. /**
  195. * 二进制文件的复制操作,高效缓存读写,每次一个字节。
  196. *
  197. * @throws IOException
  198. */
  199. static void copyBinary3() throws IOException {
  200. BufferedInputStream bufferedInputStream = new BufferedInputStream(
  201. new FileInputStream("file.bmp"));
  202. BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(
  203. new FileOutputStream("copies.bmp"));
  204. int num = 0;
  205. while ((num = bufferedInputStream.read()) != -1) {
  206. bufferedOutputStream.write(num);
  207. }
  208. bufferedOutputStream.close();
  209. bufferedInputStream.close();
  210. }
  211.  
  212. /**
  213. * 二进制文件的复制操作,高效缓存读写,每次读1024个字节。
  214. *
  215. * @throws IOException
  216. */
  217. static void copyBinary4() throws IOException {
  218. BufferedInputStream bufferedInputStream = new BufferedInputStream(
  219. new FileInputStream("file.bmp"));
  220. BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(
  221. new FileOutputStream("copies.bmp"));
  222. int length = 0;
  223. byte[] bytes = new byte[1024];
  224. while ((length = bufferedInputStream.read(bytes)) != -1) {
  225. bufferedOutputStream.write(bytes, 0, length);
  226. }
  227. bufferedInputStream.close();
  228. bufferedOutputStream.close();
  229. }
  230.  
  231. // -------------------------------------------------//
  232. // 缓冲高效转换流对象 //
  233. // -------------------------------------------------//
  234. /**
  235. * 高效缓冲流结合转换流对文本进行复制编码及解码过程。
  236. * @throws IOException
  237. */
  238. static void codec() throws IOException {
  239. //编码过程,将文本文件中编码。
  240. BufferedReader bufferedReader = new BufferedReader(
  241. new InputStreamReader(new FileInputStream("file.txt"), "gb2312"));
  242. //解码过程,将解码后的流写入文本文件。
  243. //BufferedWriter bufferedWriter = new BufferedWriter(
  244. //new OutputStreamWriter(new FileOutputStream("copies.txt"),"gb2312"));
  245. //将键盘录入内容编码
  246. //System.out.print("输入测试文本内容:");
  247. //BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in,"gb2312"));
  248. //将解码后的流直接输出到Console。
  249. BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(System.out,"utf-8"));
  250. int length = 0;
  251. char[] chs = new char[1024];
  252. while ((length = bufferedReader.read(chs))!=-1) {
  253. bufferedWriter.write(chs,0,length);
  254. }
  255. bufferedWriter.close();
  256. bufferedReader.close();
  257. //总结:用什么编码,就用什么解码。 如果编码和解码不一致,如果上例就会出现乱码显示。
  258. }
  259.  
  260. static void printFlow() throws IOException{
  261. BufferedReader bufferedReader = new BufferedReader(new FileReader("file.txt"));
  262. //将流写入文本。
  263. //PrintWriter printWriter = new PrintWriter(new FileWriter("copies.txt"),true);
  264. //将流输出到Console。
  265. PrintStream printStream = new PrintStream(System.out);
  266. char[] chs = new char[1024];
  267. while (bufferedReader.read(chs)!=-1) {
  268. printStream.println(chs);
  269. //printWriter.println(chs);
  270. bufferedReader.read(chs);
  271. }
  272. bufferedReader.close();
  273. printStream.close();
  274. }
  275. }

  最后PrintStream及PrintWriter只是输出,没有相应的输入。想想Java开始的第一天那个HelloWorld就用到了PrintStream只是刚开始不明白罢了。或许现在了还有不明白的地方,但随着知识的积累,相信学习Java会是件很快乐的事。

文件IO流总结的更多相关文章

  1. Java - 文件(IO流)

    Java - 文件 (IO)   流的分类:     > 文件流:FileInputStream | FileOutputStream | FileReader | FileWriter     ...

  2. Java File类与文件IO流总结

    1.File类 File类被定义为“文件和目录路径名的抽象表示形式”,这是因为File类既可以表示“文件”也可以表示“目录”,他们都通过对应的路径来描述.通过构造函数创建一个File类对象,则该对象就 ...

  3. Java文件IO流的操作总结

    Java中的IO操作涉及到的概念及相关类很多,很容易弄混,今天特来整理总结一下,并附上一份完整的文件操作的代码. 概念解析 读和写 流就是管道,向管道里面写数据用输出流:write 从管道里面读数据, ...

  4. 关于java读取文件IO流学习总结(一)

    IO流的分类: 1.根据流的数据对象来分: 高端流:所有的内存中的流都是高端流,比如:InputStreamReader 低端流:所有的外界设备中的流都是低端流,比如InputStream,Outpu ...

  5. 3,Java中的文件IO流

    1,File类 ··· 概念:File对象可以表示一个文件或目录.可以对其进行增删改查. ··· 常用方法:     File f = new File(".");     判断是 ...

  6. 第六章 文件&IO流

    6.1.File类 描述:该类是文件和目录路径名的抽象表示 构造方法: 方法 描述 public File(String pathname) 通过将给定的路径名字符串转换为抽象路径名来创建新的File ...

  7. 文件IO流完成文件的复制(复杂版本主要用来演示各种流的用途,不是最佳复制方案哦)

    package io; import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.File;import j ...

  8. 文件IO流

    //字节流读写含有中文的文本文件会出现问题,我在实践中居然没有检验出该问题,新人小菜,希望大家能指出: import java.io.FileInputStream; import java.io.F ...

  9. 关于java读取文件IO流学习总结(二)

    今天网上随意逛了逛,某处看到关于文件的操作,描述的不错,加深了对于文件操作的理解,在此分享给大家.希望能够有所收获. java读取txt文件内容: 可以作如下理解: 1. 首先获得一个文件句柄.Fil ...

随机推荐

  1. spring mvc 插入一条数据 返回该数据的主键编号

    import org.springframework.jdbc.core.PreparedStatementCreator; import org.springframework.jdbc.suppo ...

  2. 具体解释XML解析(一)—解析接口浅析

    在DRP项目中接触到了一个XML解析工具DOM4J,它作为解析工具的据说性能很优秀.可是刚刚接触解析工具不久,而且也没有使用过其它的解析工具.因此对于DOM4J的性能没有直接的感受(没有參照物).只是 ...

  3. hdu_2191多重背包

    用二维数组解的,因为忘了memset害我wa了好几发... #include<iostream> #include<cstdio> #include<cstring> ...

  4. 14.MongoDBUtils工具类

    1. public class DbUtils { public static MongoCollection<Document> getMongoCollection(String lo ...

  5. [雅礼NOIP2018集训 day3]

    考试的时候刚了T1两个小时线段树写了三个子任务结果发现看错了题目,于是接下来一个半小时我自闭了 result=历史新低 这告诉我们,打暴力要端正态度,尤其是在发现自己之前出锅的情况下要保持心态的平和, ...

  6. Linux系统安装Redis数据库

    Redis redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合).zset(sorte ...

  7. 指向类成员函数的函数指针及#define typedef 实现类成员函数的类型转换

    #include <iostream> using namespace std; class Test { public : void print() { cout << &q ...

  8. luogu 2308添加括号

    添加括号 传送门 题目大意 现在要添上n-1对括号,加法运算依括号顺序进行,得到n-1个中间和,求出使中间和之和最小的添括号方法. 这道题其实是一个很简单的区间dp,中间和的意思是括号里面的和,也就是 ...

  9. SparkSession - Spark SQL 的 入口

    SparkSession - Spark SQL 的 入口 翻译自:https://jaceklaskowski.gitbooks.io/mastering-apache-spark/content/ ...

  10. 固定执行计划-SQL PROFILE手工绑定

    固定(稳定)执行计划 你的应用的功能时快时慢,变化比较大,功能的性能能够保持一种稳定的状态,ORACLE 固定执行计划,采用以下这几种方式 oracle 9i使用 Outline oracle 10g ...