JavaIO流

斜体样式## io流

数据在计算机中本质是二进制的字节流,所以在计算机中的操作都是以流的形式进行的。javaIO流,是一种计算机用语。主要是用于处理数据的传输。

io流图示:
在这里插入图片描述

1.字节流

1).OutputStream 字节输出流 (写入)

抽象类,无法直接使用,通过其子类FileOutputStream,向文件写入字节。

FileOutputStream 字节文件输出流

用于将数据写入到File,从程序中写入到其他位置。

public static void outputStreamMethod() throws IOException {
    //指定文件所在的位置及名称
    File file = new File("f:/io.txt");
    //参数二:true代表接着文件的末尾续写
    OutputStream os = new
    FileOutputStream(file,true);
    //写数字
    os.write(18);
    os.write(97);
    //写字符串
    os.write("haha".getBytes());
    //关于流的操作,一定要有关闭流的动作
    os.close();
}
2).InputStream 字节输入流(读取)

抽象类,无法直接使用,通过其子类FileInputStream,从文件中获取字节。

FileInputStream 字节文件输入流

从文件系统中的某个文件中获得输入字节,用于读取诸如图像数据之类的原始字节流。

public static void inputStreamMethod() throws IOException {
    //指定文件所在的位置及名称
    File file = new File("f:/io.txt");
    InputStream is = new FileInputStream(file);
    /*//每次读一个字节
		int result = is.read();
		System.out.println(result);*/
    //使用数组读取时虽提高了操作效率,但会出现覆盖问题
    byte[] bytes = new byte[4];
    //read()方法返回-1到达流的末尾表示数据读取完成
    while(is.read(bytes)!=-1) {
        System.out.println(new String(bytes));
    }
    //关于流的操作,一定要有关闭流的动作
    is.close();
}
总结:

字节流:
1.字节流在操作的时候不会用到缓冲区(也就是内存)

(没有关闭字节流操作,但是文件中也会依然存在了输出的内容,证明字节流是直接操作文件本身的)

2.字节流可用于任何类型的对象,包括二进制对象
3.字节流处理单元为1个字节,操作字节和字节数组。
InputStream是所有字节输入流的祖先,而OutputStream是所有字节输出流的祖先。

FileInputStream和FileOutputStream是操纵字节数据,当操纵字符数据时会有报错的可能,而且每次写入输出只是单个,所以并不能拿出来单独使用

2.字符流

字符流是由多个字节流组成,最小单位是b(字节)

1).Writer写入字符流的抽象类

抽象类,无法直接使用,通过其子类的子类FileWriter向文件写入字符。

FileWriter写入字符文件的方便类
public static void writerMethod() throws IOException {
    Writer writer = new FileWriter("f:/writer.txt",true);
    writer.write(98);
    writer.write("李二");
    writer.write("a");
    //使用字符流在进行书写时要求刷新或关闭流
    //writer.flush();
    writer.write("张三");
    //writer.flush();
    writer.close();
    //流关闭后不能再书写
    //writer.write("李四");
}

2).Reader读取字符流的抽象类

抽象类,无法直接使用,通过其子类的子类FileReader从文件中获取字符。

FileReader读取字符文件的方便类
public static void readerMethod() throws IOException {
    Reader reader = new FileReader("f:/writer.txt");
    //每次读一个字节
    /*int result = reader.read();
		System.out.println((char)result);*/
    //使用数组读取
    char[] cbuf = new char[1024];
    while(reader.read(cbuf)!=-1) {
        System.out.println(new String(cbuf));
    }
    //关于流的操作,一定要有关闭流的动作
    reader.close();
}
总结:

字符流:
1.字符流在操作的时候会用到缓冲区

(字符流不关闭执行后会发现文件中没有任何内容,这是因为字符流操作时使用了缓冲区,而 在关闭字符流时会强制性地将缓冲区中的内容进行输出,但是如果程序没有关闭,则缓冲区中的内容是无法输出的,所以得出结论:字符流使用了缓冲区,而字节流没有使用缓冲区。)

2.字符流只能处理字符或者字符串
3.字符流处理的单元为2个字节的Unicode字符,操作字符、字符数组或字符串,
Reader是所有读取字符串输入流的祖先,而writer是所有输出字符串的祖先

FileReader和FileWriter可以操纵字符数据,且文件的编码应该和Java所定的编码匹配,当遇到编码不符的情况,则会乱码。

3.流转换

字节流在读取的过程中效率高,针对某些问题(中文乱码,空间浪费等)不好处理,此时就需要将其转换字符流

字符流在读取的过程中效率低且有局限性(音频、视频等),此时就需要将其转换为字节流

针对上面的问题,我们使用了另外两种类,即InputStreamReader和OutputStreamWriter,这两种是Reader和Writer的子类,也是FIleReader和FileWriter 的父类。它们是字节到字符和字符到字节的桥梁,即可以将文件中的带有字符的字节数据顺利读入到Java中,将Java中的数据成功写入到文件中。在使用的过程中,我们需要指定编码,即文件和Java中指定的编码相匹配,这样编码相同了,字符也可以和字节互转了,我们可以成功的操纵数据了。

1).InputStreamReade是字节流通向字符流的桥梁
public static void main(String[] args) throws IOException {
 
        //字节流-->字符流
        //InputStream is = System.in;
        //将字节输入流转换为字符输入流
        //InputStreamReader isr = new InputStreamReader(is);
        //将输入流包装一下--用缓冲流读
        // BufferedReader br = new BufferedReader(isr);
    
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new FileWriter("f:/is2.txt"));
        String line = null;
        while((line = br.readLine())!=null){
            if("over".equals(line)){
                break;
            }
            bw.write(line);
            bw.newLine();
            bw.flush();         
        }
        bw.close();
        br.close();
    }
