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

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值