JavaSE模板化的IO流

IO流

首先说明一下本章主要学什么,IO流,其实就是升级版的File文件操作,在本章通过学习一些流,调用相应的方法,就可以实现从程序到文件,再从文件到程序的相应操作,而这一章节的代码也比较模板化,因此只需要记住基本的流,基本的使用方法,具体应用可以在项目中进行实践。

一、流的三种分类方式
1.流向

输入流、输出流

2.数据单位

字节流、字符流

3.流的角色

节点流、处理流

二、流的结构体系

在这里只提供一些常用常见的流

这个表其实也不用记,看一眼,知道有啥东西就行了,重点在后边。

分类字节输入流字节输出流字符输入流字符输出流
抽象基类InputStreamOutputStreamReaderWriter
访问文件FileInputStreamFileOutputStreamFileReaderFileWriter
访问数组ByteArrayInputStreamByteArrayOutputStreamCharArrayReaderCharArrayWriter
访问字符串StringReaderStringWriter
缓冲流BufferedInputStreamBufferedOutputStreamBufferedReaderBufferedWriter
转换流InputStreamReaderOutputStreamWriter
对象流ObjectInputStreamObjectOutputStream
特殊流DataInputStreamDataOutputStream
三、输入、输出的标准化过程

模板的输入输出过程我用文件的字节输入输出流演示

1.输入过程

①创建File类的对象,指明读取的数据的来源(要求此文件一定存在)

File srcFile = new File("d:\\zyb.jpg");

②创建相应的输入流,将File类的对象作为参数,传入流的构造器中

FileInputStream fis = new FileInputStream(srcFile);

③读入过程:创建相应的byte[]或char[],并调用fis的read方法,放入循环中

byte[]buffer=new byte[10];
int len=0;
while((len=fis.read(buffer))!=-1){
    System.out.println(new String(buf,0,len));
}

④关闭流资源

fis.close();

说明:程序中出现的异常需要使用try-catch-finally处理

2.输出过程

①创建File对象,指明写出数据的位置(不要求此文件一定要存在)

File destFile = new File("d:\\zyb2.jpg");

②创建相应的输出流,将File类的对象作为参数,传入流的构造器中

FileOutputStream fos = new FileOutputStream(destFile);

③写出(创建buffer数组和len指针变量的过程和输入过程相同)

fos.write(buffer,0,len);

④关闭流资源

fos.close();
四、节点流
1.FileReader(字符输入流)

说明点:1、read()理解:返回读入的一个字符。如果到达文件末尾,则返回-1.

​ 2、异常处理:为了保证流资源一定可以执行关闭操作,需要使用try-catch-finally

​ 3、读入的文件一定要存在,否则会报FileNotFoundException异常

代码演示:

@Test
public void testFileReader1() throws IOException {

    //1.File类的实例化
    File file = new File("e:\\news2.txt");

    //2.FileReader流的实例化
    FileReader fileReader = new FileReader(file);

    //3.读入文件的操作
    //read(char[] cubf):每次返回读入cubf数组中的字符个数,如果到达文件末尾,则返回-1
    char[]cbuf = new char[5];
    int len=0;
    while((len = fileReader.read(cbuf))!=-1){
        String str = new String(cbuf,0,len);
        System.out.println(str);
    }

    //4.资源的关闭
    fileReader.close();

}
2.FileWriter(字符输出流)

说明:1.输出到文件的操作,对应的File可以不存在,不会报异常

​ 2.File对应的硬盘中的文件如果不存在,在输出的过程中,会自动创建此文件。

​ File对应的硬盘中的文件如果存在:

有两种构造器,如果流使用的构造器是FileWriter(file)/FileWriter(file,false)则写入的信息会对原文件进行覆盖,比如原文件中已经含有字符“hello”,而我使用writer写入“world”,则最后文件的内容只有“world”。

​ 如果流使用的构造器是**FileWriter(file,true)**那么进行的是对原文件的续写操作,不会进行覆盖。比如原文件中已经含有字符“hello”,我写入“world”,则最后文件的内容为“hello world”。

代码演示:

@Test
public void testFileWriter() throws IOException {
    
    //1.提供File类的对象,指明写出到的文件
    File file = new File("hello1.txt");
    
    //2.提供FileWriter的对象,用于数据的写出
    FileWriter fw = new FileWriter(file, false);
    
    //3.写出到文件操作
    fw.write("wu zi bu xing\n");
    fw.write("edg nb!");
    
    //4.流资源的关闭
    fw.close();
    
}
3.文本文件的复制

文本文件的复制操作是通过在一个程序中同时调用输入流和输出流,进而实现创建一个新的文本,并对其进行赋值。

代码如下:

其中,srcFile是被复制的文件,destFile是将要创建,进行复制的文件。

