Java类库里有四个表示流的抽象父类:InputStream、OutputStream、Reader、Writer。

  其中 InputStream 和 OutputStream 是对字节进行操作的输入流和输出流;Reader 和 Writer 是对字符操作的输入输出流。

  它们是抽象类,在用它们的时候必须要对其进行实例化,因此类库也提供了具有不同功能的它们的子类,比如,以文件形式输入输出的 FileInputStream、FileOutputStream 和FileReader、FileWriter 等。

  以下列出了 Java IO 中一些比较常用的流类以及它们的方法使用,更多的流类请查阅API文档。

  --------------------------------------------------------------

  一、字节流

  1. InputStream、OutputStream 只能进行字节的传输数据

         InputStream抽象了应用程序读取数据的方式

       OutputStream抽象了应用程序写出数据的方式

  2. EOF = End,读到 -1 就读到结尾。

  3. 输入流的基本方法(以下的 in 代表输入流的对象)

      int b = in.read();

      从流读取一个字节无符号填充到int的低8位。(一个int变量是4个字节,1字节=8位,read()方法只能读取一个字节并返回int,所以该字节填充到int的低八位。)若读到结尾,返回 -1。用该方法读取大文件时,要使用while循环,这样效率较低,时间也较长,可以使用下面的批量读取方式。

      in.read(byte[] buf);

      从流读取数据直接填充到字节数组buf,读取字节的个数取决于数组的长度。返回的是读到的字节的个数。如果读到结尾返回-1。

      in.read(byte[] buf, int start, int size);

      从流读取数据到字节数组buf,从buf的start位置开始,存放最多size长度的数据。返回的是读到的字节的个数。如果读到结尾返回-1。

  4. 输出流的基本方法(以下的 out 代表输出流的对象)

      out.write(int b);

      写出一个byte到流,写出的是b的低8位。

      out.write(byte[] buf);

      将一个字节数组写出到流。

      out.write(byte[] buf, int start, int size);

      从buf的start位置开始,写size长度的数据到流。

  5. FileInputStream 是 InputStream 的子类,具体实现了在文件上读取字节数据:

  1. package test;
  2.  
  3. import java.io.File;
  4. import java.io.FileInputStream;
  5. import java.io.InputStream;
  6.  
  7. public class TestDemo {
  8.  
  9. public static void main(String[] args) throws Exception {
  10. //我们在D盘下创建了一个demo.txt,内容为“你好hello”。
  11. File file = new File("D:\\demo.txt");
  12. if(!file.exists()) file.createNewFile();
  13. InputStream in = new FileInputStream(file);
  14. int temp;
  15. while((temp = in.read()) != -1) {
  16. System.out.print(Integer.toHexString(temp & 0xff) + " ");
  17. }
  18. in.close();
  19. System.out.println();
  20.  
  21. InputStream in2 = new FileInputStream(file);
  22. byte[] buf = new byte[1024];
  23. int bytes = in2.read(buf);
  24. String s = new String(buf,0,bytes,"GBK");
  25. System.out.println(s);
  26. in2.close();
  27. }
  28.  
  29. }

  30. Output: c4 e3 ba c3 68 65 6c 6c 6f
  31.       你好hello

  6. FileOutputStream 是InputStream的子类,具体实现了在文件上读写出字节数据:

  1. //这是一个拷贝文件的例子
  2.  
  3. package test;
  4.  
  5. import java.io.File;
  6. import java.io.FileInputStream;
  7. import java.io.FileNotFoundException;
  8. import java.io.FileOutputStream;
  9. import java.io.IOException;
  10.  
  11. public class TestDemo {
  12.  
  13. public static void copyFile(File srcFile,File destFile) throws IOException{
  14. if(!srcFile.exists()) {
  15. throw new IllegalArgumentException("文件 " + srcFile + " 不存在!");
  16. }else if(!srcFile.isFile()) {
  17. throw new IllegalArgumentException(srcFile + " 不是文件!");
  18. }else {
  19. FileInputStream in = new FileInputStream(srcFile);
  20. FileOutputStream out = new FileOutputStream(destFile);
  21. byte[] bytes = new byte[8*1024];
  22. int b;
  23. while((b = in.read(bytes, 0, bytes.length)) != -1) {
  24. out.write(bytes, 0, b);
  25. out.flush(); //对于字节流而言,此句不加也没关系。
  26. }
  27. in.close();
  28. out.close();
  29. }
  30. }
  31.  
  32. public static void main(String[] args) {
  33. try {
  34. copyFile(new File("D:\\demo.txt"),new File("D:\\demo_copy.txt"));
  35. } catch (IOException e) {
  36. // TODO Auto-generated catch block
  37. e.printStackTrace();
  38. }
  39. }
  40.  
  41. }

  7. DataInputStream / DataOutputStream

      对“流”功能的扩展,可以更加方便的读写int,long,字符等基本数据类型

      如:DataOutputStream的方法有 writeInt() , writeDouble() , writeUTF() 等。

      在构造Data流时,要用到其他的流作为参数。如:DataOutputStream dos = new DataOutputStream(new FileOutputStream(file));

      这其实是一种“装饰器(过滤器)”设计模式:首先用“其他的流”来构造Data流,然后像 writeInt() 这些方法里面其实都是用“其他的流”的 write() 方法来实现的,如:一个Int有4个字节,用 write() 八位八位地写,做4次 write() ,然后再做移位操作。说白了就是用 writeInt() 将这些操作包装好,方便以后的直接使用。

     

