目录

  • 一、背景
  • 二、IO流的分类
  • 三、字符流操作相关代码示例
    • 1、FileReader读取文件内容
    • 2、FileWriter向文件写数据
    • 3、实现文件内容复制
    • 4、注意事项
    • 5、利用try-catch-finally处理异常
  • 四、字节流操作相关代码示例
    • 1、用字节流读取文本文件操作(不建议)
    • 2、读图片文件
    • 3、非文本文件内容的复制
  • 五、缓冲字节流(-->处理流)
  • 六、缓冲字符流(-->处理流)
  • 七、转换流(-->处理流)
  • 八、System类
    • 1、System.in
    • 2、System.out
  • 九、数据流(-->处理流)
  • 十、对象流
    • 1、序列化
    • 2、反序列化
    • 3、代码示例
    • 4、序列化版本标识符(serialVersionUID)
    • 5、序列化的细节

一、背景

  Java中有File类,用于封装文件/目录的各种信息,对目录/文件进行操作,但是我们不能获取到文件/目录中的内容。因此引入IO流,用于处理设备之间的数据的传输。


二、IO流的分类

按照方向:输入流、输出流
按照处理数据的单位:字节流(小)、字符流(大)

组合形成四种:输入字节流(InputStream)、输出字节流(OutputStream)
       输入字符流(Reader)、输出字符流(Writer)
这四个就是抽象基类

按照功能:节点流、处理流

节点流:单独一个“流”处理数据
处理流:“流”套着“流”,组合使用(构造器嵌套)


三、字符流操作相关代码示例

1、FileReader读取文件内容

将桌面的test.txt文件的内容读取到程序里。
(1)一次读一个字符----->效率低下

public class FileTest {public static void main(String[] args) throws IOException {//创建一个File类对象File f = new File("/Users/minh/Desktop/test.txt");//创建一个FileReader的流的对象FileReader fr = new FileReader(f);//读取文件内容//遍历方式1:
//        int read = fr.read();
//        while(read != -1){//            System.out.println((char)read);
//            read = fr.read();
//        }//遍历方式2:int read;while ((read = fr.read()) != -1)System.out.println((char)read);//主动关闭流fr.close();}
}

(2)一次读多个字符----->提高效率

public class FileTest {public static void main(String[] args) throws IOException {//创建一个File类对象File f = new File("/Users/minh/Desktop/test.txt");//创建一个FileReader的流的对象FileReader fr = new FileReader(f);char[] ch = new char[5];//缓冲数组int len = fr.read(ch);while(len != -1){//方式1:
//            for(int i = 0; i < len; i++)
//                System.out.print(ch[i]);//方式2:String str = new String(ch, 0, len);System.out.print(str);len = fr.read(ch);}//关闭流fr.close();}
}

2、FileWriter向文件写数据

将程序中的内容输出到文件中。
(1)一个字符一个字符输出

public class FileTest {public static void main(String[] args) throws IOException {//创建一个File类对象File f = new File("/Users/minh/Desktop/output.txt");//创建一个FileWriter的流的对象FileWriter fw = new FileWriter(f);//new FileWriter(f, false);//new FileWriter(f, true);String str = "hello牛奶hello麦片";for(int i = 0; i < str.length(); i++){fw.write(str.charAt(i));}//关闭流fw.close();}
}

如果目标文件不存在,那么会自动创建次文件
如果目标文件存在,new FileWriter(f)和new FileWriter(f, false)都相当于对源文件进行覆盖操作;new FileWriter(f, true)相当于对源文件进行追加操作。

(2)一次输出多个字符

