Java基础篇——IO流

I/O流

概况图

在这里插入图片描述

一、File

概念:代表物理盘符中的一个文件或文件目录(即文件夹)

理解

  • 相对路径:相较于某个路径下,指明的路径
  • 绝对路径:包含盘符在内的文件或文件目录的路径

删除方法

  • delete
    • 删除一个文件或空目录

创建方法

  • boolean createNewFile()
    • 创建一个新文件
  • boolean mkdir()
    • 创建文件目录。如果此文件目录存在,就不创建;如果上层目录不存在也不创建
  • boolean mkdirs()
    • 创建目录。如果目录不存在,一并创建

获取方法

  • String getAbsolutePath()
    • 获取绝对路径
  • String getPath()
    • 获取路径
  • String getName()
    • 获取名称
  • String getParent()
    • 获取上层文件目录路径。若无,返回null
  • long length()
    • 获取文件长度(字节数)。不能获取目录的长度
  • long lastModified()
    • 获取最后一次的修改时间,毫秒值
  • String [] list()
    • 获取指定目录下的所有文件或者文件目录的名称数组
  • File []listFiles()
    • 获取指定目录下的所有文件或者文件目录的File数组

判断方法

  • boolean renameTo(File desk)

    • 把文件重命名为指定的文件路径

      //要保证返回true,需要file1在硬盘中存在,且file2不能在硬盘中存在
      File file1 = new File("hello.txt");
      File file2 = new File("D:\\hi.txt");
      boolean a = file1.renameTo(file2);
      
  • boolean isDirectory()

    • 判断是否文件目录
  • boolean isFile()

    • 判断是否是文件
  • boolean exists()

    • 判断是否存在
  • boolean canRead()

    • 判断是否可读
  • boolean canWrite()

    • 判断是否可写
  • boolean isHidden()

    • 判断是否隐藏

FileFilter接口

当调用File类中的listFiles()方法时,支持传入FileFilter接口实现类,对获取文件进行过滤,只有满足条件的文件的才可出现在listFiles()的返回值中

语法

public interface FileFilter
    boolean accept(File pathname)

综合案例

		//遍历当前目录下所有文件名和文件夹名
		//方式一:遍历目录文件下以.jpg结尾的文件
        File dir2=new File("d:\\");
		String[] list=dir2.list(new FilenameFilter() {
            @Override
            public boolean accept(File dir, String name) {// 测试指定文件是否应该包含在某一文件列表中。
                //return true;//符合要求
                //return false;//不符合要求
                if(name.endsWith(".jpg")){
                    return true;
                }
                return false;
            }
        });
        for (String s : list) {
            System.out.println(s);
        }
		//方式二:
        
        System.out.println("-----------list()---------");
        //获取当前目录下的所有的文件名和文件夹名
       String[] list = dir2.list();
        for (String s : list) {
            System.out.println(s);
        }

public class FileDemo3 {
    public static void main(String[] args) {
        ///listDir(new File("d:\\aaa"),0);
        listDir(new File("D:\\H5_SQL"),0);
    }
    //案例1:递归遍历文件夹
    public static void listDir(File dir,int level){
        File[] files = dir.listFiles();
        System.out.println(getSeparator(level)+dir.getName());
        level++;
        if(files!=null&& files.length>0){
            for (File file : files) {
                if(file.isDirectory()){//file是文件夹
                    listDir(file,level);
                }else{
                    System.out.println(getSeparator(level)+file.getName());
                }
            }
        }
    }
    public static String getSeparator(int level){
        if(level<=0){
            return "";
        }
        StringBuilder sb=new StringBuilder("|");
        for (int i = 0; i < level; i++) {
            sb.append("________");
        }
        return sb.toString();
    }
    //案例2:递归删除文件夹
    public static void listDelete(File dir){
        File[] files = dir.listFiles();
        if(files!=null&&files.length>0){
            for (File file : files) {
                if(file.isDirectory()){
                    listDelete(file);
                }else{
                    //删除文件
                    System.out.println(file.toString()+" 删除结果是:"+file.delete());//不进回收站
                }
            }
        }
        //删除dir
        System.out.println(dir.toString()+" 删除结果是:"+dir.delete());
    }

}

二、IO流原理及流的分类

1.抽象基类

  • InputStream/OutputStream 字节流输入/输出
    • InputStream 字节输入流
      • public int read()
      • public int read(byte []b)
      • public int read(byte []b, int off, int len)
    • OutputStream 字节输出流
      • public void write(int n)
      • public void write(byte []b)
      • public void write(byte []b, int off, int len)
  • Reader/Writer 字符流输入/输出

