70_Java_IO流_缓冲流_转换流_对象流_特殊流(dataoutstream)

举报
alexsully 发表于 2021/06/23 20:50:46 2021/06/23
【摘要】 缓冲流_Buffered 转换流_InputStreamReader_编解码 对象流_ObjectInputStream_序列化 特殊流(dataoutstream)-RandomAccessFile

处理流之一:缓冲流的使用

1.缓冲流:
    BufferedInputStream   BufferedOutputStream
    BufferedReader        BufferedWriter
2. 作用:提供流的读取、写入的速度  提高读写速度的原因:内部提供了一个缓冲区
3. 处理流,就是“套接”在已有的流的基础上

BufferedInputStream bis = null;
        BufferedOutputStream bos = null;

        try {
            //1.造文件
            File srcFile = new File(srcPath);
            File destFile = new File(destPath);
            //2.造流
            //2.1 造节点流
            FileInputStream fis = new FileInputStream((srcFile));
            FileOutputStream fos = new FileOutputStream(destFile);
            //2.2 造缓冲流
            bis = new BufferedInputStream(fis);
            bos = new BufferedOutputStream(fos);

            //3.复制的细节:读取、写入
            byte[] buffer = new byte[1024];
            int len;
            while((len = bis.read(buffer)) != -1){
                bos.write(buffer,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.资源关闭
            //要求:先关闭外层的流,再关闭内层的流
            if(bos != null){
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
            if(bis != null){
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
            //说明:关闭外层流的同时,内层流也会自动的进行关闭。关于内层流的关闭,我们可以省略.
//        fos.close();
//        fis.close();
        }
    }


@Test
    public void testBufferedReaderBufferedWriter(){
        BufferedReader br = null;
        BufferedWriter bw = null;
        try {
            //创建文件和相应的流
            br = new BufferedReader(new FileReader(new File("dbcp.txt")));
            bw = new BufferedWriter(new FileWriter(new File("dbcp1.txt")));

            //读写操作
            //方式一:使用char[]数组
//            char[] cbuf = new char[1024];
//            int len;
//            while((len = br.read(cbuf)) != -1){
//                bw.write(cbuf,0,len);
//    //            bw.flush();
//            }

            //方式二:使用String
            String data;
            while((data = br.readLine()) != null){
                //方法一:
//                bw.write(data + "\n");//data中不包含换行符
                //方法二:
                bw.write(data);//data中不包含换行符
                bw.newLine();//提供换行的操作

            }


        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //关闭资源
            if(bw != null){

                try {
                    bw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(br != null){
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }


处理流之二:转换流的使用
  1.转换流:属于字符流
    InputStreamReader:将一个字节的输入流转换为字符的输入流
    OutputStreamWriter:将一个字符的输出流转换为字节的输出流
 
  2.作用:提供字节流与字符流之间的转换
 
  3. 解码:字节、字节数组  --->  字符数组、字符串  (看不懂到看得懂 -InputStreamReader)
     编码:字符数组、字符串 ---> 字节、字节数组  (OutputStreamWriter)


4.字符集
 ASCII:美国标准信息交换码。用一个字节的7位可以表示(合计8位,但是其中一位没用,2*7  128)
 ISO8859-1:拉丁码表。欧洲码表用一个字节的8位表示。
 GB2312:中国的中文编码表。最多两个字节编码所有字符
 GBK:中国的中文编码表升级,融合了更多的中文文字符号。最多两个字节编码
 Unicode:国际标准码,融合了目前人类使用的所有字符。为每个字符分配唯一的字符码。所有的文字都用两个字节来表示。
 UTF-8:变长的编码方式,可用1-4个字节来表示一个字符。



    @Test
    public void test2() throws Exception {
        //1.造文件、造流
        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");

        //2.读写过程
        char[] cbuf = new char[20];
        int len;
        while((len = isr.read(cbuf)) != -1){
            osw.write(cbuf,0,len);
        }

        //3.关闭资源
        isr.close();
        osw.close();

    }


三 其他处理流的使用
  1.标准的输入、输出流
  2.打印流
  3.数据流


其他流的使用
  1.标准的输入、输出流
  2.打印流
  3.数据流
  
1.标准的输入、输出流
    System.in:标准的输入流,默认从键盘输入
    System.out:标准的输出流,默认从控制台输出
    System类的setIn(InputStream is) / setOut(PrintStream ps)方式重新指定输入和输出的流
    
2 打印流:PrintStream 和PrintWriter

3. 数据流 :为了方便地操作Java语言的基本数据类型和String的数据,可以使用数据流
    将文件中存储的基本数据类型变量和字符串读取到内存中,保存在变量中。
    注意点:读取不同类型的数据的顺序要与当初写入文件时,保存的数据的顺序一致!
    3.1 DataInputStream 和 DataOutputStream
    3.2 作用:用于读取或写出基本数据类型的变量或字符串


public class other {
    public static void main(String[] args) {
        BufferedReader br= null;
        //public final static InputStream in = null;
        try {
            InputStreamReader ins  = new InputStreamReader(System.in);
            br= new BufferedReader(ins);

            while (true){
                System.out.println("请输入字符串: ");
                String s = br.readLine();
                if ("e".equalsIgnoreCase(s) || "exit".equalsIgnoreCase(s)){
                    System.out.println("88");
                    break;
                }
                System.out.println(s.toUpperCase());
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                br.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Test
    public void test1(){
        PrintStream ps = null;
        try {
            FileOutputStream fos = new FileOutputStream("alex.txt");
            ps = new PrintStream(fos, true);  //自动刷新
            if (ps !=null ){
                System.setOut(ps);   // 指定打印位置
            }
            for (int i = 0; i <=100 ; i++) {
                System.out.print((char) i );
                if (i % 50 == 0) { // 每50个数据一行
                    System.out.println(); // 换行
                }
            }

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            ps.close();
        }
    }

    @Test
    public void test2() throws  IOException{
        DataOutputStream dos  = new DataOutputStream(new FileOutputStream("alex2"));
        dos.writeUTF("alex");
        dos.writeInt(1);
        dos.writeBoolean(true);
        dos.flush();
        dos.close();
    }

    /*
将文件中存储的基本数据类型变量和字符串读取到内存中,保存在变量中。
注意点:读取不同类型的数据的顺序要与当初写入文件时,保存的数据的顺序一致!
 */
    @Test
    public void test3() throws  IOException{
        DataInputStream diss  = new DataInputStream(new FileInputStream("alex2"));
        String s = diss.readUTF();
        int i = diss.readInt();
        boolean b = diss.readBoolean();
        System.out.println(s);
        System.out.println(i);
        System.out.println(b);

    }
}


四  处理流之 对象流

对象流的使用
   1.ObjectInputStream 和 ObjectOutputStream
   2.作用:用于存储和读取基本数据类型数据或对象的处理流。它的强大之处就是可以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来
   3.要想一个java对象是可序列化的,需要满足相应的要求。见Person.java
   4.序列化机制:
   对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,
   从而允许把这种二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点
   当其它程序获取了这种二进制流,就可以恢复成原来的Java对象



public class ObjectInputOutputStreamTest {

    /*
    序列化过程:将内存中的java对象保存到磁盘中或通过网络传输出去
    使用ObjectOutputStream实现
     */
    @Test
    public void testObjectOutputStream(){
        ObjectOutputStream oos = null;

        try {
            //1.
            oos = new ObjectOutputStream(new FileOutputStream("object.dat"));
            //2.
            oos.writeObject(new String("我爱北京天安门"));
            oos.flush();//刷新操作

            oos.writeObject(new Person("王铭",23));
            oos.flush();

            oos.writeObject(new Person("张学良",23,1001,new Account(5000)));
            oos.flush();

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(oos != null){
                //3.
                try {
                    oos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        }

    }

    /*
    反序列化:将磁盘文件中的对象还原为内存中的一个java对象
    使用ObjectInputStream来实现
     */
    @Test
    public void testObjectInputStream(){
        ObjectInputStream ois = null;
        try {
            ois = new ObjectInputStream(new FileInputStream("object.dat"));

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

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

            System.out.println(str);
            System.out.println(p);
            System.out.println(p1);

        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            if(ois != null){
                try {
                    ois.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        }
    }
}

可序列化
  1.需要实现接口:Serializable
  2.当前类提供一个全局常量:serialVersionUID
  3.除了当前Person类需要实现Serializable接口之外,还必须保证其内部所有属性
   也必须是可序列化的。(默认情况下,基本数据类型可序列化)
  补充:ObjectOutputStream和ObjectInputStream不能序列化static和transient修饰的成员变量

public class Person implements Serializable{
    public static final long serialVersionUID = 475463534532L;
    private String name;
    private Account acct;}

class Account implements Serializable{
    public static final long serialVersionUID = 4754534532L;
    private double balance;}


五 特殊流(任意流) RandomAccessFile DataInputStream  DataOutputStream

RandomAccessFile的使用(任意)
  1.RandomAccessFile直接继承于java.lang.Object类,实现了DataInput和DataOutput接口
  2.RandomAccessFile既可以作为一个输入流,又可以作为一个输出流
  3.如果RandomAccessFile作为输出流时,写出到的文件如果不存在,则在执行过程中自动创建。
     如果写出到的文件存在,则会对原有文件内容进行覆盖。(默认情况下,从头覆盖)
  4.可以通过相关的操作,实现RandomAccessFile“插入”数据的效果

public class RandomAccessFileTest {
    @Test
    public  void test1() throws IOException {
        RandomAccessFile rfa1 = new RandomAccessFile(new File("xxx"), "r");
        RandomAccessFile rfa2 = new RandomAccessFile(new File("xxx"), "rw");
        int len;
        byte[] bytes = new byte[1024];
        while ((len= rfa1.read(bytes)) != -1){
            rfa2.write(bytes,0,len);
        }

        rfa1.close();
        rfa2.close();
    }


    @Test
    public void test2() throws IOException {
        RandomAccessFile rfarw = new RandomAccessFile(new File("hello.txt"), "rw");

        int len;
        byte[] bytes = new byte[20];
        StringBuilder stringBuilder = new StringBuilder((int) new File("hello.txt").length());
        rfarw.seek(3); //将指针调到角标为3的位置
        //保存指针3后面的所有数据到StringBuilder中

        while ((len= rfarw.read(bytes)) != -1){
            stringBuilder.append(new String(bytes,0,len));

        }
        //调回指针,写入"abc"
        rfarw.seek(3);
        rfarw.write("abc".getBytes());
        //将StringBuilder中的数据写入到文件中
        rfarw.write(stringBuilder.toString().getBytes());  // 此处是顺序写入

        rfarw.close();
    }

    @Test
    public void test3() throws IOException {
        RandomAccessFile rfarw = new RandomAccessFile(new File("hello2.txt"), "rw");
        
        rfarw.write("abc".getBytes());
        rfarw.write("ddd".getBytes()); // 顺序写入
    }
    
}





【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。