writeInt()源码 

  1. package test;
  2.  
  3. import java.io.DataInputStream;
  4. import java.io.DataOutputStream;
  5. import java.io.FileInputStream;
  6. import java.io.FileOutputStream;
  7. import java.io.IOException;
  8.  
  9. public class TestDemo {
  10.  
  11. public static void main(String[] args) throws IOException{
  12.  
  13. DataOutputStream dos = new DataOutputStream(
  14. new FileOutputStream("D:\\demo.dat"));
  15. dos.writeInt(10);
  16. dos.writeInt(-10);
  17. dos.writeUTF("中国"); //采用utf-8编码写出
  18. dos.writeChars("中国"); //采用utf-16be编码写出
  19. PrintHex.printHex("D:\\demo.dat");
  20. dos.close();
  21.  
  22. DataInputStream dis = new DataInputStream(
  23. new FileInputStream("D:\\demo.dat"));
  24. System.out.println();
  25. int i = dis.readInt();
  26. System.out.println(i);
  27. i = dis.readInt();
  28. System.out.println(i);
  29. String s = dis.readUTF();
  30. System.out.println(s);
  31. dis.close();
  32. }
  33.  
  34. }
  35.   /*--------------------------------------------*/
  36. package test;
  37.  
  38. import java.io.FileInputStream;
  39. import java.io.IOException;
  40.  
  41. public class PrintHex {
  42.  
  43. public static void printHex(String fileName) throws IOException {
  44. FileInputStream in = new FileInputStream(fileName);
  45. int b;
  46. while((b = in.read()) != -1) {
  47. System.out.print(Integer.toHexString(b & 0xff) + " ");
  48. }
  49. in.close();
  50. }
  51.  
  52. }
  53.  
  54. /**
  55. * Output:
  56. * 0 0 0 a ff ff ff f6 0 6 e4 b8 ad e5 9b bd 4e 2d 56 fd
  57. * 10
  58. * -10
  59. * 中国
  60. */

  8. BufferedInputStream / BufferedOutputStream

      这两个流类为IO提供了带缓冲区的操作,一般打开文件进行读写操作时都会加上缓冲,这种流模式提高了IO的性能。

      从应用程序中把输入放入文件,相当于将一缸水倒入到另一个缸中:
      FileOutputStream  --->  write() 方法相当于一滴一滴地把水“转移”过去。
      DataOutputStream  --->  writeXxx() 方法会方便一些,相当于一瓢一瓢把水“转移”过去。
        BufferedOutputStream  --->  write 方法更方便,相当于一飘一瓢先放入桶中,再从桶中倒入到另一个缸中,性能提高了。

      这种字节缓冲流同样是采用装饰模式,要用其他的流来参与构造。

      以下是四种不同方式的文件拷贝,效率对比:

  1. package test;
  2.  
  3. import java.io.BufferedInputStream;
  4. import java.io.BufferedOutputStream;
  5. import java.io.FileInputStream;
  6. import java.io.FileOutputStream;
  7. import java.io.IOException;
  8.  
  9. public class CopyMethod {
  10. //以单字节传输
  11. public static void copyByByte(String srcFile,String destFile) throws IOException {
  12. FileInputStream fis = new FileInputStream(srcFile);
  13. FileOutputStream fos = new FileOutputStream(destFile);
  14. int i;
  15. while((i = fis.read()) != -1) {
  16. fos.write(i);
  17. }
  18. fis.close();
  19. fos.close();
  20. }
  21. //以字节数组传输
  22. public static void copyByBytes(String srcFile,String destFile) throws IOException {
  23. FileInputStream fis = new FileInputStream(srcFile);
  24. FileOutputStream fos = new FileOutputStream(destFile);
  25. byte[] bytes = new byte[8*1024];
  26. int i;
  27. while((i = fis.read(bytes, 0, bytes.length)) != -1) {
  28. fos.write(bytes, 0, i);
  29. }
  30. fis.close();
  31. fos.close();
  32. }
  33. //以单字节缓冲流传输
  34. public static void copyByByteBuffer(String srcFile,String destFile) throws IOException {
  35. BufferedInputStream bis = new BufferedInputStream(
  36. new FileInputStream(srcFile));
  37. BufferedOutputStream bos = new BufferedOutputStream(
  38. new FileOutputStream(destFile));
  39. int i;
  40. while((i = bis.read()) != -1) {
  41. bos.write(i);
  42. bos.flush(); //缓冲流要冲刷,否则写入不到文件
  43. }
  44. bis.close();
  45. bos.close();
  46. }
  47. //以字节数组缓冲流传输
  48. public static void copyByBytesBuffer(String srcFile,String destFile) throws IOException {
  49. BufferedInputStream bis = new BufferedInputStream(
  50. new FileInputStream(srcFile));
  51. BufferedOutputStream bos = new BufferedOutputStream(
  52. new FileOutputStream(destFile));
  53. byte[] bytes = new byte[8*1024];
  54. int i;
  55. while((i = bis.read(bytes, 0, bytes.length)) != -1) {
  56. bos.write(bytes, 0, i);
  57. bos.flush(); //缓冲流要冲刷,否则写入不到文件
  58. }
  59. bis.close();
  60. bos.close();
  61. }
  62.  
  63. }
  1. package test;
  2.  
  3. import java.io.IOException;
  4.  
  5. public class TestDemo {
  6.  
  7. public static void main(String[] args) {
  8. try {
           //比较这四种拷贝方式的效率。
  9. long start = System.currentTimeMillis();
  10. //Copy.copyByByte("D:\\1.mp3", "D:\\2.mp3"); //用时2908ms
  11. //Copy.copyByByteBuffer("D:\\1.mp3","D:\\2.mp3"); //用时1854ms
  12. //Copy.copyByBytes("D:\\1.mp3","D:\\2.mp3"); //用时7ms
  13. //Copy.copyByBytesBuffer("D:\\1.mp3","D:\\2.mp3"); //用时37ms,以字节数组缓冲流的方式反而比不带缓冲的字节数组传输得慢。
  14. long end = System.currentTimeMillis();
  15. System.out.println(end-start);
  16. } catch (IOException e) {
  17. // TODO Auto-generated catch block
  18. e.printStackTrace();
  19. }
  20. }
  21.  
  22. }

  ------------------------------------------------------------------

  二、字符流 

  1) 认识文本和文本文件:

    java的文本(char) 是16位无符号整数,是字符的unicode编码(双字节编码)。

    文件 是byte byte byte ... 的数据序列。

    文本文件 是文本(char)序列按照某种编码方案(utf-8,utf-16be,gbk)序列化为byte的存储结果。

  2) 字符流(Reader Writer为抽象类) ---> 一般操作的是文本文件

  1. InputStreamReader / OutputStreamWriter 

    字符的处理:一次处理一个字符。字符的底层依然是基本的字节序列,字符流的基本实现:

    InputStreamReader   完成byte流解析为char流,按照编码解析。

    OutputStreamWriter  提供char流到byte流,按照编码处理。

    字符流在构造时依然要用到字节流对象作为构造参数。

  1. //我们利用字符流同时做了文本文件的打印和拷贝。
  2. package test;
  3.  
  4. import java.io.FileInputStream;
  5. import java.io.FileOutputStream;
  6. import java.io.IOException;
  7. import java.io.InputStreamReader;
  8. import java.io.OutputStreamWriter;
  9.  
  10. public class IsrAndOswDemo {
  11. public static void main(String[] args)throws IOException {
  12. FileInputStream in = new FileInputStream("D:\\douban-utf-8.txt");
  13. InputStreamReader isr = new InputStreamReader(in,"utf-8"); //如不写编码方式就默认为项目的编码。操作的时候,要写文件本身的编码格式。
  14.  
  15. FileOutputStream out = new FileOutputStream("D:\\douban-utf-8-copy.txt");
  16. OutputStreamWriter osw = new OutputStreamWriter(out,"utf-8");
  17. /*int c ;
  18. while((c = isr.read())!=-1){
  19. System.out.print((char)c);
  20. }*/
  21. char[] buffer = new char[8*1024];
  22. int c;
  23. /*批量读取,放入buffer这个字符数组,从第0个位置开始放置,最多放buffer.length个
  24. 返回的是读到的字符的个数
  25. */
  26. while(( c = isr.read(buffer,0,buffer.length))!=-1){
  27. String s = new String(buffer,0,c);
  28. System.out.print(s);
  29. osw.write(buffer,0,c);
  30. osw.flush();
  31. }
  32. isr.close();
  33. osw.close();
  34. }
  35. }

  2. FileReader / FileWriter

    方便直接读写文本文件,不用像 InputStreamReader 和 OutputStreamWriter 一样需要嵌套一个File字节流。

    在构造文件字符流时,有两点需要注意:

     1) 不能使用编码方式的参数,也就是说只能读取编码方式和项目编码方式相同的文本文件,否则读取进来再做输出时会乱码。

     2) 构造FileWriter时,可以使用append参数,如果设置为true,会在输出的文本文件后面追加文本内容。

  1. //文本文件拷贝实例
  2.  
  3. package test;
  4.  
  5. import java.io.FileReader;
  6. import java.io.FileWriter;
  7. import java.io.IOException;
  8.  
  9. public class FrAndFwDemo {
  10. public static void main(String[] args) throws IOException{
  11. FileReader fr = new FileReader("D:\\douban-gbk.txt");
  12. FileWriter fw = new FileWriter("D:\\douban-gbk-copy.txt",true); //可以添加append参数,如果有,则在文件后面追加内容。
  13. char[] buffer = new char[2056];
  14. int c ;
  15. while((c = fr.read(buffer,0,buffer.length))!=-1){
  16. fw.write(buffer,0,c);
  17. fw.flush();
  18. }
  19. fr.close();
  20. fw.close();
  21. }
  22. }

  3. 字符流的过滤器 BufferedReader / BufferedWriter / PrintWriter

    这两个过滤器最强大的功能是具有读写一整行的方法:

    BufferedReader ---> readLine() 读一行,但是不能识别换行符

    BufferedWriter / PrintWriter ---> 写一行

  1. package test;
  2.  
  3. import java.io.BufferedReader;
  4. import java.io.BufferedWriter;
  5. import java.io.FileInputStream;
  6. import java.io.FileOutputStream;
  7. import java.io.IOException;
  8. import java.io.InputStreamReader;
  9. import java.io.OutputStreamWriter;
  10. import java.io.PrintWriter;
  11.  
  12. public class BrAndBwOrPwDemo {
  13. public static void main(String[] args) throws IOException{
  14. //对文件进行读写操作
  15. BufferedReader br = new BufferedReader(
  16. new InputStreamReader(
  17. new FileInputStream("D:\\douban-utf-8.txt"),"utf-8"));
  18. /*BufferedWriter bw = new BufferedWriter(
  19. new OutputStreamWriter(
  20. new FileOutputStream("D:\\douban-utf-8-copy.txt"),"utf-8")); //写出时如果不加编码方式,会按默认的编码方式写出,copy的文件不再是utf-8编码,而是gbk编码。*/
  21. PrintWriter pw = new PrintWriter("e:\\javaio\\imooc4.txt","utf-8");
  22. //PrintWriter pw1 = new PrintWriter(outputStream,boolean autoFlush);
  23. String line ;
  24. while((line = br.readLine())!=null) { //readLine方法一次读一行,但并不能识别换行
  25. System.out.println(line);
  26. /*bw.write(line);
  27. //单独写出换行操作
  28. bw.newLine();//换行操作
  29. bw.flush();*/
  30. pw.println(line); //写入到文件
  31. pw.flush();
  32. }
  33. br.close();
  34. //bw.close();
  35. pw.close();
  36. }
  37. }

  ------------------------------------------------------------------

  三、对象的序列化和反序列化

    对象序列化,就是将 Object 转换成 byte序列,反之叫对象的反序列化。对对象进行序列化和反序列化为的是 方便将来在 网络上 或者 本地 进行对象的传输。

  1. 序列化的基本操作 ObjectOutputStream / ObjectInputStream

    1) 序列化流(ObjectOutputStream) ---> 方法 writeObject(Object)

      反序列化流(ObjectInputStream) ---> 方法 readObject() ,返回的是Object类

    2) 序列化接口(Serializable)

      要对对象进行序列化,那么这个对象必须要实现序列化接口Serializable,否则将出现异常。这个接口,没有任何方法,只是一个标准。

  1. package test;
  2.  
  3. import java.io.FileInputStream;
  4. import java.io.FileOutputStream;
  5. import java.io.ObjectInputStream;
  6. import java.io.ObjectOutputStream;
  7.  
  8. public class ObjectSeriaDemo1 {
  9. public static void main(String[] args) throws Exception{
  10. String file = "demo/obj.dat";
  11. //对象的序列化,将stu对象转化为字节序列存入file。
  12. ObjectOutputStream oos = new ObjectOutputStream(
  13. new FileOutputStream(file));
  14. Student stu = new Student("10001", "张三", 20);
  15. oos.writeObject(stu);
  16. oos.flush();
  17. oos.close();
  18. //对象的反序列化,将file中的字节序列转化为对象。
  19. ObjectInputStream ois = new ObjectInputStream(
  20. new FileInputStream(file));
  21. Student stu2 = (Student)ois.readObject(); //需要进行强制类型转换,因为readObject方法返回的是Object类,而不是Student类。
  22. System.out.println(stu2);
  23. ois.close();
  24. }
  25. }

