javaIO流

一、IO流的分类

  • 按照数据流向,可分为输入流和输出流,输入流读取数据,输出流写入数据。
  • 按照读取的数据类型,可分为字节型流和字符型流,字节流操作的最小数据单元是8位的字节,字符流操作的最小数据单元是16位的字符。
  • 按照处理功能,可分为节点流和处理流,节点流直接从IO设备或文件等读取或写入数据,也称为低级流,处理流是对节点流的封装,使用装饰者模式,提供了更为丰富便捷的读取方法,不直接操作IO设备及文件等,提高io读写的效率。

二、java IO流类

IO流抽象基类:
字节流基类:InputStream ,OutputStream
字符流基类:Reader,Writer
字节节点输入流:FileInputStream、ByteArrayInputStream、PipedInputStream
字节节点输出流:FileOutPutStream、ByteArrayInputStream、PipedInputStream
字节处理输入流:BufferedInputStream、ObjectInputStream、DataInputStream
字节处理输出流:BufferedOutPutStream、ObjectOutPutStream、DataInputSteam
字符节点输入流:FileReader、CharArrayReader、PipedReader
字符节点输出流:FileWriter、CharArrayWriter、PipedWriter
字符处理输入流:BufferedReader、InputStreamReader
字符处理输出流:BufferedWriter、OutputStreamWriter

节点流一般对文件、数组、管道等进行操作
处理流包括:缓冲流、转换流、对象流等

缓冲流的作用:程序与磁盘交互很慢,节点流每次读写一个数据单元交互一次,效率较低。缓冲流提供一定容量的缓存,将读写的数据存入缓存,当缓存满时再与磁盘交互,增加了每次交互的数据量,减少交互的次数,提高了读写的效率。
转换流的作用:将字节流转换成字符流
对象流的作用(ObjectInputStream/ObjectOutputStream):实现对象的序列化与反序列化

DataInputStream/DataOutputStream:读取/写入基本类型和字符串

1.IO流基本方法

字节流InputStream方法:
int code = read(); 读取一个字节,返回字节的code码
int count = read(byte[] bytes); 读取若干个字节存入数组中,返回有效字节个数
read(byte[] b, int off, int len);读取最多 len 个字节,存储到 b 中,从偏移量 off 开始的位置。返回值是实际读取的字节数,如果已到达流的末尾,则返回 -1
close() 关闭流

字节流OutputStream方法:
write(int code ); 将code对应的字符写入文件
write(byte[] bytes); 将数组中的全部字节写入文件
write(byte[] b, int off, int len);将指定数组中从偏移量 off 开始的 len 个字节写入此文件输出流。
flush();刷新流缓冲
close();关闭流

字符流Reader方法:
read() 返回字符code
read(char[] ch) 读取若干存入数组,返回有效字符个数
read(char[] ch, int off, int len) : 将字符读入数组的某一部分。
close()关闭流

字符流Writer方法:
write(int code ); 将code对应的字符写入文件
write(char[] bytes); 将数组中的全部字节写入文件
write(char[] b, int off, int len);将指定数组中从偏移量 off 开始的 len 个字符写入此文件输出流。
flush();刷新流缓冲
close();关闭流

字符缓冲流特有的两个方法:
BufferedWriter类:newLine();写入一个行分隔符。这个方法会自动适配所在系统的行分隔符。
BufferedReader类: readLine();读取一个文本行。

2.对象的序列化与反序列化

对象的序列化(Serialization)是指将对象转换为字节流的过程,以便于存储到文件或通过网络传输。
反序列化(Deserialization)则是将字节流转换回对象的过程。
1.对象实现serializable接口
2.使用ObjectOutputStream 和 ObjectInputStream 类来实现对象的序列化和反序列化

Person类:

import java.io.Serializable;

public class Person implements Serializable {

    private long serialVersionUID = -440948515215806089L;
    private String name;
    private int age;

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

    public String toString(){
        return "{"+this.name+","+this.age+"}";
    }
    public String getName(){
        return this.name;
    }
    public int getAge(){
        return this.age;
    }
    public void eat(){
        System.out.println(this.name+"的吃饭方法");
    }
}

