简述java IO流

简述java IO流

  • I/O是Input/Output的缩写, I/O技术是非常实用的技术,如读/写文 件,网络通讯等等。
  • (Stream)是指从源节点到目标节点的数据流动。
  • 源节点目标节点可以是文件、网络、内存、键盘、显示器等等。
  • 源节点的数据流称为输入流(用来读取数据)。
  • 目标节点的数据流称为输出流(用来写入数据)

一、IO 流的分类

1、按流向不同:

输入流

输出流(以程序为主体)

2、按数据不同:

字节流(字符流用于操作文本文件 .txt .java)

字符流(字节流用于操作非文本文件 .avi .jpg )

3、按角色不同:

节点流

处理流

请添加图片描述

字节与字符的区别

**字节(**Byte)是计量单位,表示数据量多少,是计算机信息技术用于计量存储容量的一种计量单位,通常情况下一字节等于八位。

字符(Character)计算机中使用的字母、数字、字和符号,比如’A’、‘B’、’$’、’&'等。

Java中字符是采用Unicode标准,Unicode 编码中,一个英文为一个字节,一个中文为两个字节,而在UTF-8编码中,一个中文字符是3个字节

其实字节流可以处理一切文件,而字符流只能处理纯文本文件,因为字字符的底层也是字节

二、IO 流体系

请添加图片描述

抽象基类 节点流
InputStream FileInputStream
OutputStream FileOutputStream
Reader FileReader
Writer FileWriter