Java基础学习 -- I/O系统、流的更多相关文章

  1. 尚学堂JAVA基础学习笔记

    目录 尚学堂JAVA基础学习笔记 写在前面 第1章 JAVA入门 第2章 数据类型和运算符 第3章 控制语句 第4章 Java面向对象基础 1. 面向对象基础 2. 面向对象的内存分析 3. 构造方法 ...

  2. Java基础学习笔记总结

    Java基础学习笔记一 Java介绍 Java基础学习笔记二 Java基础语法之变量.数据类型 Java基础学习笔记三 Java基础语法之流程控制语句.循环 Java基础学习笔记四 Java基础语法之 ...

  3. 转载-java基础学习汇总

    共2页: 1 2 下一页  Java制作证书的工具keytool用法总结 孤傲苍狼 2014-06-24 11:03 阅读:25751 评论:3     Java基础学习总结——Java对象的序列化和 ...

  4. java基础学习总结——java环境变量配置(转)

    只为成功找方法,不为失败找借口! 永不放弃,一切皆有可能!!! java基础学习总结——java环境变量配置 前言 学习java的第一步就要搭建java的学习环境,首先是要安装 JDK,JDK安装好之 ...

  5. Java基础学习(2)

    Java基础学习(二) 面向对象 对象:客观存在的事物 面向对象:人具体关注的事物的某些信息 类:是模子,确定对象会拥有的特征(属性)和行为(方法) 对象的属性:对象具有的各种特征 对象的方法:对象能 ...

  6. Java基础学习-- 继承 的简单总结

    代码参考:Java基础学习小记--多态 为什么要引入继承? 还是做一个媒体库,里面可以放CD,可以放DVD.如果把CD和DVD做成两个没有联系的类的话,那么在管理这个媒体库的时候,要单独做一个添加CD ...

  7. 2015年12月28日 Java基础系列(六)流

    2015年12月28日 Java基础系列(六)流2015年12月28日 Java基础系列(六)流2015年12月28日 Java基础系列(六)流

  8. Java基础学习中一些词语和语句的使用

    在Java基础学习中,我们刚接触Java会遇到一些词和语句的使用不清的情况,不能很清楚的理解它的运行效果会是怎么样的,如:break,continue在程序中运行效果及跳转位置, 1.先来看看brea ...

  9. java基础学习总结——开篇

    java是我学习的第一门编程语言,当初学习java基础的时候下了不少功夫,趁着这段时间找工作之际,好好整理一下以前学习java基础时记录的笔记,当作是对java基础学习的一个总结吧,将每一个java的 ...