序列化并存储到test.txt文件

    public static void main(String[] args){
        try {
            //将对象直接记录在文件中
            //对象的序列化
            Person p1 = new Person("zhangsan",18);
            //对象输出流
            FileOutputStream fos = new FileOutputStream("test.txt");
            ObjectOutputStream oos = new ObjectOutputStream(fos);//高级流
            oos.writeObject(p1);//将对象拆分成字节碎片  序列化到文件里
            oos.flush();
            oos.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

执行结果
在这里插入图片描述
对象反序列化

    public static void main(String[] args){
        //需要一个对象输入流
        try {
            ObjectInputStream ois = new ObjectInputStream(new FileInputStream("test.txt"));
            Person p = (Person)ois.readObject();
            System.out.println(p);
            p.eat();//EOFException说明没有对象  通常会将所有记录的对象存在一个集合
            ois.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

执行结果:
在这里插入图片描述


3.文件流应用

文件流构造方法

FileInputStream(File file );
FileInputStream(String fileName);
FileReader(File file);
FileReader(String name);

FileOutPutStream(File file);
FileOutputStream(String fileName);
FileWriter(File file);
FileWriter(String fileName);
此外上述构造方法均有带两个参数的重载,第二个参数为booleanl类型,表示是否追加,不追加则写时覆盖原文件内容

需求简单介绍:
小系统目前已实现登录注册修改用户信息留言等功能,但是数据并未持久化存储,总是需要先进行注册才能进行登录。
改进:
可将用户信息存入文件中,系统初始化时读取文件中的用户信息,注册时将用户信息写入文件,修改用户信息时需要同步修改文件中某一行的信息

用户信息存储在userdata/userdata.properties中
UserService 类中有一个Map类型的属性userMap,存储用户名和用户的映射
创建UserService时需要读取userdata.properties文件,按照一定的规则进行解析,并将解析后的数据存储至userMap中
注册时需要向userMap中添加新用户并将新用户写入文件
修改用户信息时需要修改userMap中的对象并修改文件中对应的某一行

文件内容
在这里插入图片描述

系统初始化读取用户信息

    public  void init(){
        FileReader reader = null ;
        BufferedReader bfReader = null;
        //使用流读取文件
        try {
            reader = new FileReader("userdata\\userdata.properties");
            bfReader = new BufferedReader(reader);
            String str ;
            while((str = bfReader.readLine())!=null){
                String[] kv = str.split("=");
                System.out.println("kv.length="+kv.length+"kv[0]="+kv[0]);
                String[] userValue =kv[1].split("\\+");
                User user = new User(userValue[0],userValue[1],userValue[2],userValue[3]);
                //消息列表
                if(userValue.length > 4){
                    String msgList = userValue[4];
                    String [] msgs = msgList.split(",");
                    ArrayList<String> list = new ArrayList<>();
                    for(String s:msgs){
                        list.add(s);
                    }
                    user.setMsgList(list);
                }
                userMap.put(kv[0],user);
                System.out.println(userMap);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally{
            if(reader !=null){

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

        }
    }

注意点:
读取每一行时尽量写成下面的形式,避免多次调用readLine()方法导致读取时部分数据丢失

String line;
while((line = bfReader.readLine())!=null){}

用户进行注册时,将用户信息按照自已定义的规则写入文件中

    //注册方法
    public String regist(String name , String psw , String repsw ,String tele ,String email ){
        String ret =null;

        if(name.length()<3 || name.length() > 8){
            ret = "账号长度应在3-8之间";
        }else if(userMap.containsKey(name)){
            ret ="该账户已被注册";
        }else if(psw == null ){
            ret = "密码不能为空";
        } else if( !psw.equals(repsw)){
            ret ="两次密码输入不一致";
        }else {
            User user = new User(name,psw,email,tele);
            write("userdata.properties",user);
            userMap.put(name,user);
            ret = "注册成功";
        }
        return ret;
    }
	//向文件写入新用户方法
    public void write(String filename ,User user){
        FileWriter f = null ;
        BufferedWriter writer = null;
        try {
            f = new FileWriter("userdata\\"+filename,true);
            writer = new BufferedWriter(f);
            String str = userToString(user);
            writer.write(str);
            writer.newLine();
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            if(f !=null){
                try {
                    f.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

注意点:
在写入新用户时需要保留原来所有的用户信息,因此在创建FileWriter时指定了是否追加,为true表示追加

更新用户信息时修改文件某一行数据

文件的修改本质上就是将数据重新读出,修改后再写回文件

    public void update(String name ,User newUser){
    	//将user对象转换成文件中存储的格式文本
        String replaceTxt =userToString(newUser);
        FileReader reader = null ;
        BufferedReader bufferedReader = null;
        FileWriter writer = null ;
        BufferedWriter bufferedWriter = null;
        try {
			//读取文件暂时存储到list中,遇到目标用户替换文本行
            reader = new FileReader("userdata\\userdata.properties");
            bufferedReader = new BufferedReader(reader);

            List<String> list = new ArrayList<>();
            String line;
            while((line = bufferedReader.readLine())!=null){
//                System.out.println("line ="+line);
                if(line.split("=")[0].equals(name)){
                    list.add(replaceTxt);
                }else{
                    list.add(line);
                }
            }
//            System.out.println("list="+list);
			//输出流将list中的文本行写回文件
            writer = new FileWriter("userdata\\userdata.properties");
            bufferedWriter = new BufferedWriter(writer);
            for(String s : list){
                bufferedWriter.write(s);
                bufferedWriter.newLine();
            }


        } catch (Exception e) {
            e.printStackTrace();
        }finally{
        	//finally中关闭输入和输出流
            if(reader != null){
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(bufferedReader != null){
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(bufferedWriter != null){
                try {
                    bufferedWriter.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(writer != null){
                try {
                    writer.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值