例子:用 FileInputStream读取文本 先创建文件li.text ,内容为 you are beautiful

    public void test1(){

        FileInputStream file = null;

        try {
            //1. 创建 FileInputStream 的实例,同时打开指定的文件
            file = new FileInputStream("D:\\Programming\\Code\\day01\\exer003\\src\\li.text");

            //2. 读取指定文件的内容
            byte[] bytes = new byte[3]; //指定读取字节数
            int len=0;

            while ((len=file.read(bytes)) != -1) //read()读取的一定数量字节数,并将它们存储到bytes中,返回读取字节的个数,若没有数据读取则返回-1
            {
                System.out.print(new String(bytes,0,len)); //将bytes中0,到len长度的字符转为String
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (file != null)
            {
                //3. 关闭流
                try {
                    file.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
you are beautiful

用 FileOutputStream 写入文件

    @Test
    public void test2()
    {
        String s="人面桃花相映红";
        FileOutputStream file = null;

        try {
            //1. 创建 FileInputStream 的实例,同时打开指定的文件
            file = new FileOutputStream("./li2.text"); // ./表示当前目录下的先对路径,用@Test则为当前模块的路径,
            												//若是用main方法,则为当前工程的路径
            //2. 将文件内容写到指定位置
            file.write(s.getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //关闭流
            if (file!=null)
            {
                try {
                    file.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

非文本文件的复制

@Test
    public void test3(){
        String src = "C:\\Users\\library\\Desktop\\7.jpg"; //自己硬盘上的文件地址
        String dest = "C:\\Users\\library\\Desktop\\9.jpg"; //复制后的地址
        copyFile(src, dest);
    }

    private void copyFile(String src, String dest) {

        FileInputStream fis = null;
        FileOutputStream fos = null;

        try {
            //1. 创建 FileInputStream 的实例,同时打开指定文件
            fis = new FileInputStream(src);

            //2. 创建 FileOutputStream 的实例,同时打开指定文件
            fos = new FileOutputStream(dest);

            //3. 读取指定文件的内容
            byte[] b = new byte[1024];
            int len = 0;

            while ((len=fis.read(b))!=-1)
            {
                fos.write(b,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //关闭流
            if (fos != null)
            {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fis != null)
            {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

三、节点流和处理流

节点流:直接操作数据读写的流类,比如FileInputStream

处理流:对一个已存在的流的链接和封装,通过对数据进行处理为程序提供功能强大、灵活的读写功能

通常很少使用单个流对象,而是将一系列的流以包装的形式链接起来处理数据。 包装可以在不改变被包装流的前提下,获得更强的流处理功能。

请添加图片描述

1)处理流之一:缓冲流

  • 为了提高数据读写的速度,Java API提供了带缓冲功能的流类,在使用这些流 类时,会创建一个内部缓冲区数组

  • 根据数据操作单位可以把缓冲流分为:

    ➢BufferedInputStream 和 BufferedOutputStream

    ➢BufferedReader 和 BufferedWriter

  • 缓冲流要“套接”在相应的节点流之上,对读写的数据提供了缓冲的功能,提高 了读写的效率,同时增加了一些新的方法

  • 对于输出的缓冲流,写出的数据会先在内存中缓存,使用flush()将会使内存中 的数据立刻写出

简单来说,缓冲流的作用就是为了提高节点流的效率

抽象基类 节点流 缓冲流
InputStream FileInputStream BufferedInputStream
OutputStream FileOutputStream BufferedOutputStream(flush()-强制清空缓冲区)
Reader FileReader BufferedReader(readLine())
Writer FileWriter BufferedWriter(newLine())

//使用缓冲流完成非文本文件的复制
    @Test
    public void test1()
    {
        String src = "C:\\Users\\library\\Desktop\\7.jpg";
        String dest = "C:\\Users\\library\\Desktop\\9.jpg";
        copyFile(src, dest);
    }

    private void copyFile(String src, String dest) {
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;

        try {
            //1. 创建 FileReader 的实例,同时打开指定文件
            FileInputStream fis = new FileInputStream(src);

            //2. 创建 FileWriter 的实例,同时打开指定文件
            FileOutputStream fos = new FileOutputStream(dest);

            //3. 创建 BufferedReader 包装对应的节点流,用于提高效率
            bis = new BufferedInputStream(fis);

            //4. 创建 BufferedWriter 包装对应的节点流,用于提高效率
            bos = new BufferedOutputStream(fos);

            //5. 读取指定文件的内容
            byte[] b = new byte[1024];
            int len=0;

            while ((len= bis.read(b))!=-1)
            {
                bos.write(b,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //关闭流
            try {
                bos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                bis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

当读取数据时,数据按块读入缓冲区,其后的读操作则直接访问缓冲区

当使用BufferedInputStream读取字节文件时,BufferedInputStream会一次性从 文件中读取8192个(8Kb),存在缓冲区中,直到缓冲区装满了,才重新从文件中 读取下一个8192个字节数组。

向流中写入字节时,不会直接写到文件,先写到缓冲区中直到缓冲区写满, BufferedOutputStream才会把缓冲区中的数据一次性写到文件里。使用方法 flush()可以强制将缓冲区的内容全部写入输出流

关闭流的顺序和打开流的顺序相反。只要关闭最外层流即可,关闭最外层流也 会相应关闭内层节点流

flush()方法的使用:手动将buffer中内容写入文件

如果是带缓冲区的流对象的close()方法,不但会关闭流,还会在关闭流之前刷 新缓冲区,关闭后不能再写出

在文件够大的时候可以明显的看到缓冲流的效率会远大于字节流,提高效率的原因是缓冲流提供了一个大小为 8192字节的缓冲区

private static int DEFAULT_BUFFER_SIZE = 8192;

至于文本文件的复制,其实都一样,就不写了哈

2)处理流之二:标准输入、输出流(了解)

System.in和System.out分别代表了系统标准的输入和输出设备

默认输入设备是:键盘,输出设备是:显示器

System.in的类型是InputStream

System.out的类型是PrintStream,其是OutputStream的子类 FilterOutputStream 的子类

重定向:通过System类的setIn,setOut方法对默认设备进行改变。

public static void setIn(InputStream in)

public static void setOut(PrintStream out)

3)处理流之二:转换流

转换流提供了在字节流和字符流之间的转换

Java API提供了两个转换流:

InputStreamReader:将InputStream转换为Reader

OutputStreamWriter:将Writer转换为OutputStream

字节流中的数据都是字符时,转成字符流操作更高效。

InputStreamReader

实现将字节的输入流按指定字符集转换为字符的输入流。

需要和InputStream“套接”。

构造器:

public InputStreamReader(InputStream in)

public InputSreamReader(InputStream in,String charsetName)

如: Reader isr = new InputStreamReader(System.in,”gbk”);

OutputStreamWriter

用于将要写入到字节流中的字符按指定字符集编码成字节。

需要和 OutputStream“套接”。

构造器 :

public OutputStreamWriter(OutputStream out)

public OutputSreamWriter(OutputStream out,String charsetName)

    /**
     * 编码
     */
    @Test
    public void test2()
    {
        String s="弱水三千,只取一瓢";

        BufferedWriter bfr = null;
        try {
            FileOutputStream fis = new FileOutputStream("./July.txt");

            OutputStreamWriter osw = new OutputStreamWriter(fis);

            bfr = new BufferedWriter(osw);

            bfr.write(s);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                bfr.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 解码
     */
    @Test
    public void test3()
    {
        BufferedReader bur = null;
        try {
            FileInputStream fis = new FileInputStream("./July.txt");

            InputStreamReader isr = new InputStreamReader(fis, StandardCharsets.UTF_8);

            bur = new BufferedReader(isr);

            String s=null;

            while ((s=bur.readLine())!=null)
            {
                System.out.println(s);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                bur.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

四、对象流

  • ObjectInputStream和OjbectOutputSteam

    用于存储和读取基本数据类型数据或对象的处理流。它的强大之处就是可 以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来。

  • 序列化:用ObjectOutputStream类保存基本类型数据或对象的机制

  • 反序列化:用ObjectInputStream类读取基本类型数据或对象的机制

ObjectOutputStream和ObjectInputStream不能序列化static和 transient修饰的成员变量

对象的序列化

将内存中的对象永久的以二进制形式保存到磁盘中

步骤:

①创建节点流的实例,同时打开指定文件

②(可选)创建缓冲流包装对应的节点流,用于提高传输效率

③创建对象流,包装对应的缓冲流,用于完成对象的序列化

④通过 wirteXxx() 方法完成序列化操作

⑤关闭流

⑥需要序列化对象的类必须实现 java.io.Serializable 接口

⑦提供序列号 private static final long serialVersionUID = 2983723325345L;

  • 若某个类实现了 Serializable 接口,该类的对象就是可序列化的:

    创建一个 ObjectOutputStream

    调用 ObjectOutputStream 对象的 writeObject(对象) 方法输出可序列化 对象。注意写出一次,操作flush()

  • 反序列化

    创建一个 ObjectInputStream 调用 readObject() 方法读取流中的对象

  • 强调:如果某个类的字段不是基本数据类型或 String 类型,而是另一个引用 类型,那么这个引用类型必须是可序列化的,否则拥有该类型的 Field 的类也 不能序列化

请添加图片描述


@Data
class person implements Serializable 
{
    private Integer age;
    private String name;
}

    //对象的序列化
    @Test
    public void test2() {
        Person p1 = new Person("张三", 18);
        Person p2 = new Person("李四", 20);

        ObjectOutputStream oos = null;
        try {
            FileOutputStream fos = new FileOutputStream("./persons.dat");
            BufferedOutputStream bos = new BufferedOutputStream(fos);
            oos = new ObjectOutputStream(bos);

            oos.writeObject(p1);
            oos.writeObject(p2);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (oos != null) {
                try {
                    oos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    //对象的反序列化
    @Test
    public void test3() {
        ObjectInputStream ois = null;
        try {
            FileInputStream fis = new FileInputStream("./persons.dat");
            BufferedInputStream bis = new BufferedInputStream(fis);
            ois = new ObjectInputStream(bis);

            Person p1 = (Person) ois.readObject();
            Person p2 = (Person) ois.readObject();

            System.out.println(p1);
            System.out.println(p2);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            if (ois != null) {
                try {
                    ois.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

要实现对象的序列化必须要让对象类实现Serializable

注意:

  • 序列化与反序列化的顺序要一致,序列号也要相等
  • transient 和 static 修饰的属性不能被序列化

五、File类的使用

java.io.File类:文件和文件目录路径的抽象表示形式,与平台无关

  • File 能新建、删除、重命名文件和目录,但 File 不能访问文件内容本身。 如果需要访问文件内容本身,则需要使用输入/输出流。
  • 想要在Java程序中表示一个真实存在的文件或目录,那么必须有一个File对 象,但是Java程序中的一个File对象,可能没有一个真实存在的文件或目录。
  • File对象可以作为参数传递给流的构造器
常用构造器
  • public File(String pathname) 以pathname为路径创建File对象,可以是绝对路径或者相对路径,如果 pathname是相对路径,则默认的当前路径在系统属性user.dir中存储。

    绝对路径:是一个固定的路径,从盘符开始

    相对路径:是相对于某个位置开始

  • public File(String parent,String child) 以parent为父路径,child为子路径创建File对象。

  • public File(File parent,String child) 根据一个父File对象和子文件路径创建File对象

  • 路径中的每级目录之间用一个路径分隔符隔开。

常用方法

File类的获取功能

public String getAbsolutePath():获取绝对路径

public String getPath() :获取路径

public String getName() :获取名称

public String getParent():获取上层文件目录路径。若无,返回null

public long length() :获取文件长度(即:字节数)。不能获取目录的长度。

public long lastModified() :获取最后一次的修改时间,毫秒值

public String[] list() :获取指定目录下的所有文件或者文件目录的名称数组

public File[] listFiles() :获取指定目录下的所有文件或者文件目录的File数组

public boolean renameTo(File dest):把文件重命名为指定的文件路径(剪切到指定路径)

    @Test
    public void test6()
    {
        File file = new File("./July.txt");
        System.out.println(file.getName());
        System.out.println(file.getPath());
        System.out.println(file.getAbsoluteFile());
        System.out.println(file.getAbsolutePath());
        System.out.println(file.getParent());
        System.out.println(file.length());
    }
July.txt
.\July.txt
D:\Pro\code\day02\exer001\.\July.txt
D:\Pro\code\day02\exer001\.\July.txt
.
27

File类的判断功能

public boolean isDirectory():判断是否是文件目录

public boolean isFile() :判断是否是文件

public boolean exists() :判断是否存在

public boolean canRead() :判断是否可读

public boolean canWrite() :判断是否可写

public boolean isHidden() :判断是否隐藏

File类的创建功能

public boolean createNewFile() :创建文件。若文件存在,则不创建,返回false

public boolean mkdir() :创建文件目录。如果此文件目录存在,就不创建了。 如果此文件目录的上层目录不存在,也不创建。

public boolean mkdirs() :创建文件目录。如果上层文件目录不存在,一并创建

File类的删除功能

public boolean delete():删除文件或者文件夹 删除注意事项: Java中的删除不走回收站。 要删除一个文件目录,请注意该文件目录内不能包含文件或者文件目录

这些都是类似的用法,就不一 一罗列了哈

list() 获取目录中所有文件的 String 类型的列表

listFiles() 获取目录中所有文件 File 对象

这两个比较有意思,来看看

list()

	File file = new File("D:\\");

    String[] list = file.list();

    for (String s : list)
    {
        System.out.println(s);
    }
14-Ajax
14ajax课程
360Chrome
360极速浏览器下载
360驱动大师目录
aDrive

listFiles()

	File file1=new File("D:\\");

    File[] files = file1.listFiles();

    for (File f : files)
    {
        System.out.println(f);
    }
D:\14-Ajax
D:\14ajax课程
D:\360Chrome
D:\360极速浏览器下载
D:\360驱动大师目录
D:\aDrive

好了好了,IO流就暂且写到这了,好累啊,学基础真的是太枯燥了,以前学的时候基本就是看个热闹,看完了其实啥也不懂,现在回过头来再把基础的复习一下感觉清晰了不少,就先这样了,还有好多东西要补列,算法,设计模式,MySQL…

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值