2021-10-21

转换流

在这里插入图片描述
在这里插入图片描述
处理流二:转换流的使用
1,转换流:属于字符流
InputStreamRead:将一个字节的输入流转换为字符的输入流;
OutputStreamWriter:将一个字符的输出流转换为字节的输出流;
2.作用:提供字节流与字符流之间的转换;
3.解码:字节、字节数组–>字符数组、字符串
编码:字符数组、字符串–>字节、字节数组
4.字符集
在这里插入图片描述
针对中文编码(gb2312,gbk),我们这里最多两个两个字节。如何判断是一个字节表示一个字符还是两个字节表示一个字符。判断标准是,如果开头是0那么是一个字节表示一个字符;如果是开头是1那么表示是两个字节表示一个字符。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
ANSI:美国国家标准学会(AMERICAN NATIONAL STANDARDS INSTITUTE: ANSI )

InputStreamReader的使用,实现字节的输入流到字符的输入流的转换

package com.atguigu.java;

import org.junit.Test;

import java.io.*;

public class InputStreamReaderTest {
    //InputStreamReader的使用,实现字节的输入流到字符的输入流的转换
    @Test
    public void testInputStreamReader() throws IOException {
        FileInputStream fis = new FileInputStream("dbcp.txt");
        //InputStreamReader isr = new InputStreamReader(fis);//默认使用系统默认的字符集
        //参数二指明了字符集,具体使用哪个字符集,取决于文件保存时使用的字符集;大小写不敏感
        InputStreamReader isr = new InputStreamReader(fis,"utf-8");//这里的字符集的选择是当初创建时是什么字符集就用什么字符集

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

综合使用InputStreamReader和OutputStreamWriter,这里输出的为用gbk编码的文件。

@Test
    //综合使用InputStreamReader和OutputStreamWriter
    public void test1() throws IOException {
        File file1 = new File("dbcp.txt");
        File file2 = new File("dbcp_gbk.txt");

        FileInputStream fis = new FileInputStream(file1);
        FileOutputStream fos = new FileOutputStream(file2);

        InputStreamReader isr = new InputStreamReader(fis, "utf-8");
        OutputStreamWriter osw = new OutputStreamWriter(fos,"gbk");

        char[] cbuf = new char[20];
        int len;
        while((len=isr.read(cbuf))!=-1){
            osw.write(cbuf,0,len);
        }
        osw.close();
        isr.close();

    }

对象流要掌握,其他流了解。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
练习题答案:

package com.atguigu.java;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

//其他流的使用
/*
1.标准的输入输出流
2.打印流
3.数据流
 */
//练习:从键盘输入字符串,要求将读取到的整行字符串转成大写输出。然后继续进行输入操作,直至输入
//字符“e”或字符“exit”退出
public class otherStreamTest {
    public static void main(String[] args) throws IOException {
        InputStreamReader isr = new InputStreamReader(System.in);
        BufferedReader br = new BufferedReader(isr);

        while (true){
            System.out.println("请输入字符串:");
            String data = br.readLine();
            //这里是避免控制人问题,不建议这种写法
            //(data.equalsIgnoreCase("e")||data.equalsIgnoreCase("exit"))
            if ("e".equalsIgnoreCase(data)||"exit".equalsIgnoreCase(data)){
                System.out.println("程序结束");
                break;
            }

            String  upperCase = data.toUpperCase();
            System.out.println(upperCase);
        }
        br.close();
    }
}

标准输入输出流,实现我们自己的scanner。

package com.atguigu.exer;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class MyInput {
    //Read a String from keyboard
    public static String readString() {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        //Declare and initialize the string
        String string = "";

        //Get the string from the keyboard
        try {
            string = br.readLine();
        } catch (IOException ex) {
            System.out.println(ex);
        }
        //Return the string obtained from the keyboard
        return string;
    }
    //Read an int value from the keyboard
    public static int readInt(){return Integer.parseInt(readString());}
    //Read a double value from the keyboard
    public static double readDouble(){return Integer.parseInt(readString());}
    //Read a byte value from the keyboard
    public static double readByte(){return Integer.parseInt(readString());}
    //Read a short value from the keyboard
    public static double readShort(){return Integer.parseInt(readString());}
    //Read a long value from the keyboard
    public static double readLong(){return Integer.parseInt(readString());}
    //Read a float value from the keyboard
    public static double readFloat(){return Integer.parseInt(readString());}
}

在这里插入图片描述
在这里插入图片描述
System.setOut()方法就是不会在控制台输出,在指定文件输出。
中间for循环代码生成结果:在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

@Test
    //将内存中字符串、基本数据类型的变量写出到文件中
    public void test() throws IOException {
        DataOutputStream dos = new DataOutputStream(new FileOutputStream("data.txt"));

        dos.writeUTF("孔空");
        dos.flush();//刷新操作,将内存中的数据写入文件。
        dos.writeInt(21);
        dos.flush();
        dos.writeBoolean(true);
        dos.flush();


        dos.close();
    }
    @Test
    //这里不要直接打开文件,操作是不对的,得读完之后在控制台看
    //将文件中存储的基本数据类型变量和字符串读取在内存中,保存在变量中
    public void test1() throws IOException {
        DataInputStream dis = new DataInputStream(new FileInputStream("data.txt"));
        //顺序很重要,写进去什么顺序读进去就是什么顺序
        String name = dis.readUTF();
        int age = dis.readInt();
        boolean isMale = dis.readBoolean();

        System.out.println("name:"+name);
        System.out.println("age:"+age);
        System.out.println("isMale:"+isMale);

        dis.close();
    }

对象流
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
这里针对的是对象流阐述的序列化,其实在客户端与服务端,app之间也是用的序列化和反序列化。
序列化机制:
对象序列化机制云南徐把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久的保存在磁盘上,或者通过网络讲这种二进制流传输到另一个网络节点。当其它程序获取了这种二进制流,就可以回复称原来的Java对象。(跨进程访问,都要求可序列化(就是json))
String类的序列和反序列:

package com.atguigu.java;

import org.junit.Test;

import java.io.*;

public class ObjectInputOutputStreamTest {
    /*
    首先是序列化过程,将内存中的Java对象保存在磁盘中或通过网络传输出去
    使用objectOutputStream实现
     */
    @Test
    public void test1() throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("object.dat"));

        oos.writeObject(new String("即使再小的帆也能远航"));//String是内存层面的,有可能会被内存回收,我们把它写入到硬盘就不会了,也就是持久

        oos.flush();

        oos.close();
    }
    /*
    反序列化,将磁盘文件中的对象还原为内存中的一个Java对象
     */
    @Test
    public void test2() throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("object.dat"));

        Object obj = ois.readObject();
        String str = (String) obj;
        System.out.println(str);
        ois.close();

    }

}