2.流的分类

  • 单位
    • 字节流:以字节为单位,可以读写所有数据
    • 字符流:以字符为单位,只能读写文本数据
  • 功能
    • 结点流:具有实际传输数据的读写功能
    • 过滤流:在结点流的基础之上增强功能

三、节点流(或文件流)

3.1 FileInputStream/FileOutputStream 字节流输入/输出

  • public int read(byte[] b)
    • 从流中读取多个字节,将读到内容存入b数组,返回实际读到的字节数;如果达到文件的尾部,则返回-1
  • public void write(byte []b)
    • 一次写多个字节,将b数组中所有字节,写入输出流

3.2 FileReader/FileWriter 字符流输入/输出

  • public int read(char[] b)

    • 从流中读取多个字节,将读到内容存入b数组,返回实际读到的字节数;如果达到文件的尾部,则返回-1
  • public void write(String b)

    • 一次写多个字节,将b数组中所有字节,写入输出流
  • 输出流可以追加

new FileOutputStream("d:\\aaa.txt",true);
new FileWriter("d:\\aaa.txt",true);
public class FileInputStreamDemo {
    public static void main(String[] args) throws Exception{
        //1创建流
        FileInputStream fis=new FileInputStream("d:\\aaa.txt");
        System.out.println("字节个数:"+fis.available());
        //2读取
        //2.1 单个字节读取
        int data;
        while((data=fis.read())!=-1) {
            System.out.print((char)data);
        }
        //2.2 一次读取多个字节
//        byte[] buf=new byte[5];
//        int len;
//        while((len=fis.read(buf))!=-1){
//            String s=new String(buf,0,len);
//            System.out.print(s);
//        }
        //3关闭
        fis.close();
    }
}

public class FileOutputStreamDemo {
    public static void main(String[] args) throws  Exception{
        //1创建文件字节输出流
        FileOutputStream fos=new FileOutputStream("d:\\out.txt",true);
        //2写入
        //2.1写入一个字节
//        fos.write(97);
//        fos.write(98);
//        fos.write(99);
        //2.2写入多个字节
        String s="好好学习,天天向上\r\n";
        byte[] data=s.getBytes();//把字符串转成字节数组
        for (int i = 0; i < 10; i++) {
            fos.write(data);
        }
        //3关闭
        fos.close();
        System.out.println("执行完了");
    }
}

四、缓冲流

4.1 BufferedInputStream/BufferedOutputStream 字节缓冲流输入/输出

4.2 BufferedReader/BufferedWriter 字符缓冲流输入/输出

  • 支持输入换行符
  • 可一次写一行,读一行
  • 默认8K
public class BufferedInputStreamDemo {
    public static void main(String[] args) throws  Exception{
        //1创建字节缓冲输入流
        FileInputStream fis=new FileInputStream("d:\\aaa.txt");
        BufferedInputStream bis=new BufferedInputStream(fis);
        //2读取文件
        int data;
        while((data=bis.read())!=-1){
            System.out.print((char)data);
        }
        //3关闭(只关闭缓冲流,内部把底层流关闭了)
        bis.close();

    }
}
public class BufferedOutputStreamDemo {
    public static void main(String[] args) throws  Exception {
        //1使用字节缓冲输出流写入文件
        FileOutputStream fos=new FileOutputStream("d:\\buffer.txt");
        BufferedOutputStream bos=new BufferedOutputStream(fos);
        //2写入文件
        String s="Java是世界上最好的语言\r\n";
        byte[] bytes=s.getBytes();
        for (int i = 0; i < 10; i++) {
            bos.write(bytes);//8K
            //bos.flush();//刷新缓冲
        }
        //3关闭(关闭缓冲流时会自动刷新缓冲区。相当于关闭了底层流)
        bos.close();
        System.out.println("结束了");
        System.out.println("------------------");
        补充 try的特殊用法:自动调用close方法,要求对象实现Closeable接口--------
        try(Student ss=new Student()){
            System.out.println(ss.toString());
        }
    }
}

五、转换流

5.1 InputStreamReader

将InputStream转换为Reader,字节输入流转换为字符输入流 字符流

5.2 OutputStreamWriter

将OutputStream转换为Writer,将字节输出流转换为字符输出流 字符流

作用

  • 解码:字节,字节数组–>字符,字符数组

  • 编码:字符,字符数组–>字节,字节数组

  • 可设置字符编码

    new InputStreamReader(new FileInputStream("d:\\writer.txt"),"utf-8");
    

