一些有意思的IO流

一.数据输入输出流
数据输入流: DataInputStream
数据输出流: DataOutputStream
这类流的特点是可以读和写基本数据类型
我们通过调用方法来实现这一目的

package org.jimmy.demo;

import java.io.*;

/**
 * @Author: Administrator
 * @CreateTime: 2019-01-21 15:50
 */
public class IODemo {
    public static void main(String[] args) throws IOException {
        DataOutputStream out = new DataOutputStream(new FileOutputStream("a.txt"));
        DataInputStream in = new DataInputStream(new FileInputStream("a.txt"));
        out.writeChar('a');
        out.writeUTF("你好");
        out.writeBoolean(true);
        out.writeInt(12);
        out.writeInt(78);
        char c = in.readChar();
        String s = in.readUTF();
        boolean b = in.readBoolean();
        int i = in.readInt();
        int i1 = in.readInt();
        System.out.println(c);
        System.out.println(s);
        System.out.println(b);
        System.out.println(i);
        System.out.println(i1);
        in.close();
        out.close();
    }
}

这里,刚开始怎么写入的,就怎么读,顺序不要乱。

a
你好
true
12
78

二.内存操作流
内存操作流,顾名思义,是在内存中进行操作,无需关联文件,数据的读写只在内存中进行,所以内存操作流也无需关闭
内存操作流的概述
内存操作流可以分为:
操作字节数组——
ByteArrayOutputStream
ByteArrayInputStream
操作字符数组——
CharArrayWrite
CharArrayReader
操作字符串——
StringWriter
StringReader
我们来通过一段代码对一些方法作以了解
操作字节数组:

package org.jimmy.demo2;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

/**
 * @Author: Administrator
 * @CreateTime: 2019-01-21 16:08
 */
public class IODemo {
    public static void main(String[] args) throws IOException {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
       out.write(19);
       out.write("你好".getBytes());
        byte[] bytes = out.toByteArray();//取出存在缓冲区的数据
        String s = new String(bytes);
        System.out.println(s);//将数据转成字符串形式输出
        ByteArrayInputStream in = new ByteArrayInputStream(bytes);
        byte[] bytes1 = new byte[1024 * 8];
        int i = in.read(bytes1,0,4);
        System.out.println(new String(bytes1,0,i));

    }
}

要注意,在进行读的操作时,每次读的最后一个字节要确保是一个数据刚好结束,例如上面代码中,一个汉字占三个字节,如果从零读到第二个字节的话,这个“你”不能输出,输出会是一个乱码,所以从0读到4,则可以将“你”读出来
操作字符数组:

package org.jimmy.demo2;

import java.io.CharArrayWriter;

/**
 * @Author: Administrator
 * @CreateTime: 2019-01-21 17:01
 */
public class IODemo2 {
    public static void main(String[] args)  {
        CharArrayWriter chw = new CharArrayWriter();
        chw.write(2);
        chw.write('s');
        chw.write(new char[]{'2','d','a','t'},0,2);//读取字符数组的一部分
        java.lang.String s = chw.toString();
        System.out.println(s);

    }
}
s2d

操作字符串的操作与字符数组类似
三.打印流
打印流分为字符流和字节流,而且只能写,不能读,所以一般需要别的写入操作来配合
我们经常用到的输出到屏幕就是用打印流来实现,例如下面这段代码:

public class IODemo3 {
    public static void main(String[] args) {
        PrintStream out=System.out;//关联屏幕
        out.println(100);
        out.print(true);
    }
}
100
true

这就是输出语句的由来;
字节操作打印流有一个特点,其他的字节流都需要我们来手动刷新,但打印流可以通过传入布尔类型的参数来实现自动刷新,但在写入数据时调用println,printf,format中的一个方法才能执行自动刷新,如果调用write方法时仍需要flush方法来刷新;

public class IODemo4 {
    public static void main(String[] args) throws IOException {
        PrintWriter prw = new PrintWriter(new FileOutputStream("b.txt"), true);
        prw.println("ab");
        prw.write(111);
        prw.flush();
        prw.println("你好");
        prw.close();
    }
}

b.txt被自动创建,其内容为:

ab
o你好

我们同样可以用打印流来实现文本文件复制,一次读取一行,且实现自动刷新换行:

public class IODemo5 {
    public static void main(String[] args) throws IOException {
        BufferedReader bfr = new BufferedReader(new FileReader("b.txt"));
        PrintWriter prw = new PrintWriter(new FileOutputStream("c.txt"),true);
        String line=null;
        while ((line=bfr.readLine())!=null){
            prw.println(line);
        }
        bfr.close();
        prw.close();
    }
}

四.随机访问流
随机访问流(RandomAccessFile)其实并不属于流,它是Object类的一个子类,但他融合了InputStream和OutputStream的功能,所以他有一个很有意思的特点,能读能写,只需要在new的过程中通过参数来决定是否可以读和写;
随机访问流还有一个特点就是他可以设置文件指针,可以不用按顺序来读取文件,可以通过seek方法来读取指定位置的数据。

public class IODemo6 {
    public static void main(String[] args) throws IOException {
        RandomAccessFile raw = new RandomAccessFile("c.txt", "rw");
        raw.writeInt(3);
        long pointer = raw.getFilePointer();//获取文件指针
        System.out.println(pointer);//4
        raw.writeUTF("你好");
        long pointer1 = raw.getFilePointer();
        System.out.println(pointer1);//12
        raw.seek(4);
        String s = raw.readUTF();
        System.out.println(s);
        raw.close();
    }
}
4
12
你好

获取文件指针操作时会发现,在获取UTF的指针位置时,明明两个汉字只占了六个字节,前面的int类型占四个字节,加起来应该是十才对,为什么最后的指针位置是12,这里会多读两个字节 是因为writeUTF()会多些两个字节,而seek()方法会将指针转移,这样再次执行操作时,会在转移后的位置进行操作。
五.序列化流与反序列化流
序列化,指的就是将对象通过流的方式存储到文件中,相对的,反序列化就是将文件中存储的对象通过流的方式还原成对象,但这个对象必须要实现Serializable 接口才能被序列化,Serializable 接口只是一个标记接口,里面并没有什么内容。
序列化过程:

public class IODemo7 {
    public static void main(String[] args) throws IOException {
        Person person = new Person("张三",23);
        ObjectOutputStream objout = new ObjectOutputStream(new FileOutputStream("Person.txt"));
        objout.writeObject(person);
        objout.close();
    }
}

反序列化过程:

public class IODemo8 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        ObjectInputStream objin = new ObjectInputStream(new FileInputStream("Person.txt"));
        Person person = (Person) objin.readObject();
        System.out.println(person.getName()+"==="+person.getAge());
        objin.close();
    }
}

我们可以将某个对象通过序列化形式来保存起来,等到要用的时候再反序列化,这样就不用每次去重新创建这么麻烦。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值