        File f = new File("/Users/minh/Desktop/output.txt");FileWriter fw = new FileWriter(f,true);String str = "hello牛奶hello麦片";char[] chs = str.toCharArray();fw.write(chs);fw.close();

3、实现文件内容复制

public class FileTest {public static void main(String[] args) throws IOException {//源文件File f1 = new File("/Users/minh/Desktop/test.txt");//目标文件File f2 = new File("/Users/minh/Desktop/output.txt");//创建FileReader和FileWriter流对象FileReader fr = new FileReader(f1);FileWriter fw = new FileWriter(f2);//数据传送
//        //方式1:一个字符一个字符传送
//        int read = fr.read();
//        while(read != -1){//            fw.write(read);
//            read = fr.read();
//        }
//        //方式2:利用缓冲数组-->一次读多个字符
//        char[] chs = new char[5];
//        int len = fr.read(chs);
//        while(len != -1){//            fw.write(chs, 0, len);
//            len = fr.read(chs);
//        }//方式3:char[] chs = new char[5];int len = fr.read(chs);while(len != -1){String str = new String(chs, 0, len);fw.write(str);len = fr.read(chs);}//关闭流,后用的流先关闭fw.close();fr.close();}
}

4、注意事项

字符流操作不能用于操作非文本文件!
文本文件:(.txt、.c、.java、.cpp等)—>建议使用字符流操作
非文本文件:图片、视频、音频(.jpg、.avi、.mp3、.doc、.ppt、.xlsx等)—>建议使用字节点操作


5、利用try-catch-finally处理异常

public class FileTest {public static void main(String[] args){//源文件File f1 = new File("/Users/minh/Desktop/test.txt");//目标文件File f2 = new File("/Users/minh/Desktop/output.txt");//创建FileReader和FileWriter流对象FileReader fr = null;FileWriter fw = null;try {fr = new FileReader(f1);fw = new FileWriter(f2);char[] chs = new char[5];int len = fr.read(chs);while(len != -1){String str = new String(chs, 0, len);fw.write(str);len = fr.read(chs);}} catch (IOException e) {e.printStackTrace();}finally {try {if(fw != null)fw.close();} catch (IOException e) {e.printStackTrace();}try {if(fr != null)fr.close();} catch (IOException e) {e.printStackTrace();}}}
}

四、字节流操作相关代码示例

1、用字节流读取文本文件操作(不建议)

细节1:文件是utf-8进行存储的,英文字符底层占1个字节,但中文字符占3个字节;
细节2:read()读取一个字节,返回值是int类型,而不是byte类型,是为了避免-1时,无法确定是读入的字节还是文件结尾的情况


2、读图片文件

public class IOTest{public static void main(String[]args) throws IOException {File f = new File("/Users/minh/Desktop/pho.jpeg");FileInputStream fis = new FileInputStream(f);byte[] b = new byte[1024*5];int len = fis.read(b);while(len != -1){len = fis.read(b);}fis.close();}
}

3、非文本文件内容的复制

以图片文件为例:

public class IOTest{public static void main(String[]args) throws IOException {File f1 = new File("/Users/minh/Desktop/pho.jpeg");File f2 = new File("/Users/minh/Desktop/out.jpeg");FileInputStream fis = new FileInputStream(f1);FileOutputStream fos = new FileOutputStream(f2);byte[] b = new byte[1024*5];int len = fis.read(b);while(len != -1){fos.write(b, 0, len);len = fis.read(b);}fos.close();fis.close();}
}

五、缓冲字节流(–>处理流)

缓冲字节流的引入是为了减少访存的次数,提高效率。在程序中分别开辟一个输入缓冲区和一个输出缓冲区,用于暂存数据。源码默认大小为8192字节。处理非文本文件—>BufferedInputStream、BufferedOutputStream
代码示例(图片文件.jpeg):

public class IOBufferTest {public static void main(String[] args) throws IOException {File f1 = new File("/Users/minh/Desktop/pho.jpeg");File f2 = new File("/Users/minh/Desktop/output.jpeg");FileInputStream fis = new FileInputStream(f1);FileOutputStream fos = new FileOutputStream(f2);BufferedInputStream bis = new BufferedInputStream(fis);BufferedOutputStream bos = new BufferedOutputStream(fos);byte[] b = new byte[1024*8];int len = bis.read(b);while(len != -1){bos.write(b, 0, len);len = bis.read(b);}bos.close();bis.close();//如果处理流包裹着节点流,那么只要关闭处理流,里面的字节流也会随之被关闭。
//        fos.close();
//        fis.close();}
}

六、缓冲字符流(–>处理流)

处理文本文件—>BufferedReader、BufferedWriter
代码示例(文本文件.txt):

public class IOBufferTest {public static void main(String[] args) throws IOException {File f1 = new File("/Users/minh/Desktop/test.txt");File f2 = new File("/Users/minh/Desktop/output.txt");FileReader fr = new FileReader(f1);FileWriter fw = new FileWriter(f2);BufferedReader br = new BufferedReader(fr);BufferedWriter bw = new BufferedWriter(fw);//方式1:char[] chs = new char[30];int len = br.read(chs);while(len != -1){bw.write(chs, 0, len);len = br.read(chs);}//        //方式2:读取String
//        //每次读取文本文件中一行,返回字符串
//        String str = br.readLine();
//        while(str != null){//            bw.write(str);
//            bw.newLine();  //在文本文件中每次写完一行需要换行
//            str = br.readLine();
//        }bw.close();br.close();}
}

七、转换流(–>处理流)

转换流的作用是将字节流和字符流进行转换。
属于字符流。

InputStreamReader:字节输入流—>字符输入流
OutputStreamWriter:字符输出流—>字节输出流

代码示例:

public class IOChangeTest {public static void main(String[] args) throws IOException {File f1 = new File("/Users/minh/Desktop/test.txt");File f2 = new File("/Users/minh/Desktop/output.txt");FileInputStream fis = new FileInputStream(f1);FileOutputStream fos = new FileOutputStream(f2);//加入一个转换流,将字节流转换为字符流。//此时需要指定一个编码,这个编码与文件本身编码格式一致。//若不指定编码格式,则默认与程序的格式一致InputStreamReader isr = new InputStreamReader(fis);//InputStreamReader isr = new InputStreamReader(fis, "utf-8");OutputStreamWriter osw = new OutputStreamWriter(fos, "gbk");char[] chs = new char[30];int len = isr.read(chs);while(len != -1){osw.write(chs, 0, len);len = isr.read(chs);}osw.close();isr.close();}
}

注:在使用InputStreamReader和OutputStreamWriter时,需指定编码格式(即文件的编码格式),若不指定则默认与程序的编码格式一致。


八、System类

System的属性:
System.in:“标准”输入流—>默认情况下,从键盘输入(字节流)
System.out:“标准”输出流—>默认情况下,输出到控制台

1、System.in

public class SystemTest {public static void main(String[] args) throws IOException {//        //标准输入流--->从键盘输入
//        InputStream in = System.in;
//        int n = in.read();
//        System.out.println(n);//        //由上述代码可知,键盘输入实际上是System.in
//        //而Scanner的作用相当于一个扫描器,扫描从System.in出来的数据
//        Scanner sc = new Scanner(System.in);
//        int i = sc.nextInt();
//        System.out.println(i);//引申--->Scanner也可以扫描其他的内容Scanner sc = new Scanner(new FileInputStream(new File("/Users/minh/Desktop/test.txt")));while(sc.hasNext()){System.out.println(sc.next());}}
}

注:之前学的从键盘输入语句:Scanner sc = new Scanner(System.in);
  其中真正起输入作用的是System.in,而Scanner仅是一个“扫描器”的作用,扫描从System.in读取的数据,因此其也可以用于扫描其他的内容。


2、System.out

输出流、打印流。