public class InputStreamReaderDemo {
    public static void main(String[] args) throws Exception{
        //1创建的转换流
        InputStreamReader isr=new InputStreamReader(new FileInputStream("d:\\writer.txt"),"utf-8");
        //2读取
        char[] buf=new char[1024];
        int len;
        while((len=isr.read(buf))!=-1){
            String s=new String(buf,0,len);
            System.out.println(s);
        }
        //3关闭
        isr.close();
    }
}
public class OutputStreamWriterDemo {
    public static void main(String[] args) throws Exception {
        //1创建转换流
        OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("d:\\output.txt"), "gbk");
        //2写出
        for (int i = 0; i < 10; i++) {
            osw.write("我爱北京\r\n");
        }
        //3关闭
        osw.close();

    }
}

六、标准输入,输出流

6.1. System.in/System.out

标准的输入流,默认键盘输入/标准的输出流,默认从控制台输出

System.in -----------> InputStream

  • FileInputStream类型

System.out ------------> OutputStream

  • PrintStream类型
  • 默认打印到控制台
  • 重定向标准输出流

6.2. 重定向标准输入/出流

System.setOut();

七、打印流

7.1 PrintStream 字节输出流

7.2 PrintWriter 字符输出流

  • 封装了print()/println()方法,支持写入后换行
//打印流,配合重定向输出流
public class Demo04 {
    public static void main(String[] args) {

        FileOutputStream fos = null;
        //打印字节流
        PrintStream ps = null;
        try {
            fos = new FileOutputStream("D:\\ceshi1.txt");
            ps = new PrintStream(fos, true);

            if (ps != null) {
                //重定向输出流
                System.setOut(ps);
            }

            for (int i = 0; i < 256; i++) {
                System.out.print((char) i);
                if (i % 50 == 0) {
                    System.out.println();
                }
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } finally {
            ps.close();
        }
    }
}

八、数据流

8.1 DataInputStream/DataOutputStream 数据输入流/输出流 字节流

方便操作Java语言的基本类型数据和String的数据,可以使用数据流。

九、对象流

9.1 ObjectOutputStream/ObjectInputStream

  • 增强了缓冲区功能
  • 增强了读写对象的功能
    • readObject()
    • 从流中读取一个对象
    • writeObject(Object obj)
    • 向流中写入一个对象

9.2 序列化,反序列化

  • 序列化
    • 把对象写入到硬盘或网络中的过程
  • 反序列化
    • 把硬盘或网络的二进制文件读取到内存形成对象的过程

对象序列化的细节

  • 序列化类及其对象属性必须实现Serializable接口
  • transient修饰为临时属性,不参与序列化
  • 读取到文件尾部的标志:java.io.EOFException
  • 使用serialVersionUID属性保证序列化的类和反序列化的类是同一个类
  • static属性不参与序列化

手动序列化接口:Externalizable(必须有无参构造)

//手动序列化
//创建Student对象
public class Student implements Closeable, Externalizable {
    private String name;
    private transient int age;

    private static final long serialVersionUID=100L;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Student() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public void close() throws IOException {
        System.out.println("学生关闭了...");
    }

    //写入数据
    @Override
    public void writeExternal(ObjectOutput out) throws IOException {
        out.writeUTF(name);
        out.writeInt(age);
        System.out.println("writeExternal");

    }
    //读取数据
    @Override
    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
        name=in.readUTF();
        age=in.readInt();
        System.out.println("readExternal");
    }
}
//序列化:也就是输出
public class ObjectOutputStreamDemo {
    public static void main(String[] args) throws  Exception{
        //实现序列化功能:把对象写入到硬盘或网络中的过程。
        //细节1:序列化类及其对象属性必须实现Serializable接口。
        //细节2:transient修饰为瞬间(临时)属性,不参与序列化。
        //细节3:读取到文件尾部的标志:java.io.EOFException。
        //细节4:使用serialVersionUID属性保证序列化的类和反序列化的类是同一个类。
        Student s1=new Student("AA", 20);
        Student s2=new Student("AAA", 22);
        Student s3=new Student("AAAA", 23);
        ArrayList<Student> list=new ArrayList<>();
        list.add(s1);
        list.add(s2);
        list.add(s3);
        //1创建对象流
        FileOutputStream fos=new FileOutputStream("d:\\student.bin");
        ObjectOutputStream oos=new ObjectOutputStream(fos);
        //2序列化
        oos.writeObject(list);
        //3关闭
        oos.close();
        System.out.println("序列化完成...");

    }
}