自定义类的序列和反序列:

package com.atguigu.java;

import org.junit.Test;

import java.io.*;

public class ObjectInputOutputStreamTest {
    /*
    首先是序列化过程,将内存中的Java对象保存在磁盘中或通过网络传输出去
    使用objectOutputStream实现

    要想一个Java对象是可序列化的,需要满足相应的要求,见person类
     */
    @Test
    public void test1() throws IOException {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("object.dat"));

        oos.writeObject(new String("即使再小的帆也能远航"));//String是内存层面的,有可能会被内存回收,我们把它写入到硬盘就不会了,也就是持久
        oos.flush();

        oos.writeObject(new Person("孔空",21));
        oos.flush();

        oos.close();

    }
    /*
    反序列化,将磁盘文件中的对象还原为内存中的一个Java对象
     */
    @Test
    public void test2() throws IOException, ClassNotFoundException {
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("object.dat"));

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

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

        System.out.println(p);
        System.out.println(str);
        ois.close();

    }

}

不加的话,如果对对象进行修改。就会报错,因为Java自己帮你生成的是随机的,下次你改过以后他就不认识了。
在这里插入图片描述

package com.atguigu.java;

import java.io.Serializable;

/*
1.必须要继承Serializable接口。
该接口没有任何方法声明,故我们称此类为标识接口
2.一定要给一个全局常量,随意给一个值就行
3.除了当前Person类实现Serializable接口之外,还必须保证其内部所有属性也必须是可序列化的(默认情况下基本数据类型就是可序列化的)。
补充:ObjectInputStream和ObjectOuputStream不能序列化static和transient修饰的成员变量(将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会被序列化。)。
 */
public class Person implements Serializable {
    public static final long serialVersionUID = 242142142142L;
    private String name;
    private int age;

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Person() {
    }
}

随机存取文件流
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

package com.atguigu.java;

import org.junit.Test;

import java.io.IOException;
import java.io.RandomAccessFile;

/*
RandomAccessFile的使用
1.直接继承于Object类,实现了DataInput和DataOutput接口
2.RandomAccessFile既可以作为一个输入流,又可以作为一个输出流
3.如果RandomAccessFile作为输出流时,写出到的文件如果不存在,则在执行过程中自动创建。
如果写出道德文件存在,则会对原有文件进行覆盖,默认从头开始覆盖。 
4.可以通过线管操作,实现RandomAccessFile	插入效果
 */
public class RandomAccessFileTest {
    @Test
    public void test1() throws IOException {
        RandomAccessFile raf1 = new RandomAccessFile("QQ图片20211018170403.png", "r");
        RandomAccessFile raf2 = new RandomAccessFile("QQ图片202110181704037.png", "rw");

        byte[] buffer = new byte[1024];
        int len;
        while((len=raf1.read(buffer))!=-1){
            raf2.write(buffer,0,len);
        }
        raf1.close();
        raf2.close();
    }
}

使用RandomAccessFile实现数据的插入:

 /*
    使用RandomAccessFile实现数据的插入
     */
    @Test
    public void test3() throws IOException {
        RandomAccessFile raf2 = new RandomAccessFile("data.txt", "rw");

        raf2.seek(3);//将指针调到角标为3的位置
        //保存指针3后面的所有数据到StringBuilder中

        StringBuilder builder = new StringBuilder((int) new File("data.txt").length());//StringBuilder实际上造的是一个数组,这里的.length是他早的数组的长度
        byte[] buffer = new byte[20];
        int len;
        while ((len=raf2.read(buffer))!=-1){
            builder.append(new String(buffer,0,len));
        }
        //调回指针,写入“xyz”
        raf2.seek(3);
        raf2.write("xyz".getBytes());

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

        raf2.close();
        //思考:可以将StringBuilder替换为ByteArrayOutputStream
    }

在这里插入图片描述
ByteArrayOutputStream的使用:
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

最后了解:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值