随机推荐

  1. 基于zipkin分布式链路追踪系统预研第一篇

    本文为博主原创文章,未经博主允许不得转载. 分布式服务追踪系统起源于Google的论文“Dapper, a Large-Scale Distributed Systems Tracing Infras ...

  2. fir.im Weekly - 如何进行 Android App 性能优化

    关于 Android App 的优化,@anly-jun 用 3 个月完成了这一系列文章,从 性能分析工具 到 ANR .Layout .消除卡顿 到 内存优化.内存分析工具大概十五六篇,并对此做一个 ...

  3. ES6新特性之 promise

    新的ES6中引入了promise的概念,目的是让回调更为优雅.层层嵌套的回调会让javascript失去美感和可读性,同时javascript也推荐采用链式的方式去书写函数调用.于是Promise就应 ...

  4. SSIS Design3:并发执行

    1,利用优先约束来并发处理数据,Data Flow Task 和 Data Flow Task 1 是并发执行的,而 Data Flow Task2 必须等到 Data Flow Task 和 Dat ...

  5. 数据结构与算法JavaScript (一) 栈

    序 数据结构与算法JavaScript这本书算是讲解得比较浅显的,优点就是用javascript语言把常用的数据结构给描述了下,书中很多例子来源于常见的一些面试题目,算是与时俱进,业余看了下就顺便记录 ...

  6. 【转】C#调用Windows图片和传真查看器打开图片

    //建立新的系统进程 System.Diagnostics.Process process = new System.Diagnostics.Process(); //设置文件名,此处为图片的真实路径 ...

  7. Python第一天 - 迭代

    (一)索引迭代 Python中,迭代永远是取出元素本身,而非元素的索引. 如果要取索引可以用enumerate()函数 例: L = ['Adam', 'Lisa', 'Bart', 'Paul'] ...

  8. DOM操作

    DOM操作,JS来操作页面 wiindows对象操作 document对象操作 点击事件:将DIV要执行的事件代码装封 onclick  鼠标单击       ondblelick  鼠标双击 onk ...

  9. T-SQL:毕业生出门需知系列(目录)

    一.前言: 作为一个应届毕业生又要准备面试 ASP.NET 攻城狮了,以前在图书馆觉得这本书讲得挺基础,这次回家就自己买了本用来复习,顺便做下读书笔记. 第4版 二.代码下载: 官方:http://f ...

  10. 【记录】VS2012新建MVC3/MVC4项目时,报:此模板尝试加载组件程序集“NuGet.VisualStudio.Interop...”

    最近电脑装了 VisualStudio "14" CTP,由于把其他版本的 VS 卸掉,由高到低版本安装,当时安装完 VisualStudio "14" CTP ...