//反序列化:输入
public class ObjectInputStreamDemo {
    public static void main(String[] args) throws  Exception{
        // 实现反序列化功能:把硬盘或网络的二进制文件读取到内存形成对象的过程。
        //(1)创建流
        FileInputStream fis=new FileInputStream("d:\\student.bin");
        ObjectInputStream ois=new ObjectInputStream(fis);
        //(2)反序列化
        ArrayList<Student> list= (ArrayList<Student>) ois.readObject();


        for (Student student : list) {
            System.out.println(student.toString());
        }
         //(3)关闭
        ois.close();
    }
}

十、随机存取文件流

  • RandomAccessFile既可以读取文件内容,也可以向文件中写入内容
  • 但是和其他输入/输出流不同的是,程序可以直接跳到文件的任意位置来读写数据
    • 读写模式
      • r:只读
      • rw:读写
    • 作用
      • 快速定位数据,并支持读写
      • 方便的获取二进制文件
public class RandomAccessFileDemo {
    public static void main(String[] args)throws Exception {
        //write();
        read();
    }
    public static void write() throws Exception{
        //1创建RandomAccessFile对象
        RandomAccessFile raf=new RandomAccessFile("d:\\ran.txt", "rw");
        //2写入
        raf.writeUTF("灿灿");
        raf.writeInt(20);
        raf.writeBoolean(true);
        raf.writeDouble(183.5);
        raf.writeUTF("龙哥");
        raf.writeInt(22);
        raf.writeBoolean(false);
        raf.writeDouble(183.6);
        //3关闭
        raf.close();
        System.out.println("写入完毕");
    }
    public static void read() throws Exception{
        //1创建RandomAccessFile对象
        RandomAccessFile raf=new RandomAccessFile("d:\\ran.txt", "r");
        //设置读取的指针的位置
        //raf.seek(21);
        //跳过指定的字节个数
        raf.skipBytes(21);
        //2读取
        String name=raf.readUTF();
        int age=raf.readInt();
        boolean sex=raf.readBoolean();
        double height=raf.readDouble();
        System.out.println(name+"..."+age+"..."+sex+"..."+height);
        //3关闭
        raf.close();
    }
}
public class RandomAccessFileDemo2 {
    public static void main(String[] args) throws Exception{
        ExecutorService es = Executors.newFixedThreadPool(4);
        byte[] data=new byte[1024*1024];//1M
        CountDownLatch countDownLatch=new CountDownLatch(4);
        long start=System.currentTimeMillis();
        for(int i=0;i<4;i++){
            int n=i;
            es.submit(new Runnable() {
                @Override
                public void run() {
                    RandomAccessFile raf= null;
                    try {
                        raf = new RandomAccessFile("d:\\电影.mp4", "rw");
                        System.out.println(Thread.currentThread().getName()+"开始下载了...");
                        raf.seek(n*(1024*1024));
                        raf.write(data);
                        Thread.sleep(2000);
                        raf.close();
                        System.out.println(Thread.currentThread().getName()+"下载完毕了...");
                        countDownLatch.countDown();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                }
            });
        };
        es.shutdown();
        countDownLatch.await();
        long end=System.currentTimeMillis();
        System.out.println("总用时:"+(end-start));
    }
}

十一、Properties

  • Properties:属性集合
  • 特点
    • 存储属性名和属性值
    • 属性名和属性值都是字符串类型
    • 没有泛型
    • 和流有关
  • 方法
    • list(PrintStream/PrintWriter out)
      • 将属性列表输出到指定的输出流
    • load(InputStream/Reader in)
      • 从输入流/输入字符中读取属性列表(键和元素对)
    • store(OutputStream/Writer out,String comments)
public class PropertiesDemo {
    public static void main(String[] args) throws Exception {
        //1创建集合
        Properties properties=new Properties();
        //2添加数据
        properties.setProperty("name", "张三");
        properties.setProperty("age","20" );
        properties.setProperty("address", "北京");
        //3与流有关的方法
        //-------1 list 使用打印流打印数据--------
        properties.list(System.out);
        //-------2 store 存储到硬盘---------------
        FileOutputStream fos=new FileOutputStream("d:\\user.properties");
        properties.store(fos,"注释");
        fos.close();
        //-------3 load 加载属性文件---------
        System.out.println("------load-----");
        Properties properties2=new Properties();
        FileInputStream fis=new FileInputStream("d:\\user.properties");
        properties2.load(fis);
        fis.close();
        properties2.list(System.out);
    }
}

十二、ByteArrayInputStream/ByteArratOutputStream

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值