2).OutputStreamWriter是字符流通向字节流的桥梁
public static void main(String[] args) throws IOException {
 
        BufferedReader br = new BufferedReader(new FileReader("f:/is2.txt"));
        //字符流-->字节流 
        //OutputStream os = System.out
        //OutputStreamWrite osw= new OutputStreamWrite(os);
        //BufferedWriter bw = new BufferedWrite(osw);
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        String line = null;
        while ((line = br.readLine())!=null) {
            bw.write(line);
            bw.newLine();
            bw.flush();
        }
        bw.close();
        br.close();
    }

4.字符缓冲对象

可以简单地把缓冲区理解为一段特殊的内存。

某些情况下,如果一个程序频繁地操作一个资源(如文件或数据库),则性能会很低,此时为了提升性能,就可以将一部分数据暂时读入到内存的一块区域之中,以后直接从此区域中读取数据即可,因为读取内存速度会比较快,这样可以提升程序的性能。(高效率)

在字符流的操作中,所有的字符都是在内存中形成的,在输出前会将所有的内容暂时保存在内存之中,所以使用了缓冲区暂存数据。

如果想在不关闭时也可以将字符流的内容全部输出,则可以使用Writer类中的flush()方法完成。

1).BufferedWriter缓冲流对象写入

将文本写入到字符输出流中,缓冲字符,以便提供对单个字符、数组和字符串的有效写入。

public static void writerMethod() throws IOException {
    Writer writer = new FileWriter("f:/buf.txt");
    //创建缓冲流对象
    BufferedWriter bw = new BufferedWriter(writer);
    bw.write("生命在于运动1");
    //输出换行符时要写\r\n
    bw.write("\r\n");
    bw.write("生命在于运动2");
    //关闭流对象---倒着关
    bw.close();
    writer.close();
}
2).BufferedReader缓冲流对象读取

从一个字符输入流中读取文本,缓冲字符,以便提供字符、数组和行的有效读取。

public static void readerMethod() throws IOException {
    Reader reader = new FileReader("f:/buf.txt");
    //创建缓冲流对象
    BufferedReader br = new BufferedReader(reader);
    String str = null;
    while((str=br.readLine())!=null) {
        System.out.println(str);
    }
    //关闭流对象---倒着关
    br.close();
    reader.close();
}

5.字符串缓冲对象

StringBuffer字符串缓冲区对象

特点:线程安全的可变字符串。同步,效率低

StringBuffer类和String一样,也用来代表字符串,只是由于StringBuffer的内部实现方式和String不同,所以StringBuffer在进行字符串处理时,不生成新的对象,在内存使用上要优于String类。
所以在实际使用时,如果经常需要对一个字符串进行修改,例如插入、删除等操作,使用StringBuffer要更加适合一些。
在StringBuffer类中存在很多和String类一样的方法,这些方法在功能上和String类中的功能是完全一样的。
但是有一个最显著的区别在于,对于StringBuffer对象的每次修改都会改变对象自身,这点是和String类最大的区别。

另外由于StringBuffer是线程安全的,所以在多线程程序中也可以很方便的进行使用,但是程序的执行效率相对来说就要稍微慢一些。

public static void readerMethod3() throws IOException {
    Reader reader = new FileReader("f:/buf.txt");
    char[] cbuf = new char[1024];
    //定义一个字符串缓冲对象用于接收字符串
    StringBuilder sb = new StringBuilder();
    while(reader.read(cbuf)!=-1) {
        //添加到字符串缓冲区里面,并返回字符串缓冲区本身
        sb.append(cbuf);
    }
    System.out.println(sb.toString());
    //关闭流对象
    reader.close();
}

6.流写对象

通过流的形式将自定义对象写到指定的文件中,该形式称为持久化存储(数据本地存储)

/**
	 * 写对象
	 * @throws IOException
	 */
public static void writeObject() throws IOException {
    User user = new User(12,"哈哈");
    //获取对象的输出流--写对象
    OutputStream os = new FileOutputStream("f:/object.txt");
    ObjectOutputStream oos = new ObjectOutputStream(os); 
    oos.writeObject(user);

    //关闭流对象
    oos.close();
    os.close();
}

运行后出现错误:实例对象未序列化异常

序列化:其实就是为要写的对象一个标识符,在java中对应将对象转成流的形式写入到指定文件中

反序列化:根据标识符再进行匹配,通过指定文件以流的形式读取到的结果再包装成对象

使用方式:只需要实体类实现一个名叫Serializable接口即可

public class User implements Serializable{

    /**
	 * 
	 */
    private static final long serialVersionUID = 1L;

    private int age;

    private String name;

    private static int count;

    //transient修饰的变量称为瞬态变量
    private transient int num;

    private String address;

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

    public void show() {}

    @Override
    public String toString() {
        return "User [age=" + age + ", name=" + name + ", address=" + address + "]";
    }
}

反序列化:读取过程中

/**
	 * 读取对象
	 * @throws IOException
	 * @throws ClassNotFoundException 
	 */
public static void readerObject() throws IOException, ClassNotFoundException {
    InputStream is = new FileInputStream("f:/object.txt");
    ObjectInputStream ois = new ObjectInputStream(is);
    //读对象
    Object obj = ois.readObject();
    //强制类型转换
    User user = (User)obj;
    System.out.println(user);

    //关闭流
    ois.close();
    is.close();
}

如果实体类中未指定seriaVersionId,那么在持久化存储后,一旦实体类做了修改,那么反序列化时就会报错

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值