美文网首页Java基础
Java基础——流(IO)

Java基础——流(IO)

作者: 莫问以 | 来源:发表于2018-08-28 09:00 被阅读9次

    流(Stream)——水流 ,可以理解为连接文件和程序的东西,Stream是从起源(source)到接收(sink)的有序数据
    一、基本分类
    1、按照流向分可以分为输入流和输出流
    输入流:只能从中读取数据,不能写入数据(基类是InputStream和Reader)
    输出流:只能向其中写入数据,不能读取数据(基类是OutputStream和Writer)


    流分类.png

    2、按照操作的数据单元分为字节流和字符流
    字节流:操作的数据单元是8位的字节(基类是InputStream和OutputStream)
    字符流:操作的数据单元是16位的字节(基类时Reader和Writer)


    IO流.jpg

    3、按照角色可以分为节点流和处理流
    节点流:可以从/向一个特定的IO设备中读/写数据的流,也被称为低级流
    处理流:用于对一个已存在的流进行连接或封装来实现读/写功能,也称为高级流或包装流

    二、IO流————字节流和字符流
    1、什么是字节流 ?
    计算机存储大小以字节计,字节可以表示所有的数据,比如文本,音频,视频.图片,都是作为字节存在的。PS: 字节流处理的单元是一个字节,用于操作二进制文件(计算机中所有文件都是二进制文件)
    2、什么是字符流?
    字节流读取文字字节数据后,不直接操作而是先查指定的编码表,获取对应的文字。再对这个文字进行操作。简单说:字符流==字节流+编码表。

    IO流的常用基类:
    字节流的抽象基流:InputStream和OutputStream
    字符流的抽象基流:Reader和Writer
    PS:此四个类派生出来的子类名称都是以父类名作为子类名的后缀,以前缀为其功能;如InputStream子类FileInputStream;Reader子类FileReader等等,看图:


    InputStream.png
    outPutStream.png
    Reader.png
    Writer.png

    示例:文件流——FileOutputStream
    文件字节输出流,使用该流可以以字节为单位将数据写入文件。
    FileOutputStream(File file)
    FileOutputStream(String str)
    PS:使用FOS对其写入数据时,若指定的文件已经包含内容,会将该文件中原有数据清除。FileOutputStream(File file,boolean true)则可以在文件原有数据末尾后追加。
    字节流输入

     public class FileInputStreamTest {
            public void main(String[] args) throws IOException {
            FileInputStream fis = new FileInputStream("FileInputStreamTest.java");
            byte[] bytes = new byte[1024];
            int hasRead = 0;
            while ((hasRead = fis.read(bytes)) > 0) {
                System.out.println(new String(bytes,0,hasRead));
            }
            fis.close();
            }
        }
    

    字节流输出

    public class FileOutputStreamTest {
            public void main(String[] args) {
            try (FileOutputStream fileOutputStream = new FileOutputStream("file.txt");
                 FileInputStream fileInputStream = new FileInputStream("FileInputStreamTest.java")) {
                byte[] bytes = new byte[1024];
                int hasRead = 0;
                while ((hasRead = fileInputStream.read(bytes)) > 0) {
                    fileOutputStream.write(bytes,0,hasRead);
                }
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            }
        }
    

    字符流输入

    public class FileReaderTest {
            public void main(String[] args) {
            try (FileReader fileReader = new FileReader("FileInputStreamTest.java")) {
                char[] chars = new char[1024];
                int hasRead = 0;
                while ((hasRead = fileReader.read(chars)) > 0) {
                    System.out.println(new String(chars,0,hasRead));
                }
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            }
        }
    

    字符流输出

    public class FileWriterTest {
            public void main(String[] args) {
            try (FileWriter fileWriter = new FileWriter("poem.txt")){
                fileWriter.write("锦瑟 -李商隐\r\n");// \r\n是windows平台的换行符
                fileWriter.write("锦瑟无端五十弦,一弦一柱思华年\r\n");
                fileWriter.write("庄生晓梦迷蝴蝶,望月春心托杜鹃\r\n");
                fileWriter.write("沧海月明珠有泪,蓝田日暖玉生烟\r\n");
                fileWriter.write("此情可待成追忆,只是当时已惘然\r\n");
            } catch (IOException e) {
                e.printStackTrace();
            }
            }
        }
    

    PS:不同的系统针对不同的换行符号识别是不一样的
    windows:\r\n
    linux:\n
    Mac:\r

    1. 缓冲流
      字节缓冲输出流:BufferedOutputStream,
      字节缓冲输入流:BufferedInputStream。
      基本代码示例:
    public class BufferedOutputStreamDemo {
        public static void main(String[] args) throws IOException {
            // BufferedOutputStream(OutputStream out)
            // FileOutputStream fos = new FileOutputStream("bos.txt");
            // BufferedOutputStream bos = new BufferedOutputStream(fos);
            // 简单写法
            BufferedOutputStream bos = new BufferedOutputStream(
                    new FileOutputStream("bos.txt"));
            // 写数据
            bos.write("hello".getBytes());
            // 释放资源
            bos.close();
        }
    }
    

    练习题:利用字节缓冲流复制数据练习

    package Paint;
    
    import java.io.BufferedInputStream;
    import java.io.BufferedOutputStream;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    
    /*
     * 需求:把e:\\a.mp4复制到当前项目目录下的b.mp4中
     * 
     * 字节流四种方式复制文件:
     * 基本字节流一次读写一个字节:   共耗时:117235毫秒
     * 基本字节流一次读写一个字节数组: 共耗时:156毫秒
     * 缓冲流一次读写一个字节: 共耗时:1141毫秒
     * 缓冲流一次读写一个字节数组: 共耗时:47毫秒
     */
    public class BufferFile {
        public static void main(String[] args) throws IOException {
            long start = System.currentTimeMillis();
            // method1("e:\\a.mp4", "copy1.mp4");
            // method2("e:\\a.mp4", "copy2.mp4");
            // method3("e:\\a.mp4", "copy3.mp4");
            method4("e:\\a.mp4", "copy4.mp4");
            long end = System.currentTimeMillis();
            System.out.println("共耗时:" + (end - start) + "毫秒");
        }
    
        // 高效字节流一次读写一个字节数组:
        public static void method4(String srcString, String destString) throws IOException {
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcString));
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destString));
    
            byte[] bys = new byte[1024];
            int len = 0;
            while ((len = bis.read(bys)) != -1) {
                bos.write(bys, 0, len);
            }
    
            bos.close();
            bis.close();
        }
    
        // 高效字节流一次读写一个字节:
        public static void method3(String srcString, String destString) throws IOException {
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcString));
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destString));
    
            int by = 0;
            while ((by = bis.read()) != -1) {
                bos.write(by);
            }
    
            bos.close();
            bis.close();
        }
    
        // 基本字节流一次读写一个字节数组
        public static void method2(String srcString, String destString) throws IOException {
            FileInputStream fis = new FileInputStream(srcString);
            FileOutputStream fos = new FileOutputStream(destString);
    
            byte[] bys = new byte[1024];
            int len = 0;
            while ((len = fis.read(bys)) != -1) {
                fos.write(bys, 0, len);
            }
    
            fos.close();
            fis.close();
        }
    
        // 基本字节流一次读写一个字节
        public static void method1(String srcString, String destString) throws IOException {
            FileInputStream fis = new FileInputStream(srcString);
            FileOutputStream fos = new FileOutputStream(destString);
    
            int by = 0;
            while ((by = fis.read()) != -1) {
                fos.write(by);
            }
    
            fos.close();
            fis.close();
        }
    }
    
    1. 重定向标准输入/输出

    重定向是指改变输入/输出目标(由键盘/屏幕改为文件)
    重定向输出流

    public class RedirectOut {
            public void main(String[] args) {
            try (PrintStream printStream = new PrintStream(new FileOutputStream("out.txt"))){
                System.setOut(printStream);
                System.out.println("普通字符串");
                System.out.println(new RedirectOut());
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
            }
        }
    

    重定向输入流

        public class RedirectIn {
            public void main(String[] args) {
            try (FileInputStream fileInputStream = new FileInputStream("poem.txt")) {
                System.setIn(fileInputStream);
                Scanner scanner = new Scanner(System.in);
                scanner.useDelimiter("\n");//只把回车作为换行符
                while (scanner.hasNext()) {
                    System.out.println("键盘输入内容:" + scanner.next());
                }
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            }
        }
    

    ---------------------- 对象流 -------------------------
    ObjectInputStream和ObjectOutputStream
    可以通过这两个流对象直接操作已有对象并将对象进行本地持久化存储,存储后的对象可以进行网络传输。

    两个对象的特有方法:
    ObjectInputStream
    Object readObject():该方法抛出异常:ClassNotFountException。

    ObjectOutputStream
    void writeObject(Object):被写入的对象必须实现一个接口:Serializable
    否则会抛出:NotSerializableException

    java允许类的对象通过串形化进行传输,实现Serializable 接口,虽然这个接口什么都没有,但一个类声明实现这个接口是,只是表明该类加入对象串行化协议。

    package Paint;
    
    import java.io.Serializable;
    
    public class Teacher implements Serializable {
    
        /** 自动生成一个UID */
        private static final long serialVersionUID = 1L;
        /** id */
        private int id;
        /** 名字 */
        private String name;
        /** 性别 */
        private String sex;
        /** 年龄 */
        private int age;
        /** 主要职务 */
        private String mainJob;
    
        public Teacher() {
        
        }
    
        public Teacher(int id, String name, String sex, int age, String mainJob) {
            super();
            this.id = id;
            this.name = name;
            this.sex = sex;
            this.age = age;
            this.mainJob = mainJob;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getSex() {
            return sex;
        }
    
        public void setSex(String sex) {
            this.sex = sex;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        public String getMainJob() {
            return mainJob;
        }
    
        public void setMainJob(String mainJob) {
            this.mainJob = mainJob;
        }
    
        @Override
        public String toString() {
            return "Teacher [id=" + id + ", name=" + name + ", sex=" + sex + ", age=" + age + ", mainJob=" + mainJob + "]";
        }
    }
    
    package Paint;
    
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    
    public class ObjectIO {
        public static void saveObject(Object obj, String filePath) {
            File file = new File(filePath);
            try {
                FileOutputStream fos = new FileOutputStream(file);
                ObjectOutputStream oos = new ObjectOutputStream(fos);
                oos.writeObject(obj);
                oos.flush();
                oos.close();
                fos.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        @SuppressWarnings("unchecked")
        public static <T> T readObject(String filePath) {
            File file = new File(filePath);
            Object obj = null;
            try {
                FileInputStream fis = new FileInputStream(file);
                ObjectInputStream ois = new ObjectInputStream(fis);
                obj = ois.readObject();
                ois.close();
                fis.close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            return (T) obj;
        }
    
        @SuppressWarnings("unchecked")
        public static <T> T cloneObject(Object obj) {
            Object objClone = null;
            try {
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                ObjectOutputStream oos = new ObjectOutputStream(baos);
                oos.writeObject(obj);// 将对象通过对象输出流,缓存到数组输出流中
    
                oos.flush();
                byte[] objTemp = baos.toByteArray();// 对象缓存为数组了
    
                // 开始克隆
                ByteArrayInputStream bais = new ByteArrayInputStream(objTemp);
                ObjectInputStream ois = new ObjectInputStream(bais);
                objClone = ois.readObject();
    
                ois.close();
                bais.close();
                oos.close();
                baos.close();
    
            } catch (Exception e) {
                e.printStackTrace();
            }
            return (T) objClone;
        }
    }
    

    测试类代码:

    package Paint;
    
    public class Test {
    
        public static void main(String[] args) throws InterruptedException {
            // new一个老师
            Teacher teacher = new Teacher(1, "李树人", "女", 23, "扫地");
            System.out.println("输出Teacher对象--"+teacher.toString());
    
            // 保存对象到文件中
            System.out.println("对象流保存Teacher对象--");
            ObjectIO.saveObject(teacher, "teacher.txt");
    
            // 线程休眠
            System.out.println("写入完毕,可以去打开teacher.txt看看有什么东西\n");
            Thread.sleep(2500);
    
            // 从本地文件获取并查看保存的对象
            Teacher teacherClone1 = ObjectIO.readObject("teacher.txt");
            System.out.println("teacherClone1"+teacherClone1.toString());
    
            System.out.println("对象判断=="+teacher.equals(teacherClone1)+"--它们确实不是同一个对象!");
    
            // 直接克隆,不写入本地
            Teacher teacherClone2 = ObjectIO.cloneObject(teacher);
            System.out.println("teacherClone2--"+teacherClone2.toString());
            
            System.out.println("teacherClone2真假判断=="+teacherClone2.equals(teacher));
            
        }
    }
    

    输出结果:


    输出结果

    我们可以看,对象是否相同判断,结果为False,可知对象不同,我们再看teacher.txt


    teacher.txt

    相关文章

      网友评论

        本文标题:Java基础——流(IO)

        本文链接:https://www.haomeiwen.com/subject/kxxfwftx.html