     PrintStream out = System.out;out.println("minh");

代码示例(将键盘输入内容输出到文件中):

public class SystemTest {public static void main(String[] args) throws IOException {//输入准备InputStream in = System.in;InputStreamReader isr = new InputStreamReader(in);BufferedReader br = new BufferedReader(isr);//输出准备File f = new File("/Users/minh/Desktop/output.txt");FileWriter fw = new FileWriter(f);BufferedWriter bw = new BufferedWriter(fw);//写入操作String str = br.readLine();while (!str.equals("exit")){bw.write(str);bw.newLine();//换行str = br.readLine();}bw.close();br.close();}
}

九、数据流(–>处理流)

用来操作基本数据类型和字符串。
分为DataInputStream和DataOutputStream两类。
代码示例(利用DataOutputStream从程序向文件写数据):

public class DataTest {public static void main(String[] args) throws IOException {//向文件中写数据DataOutputStream dos = new DataOutputStream(new FileOutputStream("\"/Users/minh/Desktop/output.txt\""));dos.writeBoolean(true);dos.writeDouble(9.8);dos.writeUTF("minh");dos.close();}
}

代码示例(利用DataInputStream从文件读数据到程序中):

//从文件中读数据DataInputStream dis = new DataInputStream(new FileInputStream(new File("/Users/minh/Desktop/output.txt")));System.out.println(dis.readBoolean());System.out.println(dis.readDouble());System.out.println(dis.readUTF());dis.close();

运行结果:

注:读的顺序需与写的顺序一致,否则就会报错!


十、对象流

用来存储和读取基本数据类型数据或对象的处理流。
它可以把Java中的对象写入到数据源中,也能把对象从数据源中还原。

1、序列化

代码示例(将一个对象(String类)写入文件):

public class ObjectTest {public static void main(String[] args) throws IOException {//将一个对象写入文件ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("/Users/minh/Desktop/output.txt")));oos.writeObject("minh");oos.close();}
}

ObjectOutputStream类:把Java对象转换成与平台无关的二进制数据,从而可以在磁盘上永久保存该数据或者通过网络将这种二进制数据传输到另一个网络节点上。称为序列化


2、反序列化

代码示例(将上述文件保存的数据读入程序):