@Test
public void testFileReaderWriter() throws IOException {
    
    //1.创建File类的对象,指明读入和写出的文件
    File srcFile = new File("hello1.txt");
    File destFile = new File("hello2.txt");
    
    //2.创建输入流和输出流的对象
    FileReader fr = new FileReader(srcFile);
    FileWriter fw = new FileWriter(destFile);
    
    //3.数据的读入和写出操作
    char[] cubf = new char[5];
    int len;
    while((len=fr.read(cubf))!=-1){
        fw.write(cubf,0,len);
    }
    
    //4.关闭流
    fw.close();
    fr.close();
}
4.FileInputStream / FileOutputStream(字节流)

​ 呃,这个和上面的字符流一样,没什么好说的,代码模板都一样,只需要在写入写出的时候把char[]数组换成byte[]数组就行了。。。

比较一下:对于文本文件(.txt,.java,.c,.cpp)之类的都使用字符流处理

​ 对于非文本文件(图片,音频,视频),使用字节流处理

五、缓冲流
1.缓冲流涉及到的类:

BufferedInputStream、BufferedOutputStream、BufferedReader、BufferedWriter

2.作用

提高流的读取、写入速度

原理:内部提供了一个缓冲区。默认情况下是8kb

3.代码实现
·1BufferedInputStream、BufferedOutStream

该代码是用节点流+缓冲流实现图片的复制

其实缓冲流的代码跟上边节点流的代码模板一样,只不过多了一步将节点流的对象放入缓冲流的构造器中的步骤

@Test
public void BufferedStreamTest() throws IOException {
    
        //1.造文件
        File srcFile = new File("d:\\zyb.jpg");
        File destFile = new File("d:\\zyb2.jpg");

        //2.造节点流
        FileInputStream fis = new FileInputStream(srcFile);
        FileOutputStream fos = new FileOutputStream(destFile);

        //3.造缓冲流
        BufferedInputStream bis = new BufferedInputStream(fis);
        BufferedOutputStream bos = new BufferedOutputStream(fos);

        //4.复制:用bis读取,用bos写入
        byte[]buffer=new byte[10];
        int len=0;
        while((len=bis.read(buffer))!=-1) {
            bos.write(buffer, 0, len);
        }

        //5.资源关闭
        //要求:先关闭外层的流,再关闭内层的流
        bos.close();
        bis.close();
    }
·2BufferedReader、BufferedWriter

之前一直都是分开写,代码比较多,现在简写一下,试试将造文件的过程和造节点流的过程一起合并到造缓冲流的过程。

@Test
public void testBufferedReaderBufferedWriter() throws IOException {
    
        //1.将造文件,造节点流合成一步
        BufferedReader  bufferedReader = new BufferedReader(new FileReader(new File("e:\\news1.txt")));
        BufferedWriter   bufferedWriter = new BufferedWriter(new FileWriter(new File("e:\\news2.txt")));
       
        //2.数据的读入写出
        char[]cbuf=new char[1024];
        int len=0;
        while((len=bufferedReader.read(cbuf))!=-1){
            bufferedWriter.write(cbuf,0,len);
        }
        
        //3.关流
        bufferedReader.close();
        bufferedWriter.close();

    }
六、转换流
1.涉及到的类

InputStreamReader:将一个字节的输入流转换为字符的输入流

解码:字节、字节数组—>字符数组、字符串

OutputStreamWriter:将一个字符的输出流转换为字节的输出流

编码:字符数组、字符串—>字节、字节数组

编码决定解码!!!

2.作用

提供字节流的字符流之间的转换

3.代码实现
·InputStreamReader

将字节输入流转换为字符输出流

呃,其实就多加了一步将字节输入流的对象放到转换流的构造器中而已

//转换输入流
@Test
public void test1() throws IOException {
    
    FileInputStream fileInputStream = new FileInputStream("e:\\news1.txt");						           
    //参数“UTF-8”指明了字符集(根据文件初始存的时候决定)
    InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream,"UTF-8");

    char[]cbuf=new char[1];
    int len;
    while((len=inputStreamReader.read(cbuf))!=-1){
        String str=new String(cbuf,0,len);
        System.out.print(str);
    }
    
    inputStreamReader.close();
}
·OutputStreamWriter

将字符输出流转换为字节输出流

写了这么多了,学了节点流,缓冲流,转换流,那现在咱们把这三个流都用到一起,综合升华一下,嘿嘿

这段代码的作用是实现文本的复制,就是将news1.txt中的文本信息复制到nesw3.txt中

快结束了,再来综合复习一下吧兄弟们

①造文件

②造节点流

③造缓冲流,提高运行效率

④造转换流,分别将输入流和输出流放入两个转换流中

⑤数组+循环 实现读入和写出

⑥关闭流

//转换输出流
@Test
public void test2() throws IOException{
	
    
    File file1 = new File("e:\\news1.txt");
    File file2 = new File("e:\\news3.txt");

    FileInputStream fileInputStream = new FileInputStream(file1);
    FileOutputStream fileOutputStream = new FileOutputStream(file2);
    
    BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);
    BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream);

    InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream);
    OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream,"gbk");

    char[]cubf=new char[1];
    int len;
    while((len=inputStreamReader.read(cubf))!=-1){
        outputStreamWriter.write(cubf,0,len);
    }

    inputStreamReader.close();
    outputStreamWriter.close();
}
七、其它特殊流
1.标准的输入输出流

