• 黑马程序员


    用于操作字节数组的流对象
    ByteArrayInputStream:在构造的时候需要接收数据源,而且数据源是一个字节数组。
    ByteArrayOutputStream: 在构造时,不用定义数据目的地,
    因为该对象中已经封装流一个可变长度的字节数组,该数组就为数据目的地。
    因为这两个流对象都操作的数组,并没有使用系统资源,所以不用进行close关闭,
    而且其不会产生IO异常。
    这种方法是用流的思想操作数组。
    注意:用于操作字符数组和操作字符串的流对象,基本与ByteArrayStream相同,详见说明书。

    import java.io.*;
    class EByteArrayDemo{
        public static void main(String[] args){
            ByteArrayInputStream bis = //数据源
                new ByteArrayInputStream("ABCDEFD".getBytes());
            ByteArrayOutputStream bos = //数据目的地
                new ByteArrayOutputStream ();
            int by = 0 ;
            while ((by=bis.read())!=-1){//将源数据长度赋予by,并判断是执行到文件末尾
                bos.write(by);            //将输入流中的字节数组存入输出流中的字节数组
            }
            System.out.println(bos.size());       //打印输出流的长度
            System.out.println(bos.toString());      //打印输出流的字符串形式
        }
    }

    //DataStream可以用于操作基本数据类型的流对象。
    //局限性,使用时必须按照文件的类型,依次取出。

    import java.io.*;
    class EDataStreamDemo
    {
        public static void main(String[] args) throws IOException
        {
            writeData();
            readData();
        }
        public static void readData() throws IOException
        {
            DataInputStream dis =
                new DataInputStream (new FileInputStream("d:\demodata.txt"));
            //该方法必须按存入的顺序取出。
            int num = dis.readInt();        //读取整数
            boolean b = dis.readBoolean();    //读取Boolean类型数据
            double d = dis.readDouble();    //读取Double类型数据
            String utf = dis.readUTF();        //读取UTF编码数据
            System.out.println("num="+num);
            System.out.println("b="+b);
            System.out.println("d="+d);
            System.out.println("UTF="+utf);
            dis.close();
        }
        public static void writeData() throws IOException
        {
            DataOutputStream dos =
                new DataOutputStream(new FileOutputStream("d:\demodata.txt"));
            dos.writeInt(234);
            dos.writeBoolean(true);
            dos.writeDouble(4323.355);
            dos.writeUTF("你好");
            dos.close();
        }
    }

    管道流
    PipedInputStream PipedOutputStream
    输入输出可以直接进行连接,通过结合线程使用。
    思路:
    1.创建Read类,覆写run方法,在run方法中实现文件读取并存储到s字符串中并打印出来。
    2.创建Write类,覆写run方法,在run方法中实现文件的写入
    3.分别创建输入和输出线程然后开启。

    import java.io.*;
    class EPipedStreamDemo{
        public static void main(String[] args) throws IOException{
            PipedInputStream in = new PipedInputStream();    //定义输入流
            PipedOutputStream out = new PipedOutputStream();//定义输出流
            in.connect(out);                //将输出流与输入流连接
            Read r = new Read(in);            //建立输入流的Read对象    
            Write w = new Write (out);        //建立输出流的Write对象
            (new Thread(r)).start();        //分别建立输入流和输出流的线程并开启
            (new Thread(w)).start();
        }
    }
    class Read implements Runnable{            //定义Read类实现Runnable接口
        private PipedInputStream in;        
        Read(PipedInputStream in){            //将输入流传入
            this.in = in;
        }
        public void run(){                            //在run方法中覆写读取操作
            try{
                byte [] byt = new byte[1024];        //定义字节数组
                int len = in.read(byt);                //将读取的内容写入字节数组
                String s = new String(byt ,0 ,len);    //将字节数组转为字符串    
                System.out.println(s);                //打印读取的数据
                in.close();
            }
            catch (IOException e){                    //定义IO异常的处理方法
                throw new RuntimeException("管道读取流运行失败");
            }
        }
    }
    class Write implements Runnable{        //定义Write实现Runnable接口
        private PipedOutputStream out;                
        Write(PipedOutputStream out){        //将输出流传入
            this.out = out ;
        }
        public void run(){                    //在run方法中覆写写入操作
            try{
                out.write("piped lai la".getBytes());//写入字符串的字节数据
                out.close();
            }
            catch (IOException e){            //定义IO异常处理方法
                throw new RuntimeException("管道输出流运行失败");
            }
        }
    }

    操作对象的流
    ObjectInputStrea ObjectOutputStream

    需求:
    实现操作对象流对对象的永久存储和数据读取。
    思路:
    1.定义Person类封装属性
    2.定义对象输出流与目标文件关联,并向其写入Person对象数据
    3.定义对象输入流与目标文件关联,并读取其中存储的Person对象数据

    import java.io.*;
    class Person implements Serializable{ //注意实现接口
        private String name;                //定义成员变量
        private int age;
        Person (String name ,int age){        //定义构造函数
            this.name = name;
            this.age = age;
        }
        public String toString(){            //覆写toString方法
            return name+":"+age;
        }
    }
    class  EObjectStreamDemo{
        public static void main(String[] args) throws Exception{
            writeObj();                        //调用写入对象方法
            readObj();                        //调用读取对象方法
        }
        public static void readObj() throws Exception{    //定义读取对象方法
            ObjectInputStream ois =                        //将对象输出流与文件相关联
                new ObjectInputStream(new FileInputStream("d:\person.txt"));
            Person p =(Person)ois.readObject();    //依次读取文件中的对象数据,注意强转为Person对象
            System.out.println(p);                //在控制台上打印对象
            ois.close();
        }
        public static void writeObj() throws Exception{    //定义写入对象方法
            ObjectOutputStream oos =                    //将输出流与文件相关联
                new ObjectOutputStream(new FileOutputStream("d:\person.txt"));
            oos.writeObject(new Person("lili",39));        //输出新对象
            oos.close();
        }
    }

    RandomAccessFile:随机读取流
    该类不算是IO体系的子类,而是直接继承自Object
    但是他是IO包中的成员,因为他具备读写功能。
    可以通过getFilePointer获取指针位置。
    同时可以seek改变指针的位置
    其完成读写的原理就是在内部封装流字节输入流和输出流。
    通过构造函数可以看出,本类只能操作文件,及固定模式
    模式: r 只读 :不会创建文件,只会读取已存在文件,如果文件不存在就会报异常。
    rw 读写:该对象的构造函数要操作的文件不存在,会自动创建;如果存在不会覆盖。

    import java.io.*;
    class ERandomDemo{
        public static void main(String[] args) throws IOException{
            //writeR();
            writeRR();
            readR();
        }
        public static void readR() throws IOException{
            //关联文件和随机读取流,模式处写"r",表示只读
            RandomAccessFile raf = new RandomAccessFile("d:\demoRandom.txt","r");
            byte[] byt = new byte[4];//设置的姓名4个字节,年龄4个字节,所以设置4个字节的数组
            //调整指针位置,只能往后移动
            raf.seek(8);
            //跳过指定的字节数
            //raf.skipByte(int n);
            raf.read(byt);            //将数据写入字节数组
            String name = new String(byt);
            int age = raf.readInt();//读取整数操作
            System.out.println("name:"+name);
            System.out.println("age:"+age);
            raf.close();
        }
        //重点掌握,该方法通过同时多线程分别输入不同位段,实现多线程输入(类似迅雷等下载软件的方法)
        //仅该方法可以实现多线程多端输入。
        public static void writeRR() throws IOException{
            RandomAccessFile raf = new RandomAccessFile("d:\demoRandom.txt","rw");
            raf.seek(8*2);
            raf.write("周期".getBytes());
            raf.writeInt(33);
            raf.close();
        }
        public static void writeR() throws IOException{
            RandomAccessFile raf = new RandomAccessFile("d:\demoRandom.txt","rw");
            raf.write("mik1".getBytes());
            //注意,使用writeInt(),而不用write()
            //因为write()写入时只会使用1个字节,数字过大时会出现数据丢失
            //writeInt()写入时占用4个字节。注意:1个中文2个字节
            raf.writeInt(31);
            raf.write("mik2".getBytes());
            raf.writeInt(32);
            raf.write("mik3".getBytes());
            raf.writeInt(33);
            raf.close();
        }
    }

    转换流的编码表
    编码:字符串变成字节数组
    String-->byte[]: str.getBytes(charsetName)
    解码:字节数组变成子符数组
    byte[]-->String: new String(byte[],charsetName)
    注意:1.GBK码的中文用utf-8解码后源码会变。因为他们都识别中文且中文码不同,
    一种识别中文的码表转成不识别中文的码表就不会出现这种能情况。
    2.GBK码的"联通"字符符合utf-8的编码形式。

    import java.io.*;
    import java.util.*;
    class  FTransDemo{
        public static void main(String[] args) throws IOException{
            writeTran();
            readTran();
        }
        public static void writeTran() throws IOException{
            BufferedWriter  bfws =         //定义转换输出流与文件关联
                new BufferedWriter(new OutputStreamWriter(new FileOutputStream("d:\demotrans.txt"),"GBK"));
            bfws.write("你好");             //写入"你好"
            bfws.close();
        }
        public static void readTran() throws IOException{
            BufferedReader  bfrs =        //定义转换输入流与文件关联
                new BufferedReader(new InputStreamReader(new FileInputStream("d:\demotrans.txt")/*,"utf-8"*/));
            char [] byt = new char [1024];//定义字符数组
            int len =0;
            while((len=bfrs.read(byt))!=-1){//将缓冲区内的数据写入字符数组,并判断是否已到文件末尾
                String s1 = new String(byt,0,len);//将字符数组转换为字符串
                //打印按照指定码表的编码
                System.out.println(Arrays.toString(s1.getBytes("GBK")));
                System.out.println(Arrays.toString(s1.getBytes("utf-8")));
                System.out.println(s1);
            }
            bfrs.close();
        }
    }

    IO流应用实例

    需求:有5个学生,每个学生有3门课的成绩
    从键盘中输入以上数据(包括姓名,3门课的成绩)
    输入格式如:张三,30,40,60,计算出总成绩
    并把学生信息和计算出的总分高低顺序存放在磁盘文件中"stud.txt"中
    1.描述学生对象
    2.定义一个可操作的学生对象工具类。
    思想:
    1.通过键盘获取一行数据,并将该行中的信息取出封装成学生对象。
    2.因为学生有很多,那么久需要存储,使用到集合,因为要对学生的总分排序
    所以用TreeSet存储。
    3.将集合的信息写入到一个文件中。

    import java.io.*;
    import java.util.*;
    public class StudentSort {
    
        public static void main(String[] args) throws NumberFormatException, IOException {
            // TODO Auto-generated method stub
            TreeSet<Student> stuSet = (TreeSet<Student>) StudentInfo.getStudent();
            for (Student s : stuSet){
                System.out.println(s+","+s.getSum());
            }
        }
    }
    class Student implements Comparable<Student>{
        private String name;                //定义学生的属性
        private int  math,cn,en;            
        private int sum;
        Student (String name, int math,int cn,int en){//定义构造函数
            this.name = name;
            this.math = math;
            this.cn = cn;
            this.en = en;
            sum = math + cn + en;
        }
        public int compareTo(Student s){        //覆写排序方法,为先判断总分,再判断名字
            int num = new Integer(s.sum).compareTo(new Integer(this.sum));
            if(num==0)
                return s.name.compareTo(this.name);
            return num;        
        }
        public int hashCode(){                    //覆写hashcode获取方式
            return name.hashCode()+sum*78;
        }
        public boolean equals (Object obj){    //覆写比较方法,定义姓名总分均相同的对象为同一对象
            if(!(obj instanceof Student))    //判断比较对象是否为学生类型
                throw new ClassCastException("类型不匹配");
            Student s = (Student) obj;        //将比较对象向下转型为Student
            return this.name.equals(s.name) && this.sum==s.sum;
        }
        public String toString(){            //覆写头String方法
            return "student  "+name+":"+math+","+cn+","+en;
        }
        public String getName(){
            return name;
        }
        public int getSum(){
            return sum;
        }
    }
    class StudentInfo{
        public static Set<Student> getStudent() throws NumberFormatException, IOException{
            BufferedReader bufr =    //将输入流与键盘关联
                new BufferedReader(new InputStreamReader(System.in));
            String line = null;
            TreeSet stuSet = new TreeSet();
            while((line=bufr.readLine())!=null){
                if("over".equals(line)) //定义结束标识
                    break;
                String[] info = line.split(",");     //将输入的数据变为字符串数组
                Student stu = new Student(info[0],    //按字符串数组数据新建学生对象
                    Integer.parseInt(info[1]),Integer.parseInt(info[2]),Integer.parseInt(info[3]));
                stuSet.add(stu);
            }
            return stuSet;    //返回学生的集合
        }
    }

    在控制台上输入

    输出结果

  • 相关阅读:
    gradle使用笔记
    MaxScale初探
    mariadb-10GTID复制及多源复制
    Shell中的循环语句实例
    Failed to load slave replication state from table mysql.gtid_slave_pos: 1146: Table 'mysql.gtid_slave_pos' doesn't exist
    学习MongoDB--(5-2):索引(查看索引的使用,管理索引)
    MongoDB索引管理
    mysql 5.5与5.6 timestamp 字段 DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP的区别
    MongoDB增加用户、删除用户、修改用户读写权限及只读权限(注:转载于http://www.2cto.com/database/201203/125025.html)
    MongoDB创建数据库
  • 原文地址:https://www.cnblogs.com/myblog-cl/p/4746655.html
Copyright © 2020-2023  润新知