     //将文件保存的数据读入程序ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("/Users/minh/Desktop/output.txt")));System.out.println((String)ois.readObject());ois.close();

ObjectInputStreame类:将上述二进制数据恢复成原来的Java对象。
称为反序列化


3、代码示例

代码示例:操作一个自定义类对象
一个自定义对象Person:

public class Person implements Serializable{private String name;private int age;private String sex;public Person() {}public Person(String name, int age, String sex) {this.name = name;this.age = age;this.sex = sex;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public String getSex() {return sex;}public void setSex(String sex) {this.sex = sex;}
}

向文件中写入一个对象:

public class SerializableTest {public static void main(String[] args) throws IOException {Person p = new Person("minh", 10, "male");//向文件中写入一个对象ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("/Users/minh/Desktop/output.txt")));oos.writeObject(p);oos.close();}
}

注:若创建的对象没有实现Serializable接口,会爆出NotSerializableException错误,因此想要序列化所创建对象的类,必须实现该接口。
但查看源码发现该接口为一个空接口,相当于只起一个标识的作用,称为标识接口,表明只有继承这个接口的类才能序列化。

从文件中读取该对象:

     //从文件中读取该对象ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("/Users/minh/Desktop/output.txt")));System.out.println((Person)(ois.readObject()));ois.close();

4、序列化版本标识符(serialVersionUID)

当对自定义对象类进行细微修改,导致文件中的数据和当前类对象不匹配,系统在读取文件数据时就会报错。
解决方案:给该类加一个“序列号”,即serialVersionUID

serialVersionUID:
凡是实现Serializable接口(标识接口)的类都会有一个标识序列化版本标识符的静态常量。
使用方法:private static final long serialVersionUID;
用其来表明类的不同版本间的兼容性。


5、序列化的细节

(1)被序列化的类的内部的所有属性,必须是可序列化的(基本数据类型都是可序列化的)
    例如:若被序列化的类内部有一个内部类,那么该类也必须实现Serializable接口。
(2)static、transient修饰的属性不能被序列化。
    因此,一些不希望被保存或被看见的属性就可以用这两个进行修饰。

java中IO流的相关知识相关推荐

  1. Java中IO流体系

    转载: https://mp.weixin.qq.com/s?__biz=MzA5NzgzODI5NA==&mid=2454030958&idx=1&sn=df27aadb92 ...

  2. Java中IO流的总结

    有关Java中IO流总结图 流分类 按方向分 输入流 输出流 按单位分 字节流 字符流 按功能分 节点流 处理流(过滤流) 其他 所有的流继承与这四类流:InputSteam.OutputStream ...

  3. Java中IO流,输入输出流概述与总结(转载自别先生文章)