System.in:标准的输入流,默认从键盘输入 例如:new Scanner(System.in)

System.out:标准的输出流,默认从控制台输出 例如:System.out.println()

2.打印流

PrintStream和PrintWriter

说明:提供了一系列重载的print()和println()方法,用于多种数据类型的输出

​ System.out返回的是PrintStream的实例

3.数据流

DataInputStream和DataOutputStream

作用:用于读取或写出基本数据类型的变量或字符串

上面的三个流作为了解即可,不用深入

八、对象流
1.介绍

ObjectInputStream和ObjectOutputStream

作用:

ObjectInputStream:**内存中的对象—>存储中的文件、通过网络传输出去 ** 序列化过程

ObjectOutputStream:存储中的文件、通过网络接受过来—>内存中的对象 反序列化过程

2.对象的序列化机制

概念描述:

序列化过程:把内存中Java对象转换成平台无关的二进制流,从而把这种二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。

反序列化过程:当其它程序获取了这种二进制流之后,就可以恢复成原来的Java对象

3.代码实现

序列化过程

​ 在这里说一点就是,java可以对自定义类进行序列化转换,但这个自定义类需要满足两个条件,第一个就是需要实现Serializable接口,这个接口是一个标识接口,不需要重写任何方法。第二个就是在类中需要提供一个全局常量serialVersionUID,其中这个全局常量的值必须进行自定义修改,任何值都可以。

  •    * @author 一只鱼zzz
     
       * @version 1.0
     
         * Person类需要满足一下的要求,方可序列化
     
         * 1.需要实现接口:Serializable(标识接口,无需重写方法)
     
         * 2.当前类需要提供一个全局常量:serialVersionUID
           */
           public class Person implements Serializable {
     
            public static final long serialVersionUID = 1231213123132L;
     
            private String name;
            private int age;
     
         public Person(String name, int age) {
                this.name = name;
                this.age = age;
            }
     
            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;
         }
     
         @Override
         public String toString() {
             return "Person{" +
                     "name='" + name + '\'' +
                     ", age=" + age +
                     '}';
         }
         }
    

/*
序列化过程:将内存中的java对象保存到磁盘中或通过网络传输出去
使用ObjectOutputStream实现
*/
@Test
public  void test1(){
   
       //1.造流造文件
       ObjectOutputStream oos = null;
   	try {
       oos = new ObjectOutputStream(new FileOutputStream("e:\\news1.dat"));
       //2.写
       oos.writeObject(new String("我爱轻大"));
       oos.flush();
       //3.刷新
       oos.writeObject(new Person("一只鱼zzzz",19));
       oos.flush();
   } catch (IOException e) {
       e.printStackTrace();
   } finally {
       //4.关
       try {
           oos.close();
       } catch (IOException e) {
           e.printStackTrace();
       }
   }
}

反序列化过程

@Test
public void  test2(){
    ObjectInputStream ois = null;
    try {
        ois = new ObjectInputStream(new FileInputStream("e:\\news1.dat"));

        Object obj=ois.readObject();
        String str=(String)obj;

        Person p = (Person) ois.readObject();

        System.out.println(p);
        System.out.println(str);
    } catch (IOException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    } finally {
        try {
            ois.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
九、RandomAccessFile流
1.介绍

(1)该类直接继承于Object类,实现了DataInput和DataOutput接口

(2)既可以作为一个输入流,又可以作为一个输出流

(3)如果作为输出流时,写出到的文件如果不存在,则在执行过程中自动创建。如果写出到的文件存在,则会对原文件内容进行覆盖。(默认情况下,从头覆盖)

(4)通过相关的操作,可以实现RandomAccessFile“插入数据”的功能

2.典型代码1
@Test
public void test1() throws IOException {

    RandomAccessFile raf1 = new RandomAccessFile(new File("hello1.txt"), "r");
    RandomAccessFile raf2 = new RandomAccessFile(new File("hello3.txt"), "rw");
    
    byte[]buffer = new byte[1024];
    int len;
    while((len=raf1.read(buffer))!=-1){
        raf2.write(buffer,0,len);
    }

    raf2.close();
    raf1.close();
}
3.典型代码2(插入效果)
@Test
public void test2() throws IOException {

    RandomAccessFile raf1 = new RandomAccessFile("hello3.txt", "rw");

    raf1.seek(3);//将指针调节到角标为3的位置

    //保存指针3后面的所有数据到StringBuilder中
    StringBuilder builder = new StringBuilder((int) new File("hello3.txt").length());

    byte[] buffer = new byte[20];
    int len;
    while((len=raf1.read(buffer))!=-1){
        builder.append(new String(buffer,0,len));
    }

    //调回指针,写入“xyz”
    raf1.seek(3);
    raf1.write("xyz".getBytes());

    //将StringBuilder中的数据写入到文件中
    raf1.write(builder.toString().getBytes());

    raf1.close();
}
  • 8
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值