黑马程序员——Java基础——IO输入与输出_3

来源:互联网 发布:黑暗骑士 知乎 编辑:程序博客网 时间:2024/03/29 10:00

IO流

作用:
利用Java语言中的IO流技术处理设备上的数据(硬盘上的文件,内存中驻留的数据)
分类:
按流向
- - - - 输入流
- - - - 输出流
按数据
- - - - 字节流
- - - - 字符流
抽象基类:
字符流
- - - - Reader
- - - - Writer
字节流
- - - - InputStream
- - - - OutputStream

功能性流对象

打印流

该流提供了打印方法,可以将各种数据类型的数据原样打印
字节打印流 PrintStream:
构造函数可以接收
- - - - File对象 File
- - - - 字符串路径 String
- - - - 字节输出流 OutputStream
字符打印流 PrintWriter:
构造函数可以接收
- - - - File对象 File
- - - - 字符串路径 String
- - - - 字节输出流 OutputStream
- - - - 字符输出流 Writer

public class PrintStreamDemo {    public static void main(String[] args) throws IOException{        BufferedReader bufr =                 new BufferedReader(                        new InputStreamReader(                                System.in));        //基础形式        //PrintWriter out = new PrintWriter(System.out);        //true参数表示如果是流,在输入回车后自动flush        PrintWriter out = new PrintWriter(System.out, true);        //输出到文件中,但是没有true参数,true参数配合流使用        //PrintWriter out = new PrintWriter("a.txt");        //将文件封装到流中,就可以配合true参数使用        //true参数只针对于流使用,PrintWriter(“a.txt”, true)非法        //PrintWriter out = new PrintWriter(new FileWriter("a.txt"), true);        String line = null;        while((line = bufr.readLine()) != null){            if("over".equals(line))                break;            out.println(line.toUpperCase());        }        out.close();        bufr.close();    }}

序列流

将多个流合并成一个流 SequenceInputStream

public class SequenceInputStreamDemo {    public static void main(String[] args) throws IOException{        Vector<FileInputStream> v = new Vector<FileInputStream>();        v.add(new FileInputStream("d:\\test\\1.txt"));        v.add(new FileInputStream("d:\\test\\2.txt"));        v.add(new FileInputStream("d:\\test\\3.txt"));        Enumeration<FileInputStream> en = v.elements();        SequenceInputStream sis = new SequenceInputStream(en);        FileOutputStream fos = new FileOutputStream("d:\\test\\4.txt");        byte[] buf = new byte[1024];        int len = 0;        while((len = sis.read(buf)) != -1){            fos.write(buf, 0, len);        }        fos.close();        sis.close();    }}

文件切割

public class SplitFile {    public static void main(String[] args) throws IOException{        splitFile();        merge();    }    public static void merge() throws IOException{        ArrayList<FileInputStream> al = new ArrayList<FileInputStream>();        al.add(new FileInputStream("d:\\test\\1.part"));        al.add(new FileInputStream("d:\\test\\2.part"));        al.add(new FileInputStream("d:\\test\\3.part"));        al.add(new FileInputStream("d:\\test\\4.part"));        final Iterator<FileInputStream> it = al.iterator();        Enumeration<FileInputStream> en = new Enumeration<FileInputStream>(){            public boolean hasMoreElements(){                return it.hasNext();            }            public FileInputStream nextElement(){                return it.next();            }        };         SequenceInputStream sis = new SequenceInputStream(en);        FileOutputStream fos = new FileOutputStream("d:\\test\\splitFile.mp3");        byte[] buf = new byte[1024 * 1024];        int len = 0;        while((len = sis.read(buf)) != -1){            fos.write(buf, 0, len);        }        fos.close();        sis.close();    }    public static void splitFile() throws IOException{        FileInputStream fis = new FileInputStream("d:\\test\\sq.mp3");        FileOutputStream fos = null;        byte[] buf = new byte[1024*1024];        int len = 0;        int count = 1;        while((len = fis.read(buf)) != -1){            fos = new FileOutputStream("d:\\test\\" + (count++) + ".part");            fos.write(buf, 0, len);            fos.close();        }        fis.close();    }}

对象的序列化

直接操作对象的流,将堆内存中的对象通过此类存入硬盘中(对象的持久化)
被操作对象需要实现Serializable接口(标记接口)
ObjectInputStream
ObjectOutputStream
当被序列化类被修改时,Java自动生成的UID改变,以序列化的该类对象是无法使用该类的,需自定义静态值serialVersionUID
静态变量是不能被序列化的
如果非静态的变量也不想被序列化则定义transient关键字

public class Person implements Serializable{    //自定义UID值,在类被修改时保证在未被修改之前生成类的对象也能够使用该类    private static final long serialVersionUID = 100L;    private int id;    private String name;    //添加transient关键字,使非静态的参数不被序列化    transient int age;    //静态变量不会被序列化    static String country = "cn";    Person(int id, String name, int age, String country){        this.id = id;        this.name = name;        this.age = age;        this.country = country;    }    public String toString(){        return id + "::" + name + "::" + age + "::" + country;    }}public class TestObjectStream {    public static void main(String[] args) throws Exception{        writeObj();        readObj();    }    public static void readObj() throws Exception{        ObjectInputStream ois =                 new ObjectInputStream(                        new FileInputStream("d:\\test\\Person.object"));        Person p = (Person)ois.readObject();        System.out.println(p);        ois.close();    }    public static void writeObj()throws IOException{        ObjectOutputStream oos =                new ObjectOutputStream(                        new FileOutputStream("d:\\test\\Person.object"));        oos.writeObject(new Person(001, "zhangsan", 27, "US"));        oos.close();    }}

**输出结果为:**1::zhangsan::0::cn

管道流

输入输出可以直接进行连接,通过结合线程使用
PipedInputStream
PipedOutputStream

public class PipedStreamDemo {    public static void main(String[] args) throws IOException{        PipedInputStream in = new PipedInputStream();        PipedOutputStream out = new PipedOutputStream();        in.connect(out);        Read r = new Read(in);        Write w = new Write(out);        new Thread(r).start();        new Thread(w).start();    }}class Read implements Runnable{    private PipedInputStream in;    Read(PipedInputStream in){        this.in = in;    }    public void run() {        try{            byte[] buf = new byte[1024];            int len = in.read(buf);            String s = new String(buf, 0, len);            System.out.println(s);            in.close();        }catch(IOException e){            throw new RuntimeException("管道输入流失败");        }    }}class Write implements Runnable{    private PipedOutputStream out;    Write(PipedOutputStream out){        this.out = out;    }    public void run() {        try{            out.write("PipedStream is coming~".getBytes());            out.close();        }catch(Exception e){            throw new RuntimeException("管道输出流失败~");        }    }}

RandomAccessFile

该类配合多线程可以实现数据的分段写入
该类不算IO体系中的子类,直接继承Object类
但是是IO包中的成员,可以通过指针对数据的元素进行操作,可以通过getFilePointer获取指针位置,同时可以通过seek改变指针的位置,完成读写的原理就是内部封装了字节数入流和输出流
该类只能操作文件,且该操作文件还有模式:只读“r”、读写“rw”等

public class RandomAccessFileDemo {    public static void main(String[] args) throws IOException{        writeFile();        writeFile2();        readFile();    }    public static void readFile() throws IOException{        RandomAccessFile raf = new RandomAccessFile("d:\\test\\4.txt", "r");        //指针索引指向第八位        raf.seek(8);        //指针索引向右移动八位        raf.skipBytes(8);        byte[] buf = new byte[4];        raf.read(buf);        String s = new String(buf);        int age = raf.readInt();        System.out.println("name:" + s);        System.out.println("age:" + age);        raf.close();    }    public static void writeFile2() throws IOException{        RandomAccessFile raf = new RandomAccessFile("d:\\test\\4.txt", "rw");        //指针索引向右移动八位三次        raf.seek(8*3);        //此时指针在第四个八位,写入数据        raf.write("周七".getBytes());        raf.writeInt(103);        raf.close();    }    public static void writeFile() throws IOException{        RandomAccessFile raf = new RandomAccessFile("d:\\test\\4.txt", "rw");        raf.write("张三".getBytes());        //写入一个数值用四个字节保存        raf.writeInt(97);    }}

操作基本数据类型的流对象DataStream

DataInputStream
DataOutputStream

public class DataStreamDemo {    public static void main(String[] args) throws IOException{        writeData();        readData();        writeUTF();        //自定义编码类型写入数据        OutputStreamWriter ows =                 new OutputStreamWriter(                        new FileOutputStream("d:\\test\\utf.txt"), "utf-8");        ows.write("你好");        ows.close();        readUTF();    }    public static void readUTF() throws IOException{        DataInputStream dis =                 new DataInputStream(                        new FileInputStream("d:\\test\\utfData.txt"));        String str = dis.readUTF();        System.out.println(str);    }    public static void writeUTF() throws IOException{        DataOutputStream dos =                new DataOutputStream(                        new FileOutputStream("d:\\test\\utfData.txt"));        dos.writeUTF("你好");        dos.close();    }    public static void readData() throws IOException{        DataInputStream dis =                 new DataInputStream(                        new FileInputStream("d:\\test\\data.txt"));        int i = dis.readInt();        boolean b = dis.readBoolean();        double d = dis.readDouble();        System.out.println(i + "::" + b + "::" + d);        dis.close();    }    public static void writeData() throws IOException{        DataOutputStream dos =                 new DataOutputStream(                        new FileOutputStream("d:\\test\\data.txt"));        dos.writeInt(123);        dos.writeBoolean(true);        dos.writeDouble(241.231);        dos.close();    }}

用于操作字节数组的流对象ByteArrayStream

在构造的时候需要接收一个数据源,且数据源是一个字节数组
ByteArrayOutputStream在构造的时候,不用定义数据目的,因为该对象中已经内部封装了可变长度的字节数组
这两个流对象都操作的数组,并没有使用系统资源,所以不用进行close关闭

public class TestByteArrayDemo{    public static void main(String[] args) throws IOException{        ByteArrayInputStream bis =                 new ByteArrayInputStream("abcdefg".getBytes());        ByteArrayOutputStream bos = new ByteArrayOutputStream();        int ch = 0;        while((ch = bis.read()) != -1){            bos.write(ch);        }        System.out.println(bos.size());        System.out.println(bos.toString());        //只有writeTO方法需要抛出异常        bos.writeTo(new FileOutputStream("d:\\test\\byteArrayDemo.txt"));    }}

转换流的字符编码、字符编码、字符编码-联通

编码:字符串转换成字节数组
解码:字节数组转换成字符串

public class TransCharactorTest {    public static void main(String[] args) throws IOException{        String s = "你好";        //用GBK进行编码        byte[] b1 = s.getBytes("GBK");        //数组转换成字符串        //System.out.println(Arrays.toString(b1));        String s1 = new String(b1, "ISO8859-1");        //用错误的解码格式进行编码,再用正确的格式进行解码        String s2 = new String(s1.getBytes("iso8859-1"), "GBK");         System.out.println("s2::" + s2);    }}

练习

需求
有五个学生,每个学生有三门课程
从键盘输入以上数据(姓名,课程1, 2, 3)
计算出中成绩并把学生的信息和计算出的分数有高到低存放在文件“stud.txt”中

public class Test {    public static void main(String[] args) throws IOException{        Comparator<Student> cmp = Collections.reverseOrder();        Set<Student> set = StudentInfoTool.getStudents(cmp);        StudentInfoTool.writeToFile(set);    }}class StudentInfoTool{    public static Set<Student> getStudents() throws IOException{        return getStudents(null);    }    public static Set<Student> getStudents(Comparator<Student> cmp) throws IOException{        BufferedReader bufr =                new BufferedReader(                        new InputStreamReader(System.in));        String line = null;        Set<Student> stus = null;        if(cmp == null)            stus = new TreeSet<Student>();        else            stus = new TreeSet<Student>(cmp);        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]));            stus.add(stu);        }        bufr.close();        return stus;    }    public static void writeToFile(Set<Student> stus) throws IOException{        BufferedWriter bufw =                new BufferedWriter(                        new FileWriter("d:\\test\\stud.txt"));        for(Student stu: stus){            bufw.write(stu.toString() + "\t");            bufw.write(stu.getSum() + "");            bufw.newLine();            bufw.flush();        }        bufw.close();    }}class Student implements Comparable<Student>{    private String name;    private int ch, ma, en;    private int sum;    Student(String name, int ch, int ma, int en){        this.name = name;        this.ch = ch;        this.ma = ma;        this.en = en;        sum = ch + ma + en;    }    public String getName(){        return name;    }    public int getSum(){        return sum;    }    public int hashCode(){        return name.hashCode() + sum * 78;    }    public boolean equals(Object obj){        if(!(obj instanceof Student)){            throw new ClassCastException("类型不匹配");        }        Student s = (Student)obj;        return this.name.equals(s.name) && this.sum == sum;    }    public String toString(){        return "student[" + name + "," + ch + "," + ma + "," + en +"]";    }        return int compareTo(Student s) {        int num = new Integer(this.sum).compareTo(new Integer(s.sum));        if(num == 0)            return this.name.compareTo(s.name);        return num;    }}
0 0
原创粉丝点击