    Java中IO流,输入输出流概述与总结 总结的很粗糙,以后时间富裕了好好修改一下. 1:Java语言定义了许多类专门负责各种方式的输入或者输出,这些类都被放在java.io包中.其中, 所有输入流类都 ...

  4. 【Java网络编程与IO流】Java中IO流分为几种?字符流、字节流、缓冲流、输入流、输出流、节点流、处理流

    Java网络编程与IO流目录: [Java网络编程与IO流]Java中IO流分为几种?字符流.字节流.缓冲流.输入流.输出流.节点流.处理流 [Java网络编程与IO流]计算机网络常见面试题高频核心考 ...

  5. Java中IO流面试题

    Java 中 IO 流分为几种? Java IO与 NIO的区别? 常用io类有那些? 字节流与字符流的区别? 说说阻塞 IO 模型? 说说非阻塞 IO 模型? 说说多路复用 IO 模型? 说说信号驱 ...

  6. 利用JAVA中关于继承的相关知识求得圆柱体体积并输出

    利用JAVA中关于继承的相关知识求得圆柱体体积并输出 Write a program: 1)Define a Circle class and a Cylinder class, which is d ...

  7. java中io流中显示中文_关于JAVA中IO流相关问题概述

    流是用于连接程序和设备之间的管道,主要用于数据传输.这个管道上有很多"按钮",每个"按钮"可以实现不同的功能. 四大基本抽象流:输入流,输出流,字节流,字符流 ...

  8. Java中IO流的分类和BIO,NIO,AIO的区别

    到底什么是IO 我们常说的IO,指的是文件的输入和输出,但是在操作系统层面是如何定义IO的呢?到底什么样的过程可以叫做是一次IO呢? 拿一次磁盘文件读取为例,我们要读取的文件是存储在磁盘上的,我们的目 ...

  9. java中io流是类吗_Java中的IO流

    今天刚刚看完java的io流操作,把主要的脉络看了一遍,不能保证以后使用时都能得心应手,但是最起码用到时知道有这么一个功能可以实现,下面对学习进行一下简单的总结: IO流主要用于硬板.内存.键盘等处理 ...

最新文章

  1. docker pull拉取镜像_docker拉取镜像失败解决
  2. mysql 优化实例(百万级数据)
  3. elastic的gc相关
  4. 祝福遨游:傲游浏览器3月将入住欧盟Win7用户桌面
  5. 把东西从学校搬回来了
  6. IPv6与IPv4的区别
  7. java利用数组随机抽取幸运观众_java利用数组随机抽取幸运观众
  8. 高等代数——大学高等代数课程创新教材(丘维声)——1.3笔记+习题
  9. 数学建模常用算法汇总及python,MATLAB实现(七) —— sklearn和SPSS实现主成分分析
  10. 2022年4月树莓派系统初始用户名密码
  11. php实现电脑自动关机,如何设置定时关电脑?三种方法教你设置电脑自动关机
  12. 未来十大最热门职业,可能消失的职业
  13. 使用python将pdf转化为长图片
  14. 黑马程序员还收费 兄弟会都是免费的
  15. Wolfram Mathematica学习笔记1
  16. Python实现电报加密(字母后移一位)
  17. 详解三大编译器:gcc、llvm 和 clang
  18. linux禁止中国使用方法,如果美国禁止软件系统,不让中国用Windows,中国何去何从?...
  19. 见鬼,TSC 编译 TS 文件出现了‘React‘ refers to a UMD global, but the current file is a module. Consider adding
  20. 美国盐湖城郊区一购物中心发生枪击案 致2人受伤

热门文章

  1. update多表联合更新
  2. python怎样用函数求水仙花数_python求解水仙花数的方法
  3. [翻译] 在 Overleaf 中追踪修订
  4. 网线接无线路由器LAN口,让手机通过WIFI上网
  5. php制作明信片,photoshop简单制作一张明信片
  6. 函数不正确如何修复?
  7. 正则表达式排除指定字符串
  8. 【ARM自学笔记】ARM7时钟简述及配置
  9. 2019计算机跨保经验:清(深)北交浙计算所经验
  10. 关于参加大数据培训机构有没有用的一些想法