IO流快速入门通俗易懂

本章File内容知识主要来自B站孙探老师的讲解外加一点点个人的理解,传送门-biu

IO流

概述

  • 流是一种抽象概念,它代表了数据的无结构化传递。按照流的方式进行输入输出,数据被当成无结构的字节序或字符序列。从流中取得数据的操作称为提取操作,而向流中添加数据的操作称为插入操作。用来进行输入输出操作的流就称为IO流。换句话说,IO流就是以流的方式进行输入输出 ------百度百科
  • 图1:
    在这里插入图片描述

IO流是什么?

仔细看过上图中的朋友们一定对Io流有了略微的一点认知!
IO:Input输入流和Output输出流

  • 那么输入输出流又是什么意思?
    • 就是Java程序进行数据传输的管道
    • 流 就是管道的意思!

从图一可知,Io流主要是用来传输文件的(也就是文件的上传下载 可能不太恰当)

文件(类 File)又是什么呢?

概述:

  • 在计算机中所有数据都是以文件的格式存储的
  • 在Java中认为文件是一个对象
  • Java认为所有的东西都是对象

构造方法:

  • File (String Pathname) :根据一个路径得到File对象
  • File (String parent,String child):根据一个目录和一个子文件/目录得到File对象
  • File(File parent,String child):根据一个父File对象和一个子文件/目录得到File对象
  • 实例:
        public class FileTest {
          //File类的构造方法:
          public static void main(String[] args) {
              //第一种
              File file1 = new File("D:\\123\\123.text");
              //第二种
              File file2 = new File("D:\\123","123.text");
              //第三种
              File file = new File("D:\\123");
              File file3 = new File(file,"123.txt");
          }
      	}
    

成员方法:

创建功能,删除功能,重命名功能,判断功能,获取功能

创建功能
  • public boolean createNewFile():创建文件,如果存在这样的文件,就不创建了
  • public boolean mkdir ( ):创建文件夹,如果存在这样的文件夹,就不创建了(make dirctory)
  • public boolean mkdirs () :创建文件夹,如果父文件夹不存在,会帮你创建出来
  • 实例:
    public class FileTest2 {
        //File类的构造方法:
        public static void main(String[] args) throws Exception {
            /**
             * public boolean createNewFile():创建文件,如果存在这样的文件,就不创建了
             */
            File file = new File("D:\\123\\b.txt");
            boolean b = file.createNewFile();
            System.out.println(b);
            //如果没有指明创建路径,那么该文件是在项目路径下创建的!
            File file2 = new File("b.txt");
            file2.createNewFile();
            /**
             * public boolean mkdir ( ):创建文件夹,如果存在这样的文件夹,就不创建了(make dirctory)
             * 该方法不能创建多层文件夹
             */
            File file3 = new File("D:\\123\\123456");
            boolean mkdir = file3.mkdir();
            System.out.println(mkdir);
            /**
             * public boolean mkdirs () :创建文件夹,如果父文件夹不存在,会帮你创建出来
             * 该方法可以创建多层文件夹
             */
            File file4 = new File("D:\\123\\123\\123");
            boolean mkdirs = file4.mkdirs();
            System.out.println(mkdirs);
        }
    }
    
删除功能
  • public boolean delete():可以用来删除文件和文件夹
  • delete删除的文件夹下面不能有文件或文件夹!!!
    实例:
    
    public class FileTest3 {
        public static void main(String[] args) throws Exception {
            //注意:delete删除的文件夹下面不能有文件或文件夹
            File file = new File("D:\\123");
            File file2 = new File("D:\\123.txt");
            file.delete();
            file2.delete();
        }
    }
    
重命名功能
  • public boolean renameTo(File dest):可以给文件或者文件夹改名字
  • 如果File改名的路径是在同一路径下,就是重命名
  • 如果File改名的路径不是在同一路径下,就是重命名并移动!
    实例:
    public class FileTest4 {
        public static void main(String[] args) throws Exception {
            //把"D:\123"文件夹的名字改为"D:\12345"
            File file = new File("D:\\123");
            File file2 = new File("D:\\12345");
            file.renameTo(file2);
            //把"D:\123.txt"的的名字改为"12345.txt"
            File file3 = new File("D:\\123.txt");
            file3.renameTo(new File("D:\\12345.txt"));
            //改名并移动
            File file5 = new File("D:\\12345.txt");
            file5.renameTo(new File("D:\\12345\\123456.txt"));
        }
    }
    
判断功能
  • public boolean isDirectory():判断是否是目录
  • public boolean isFile():判断是否是文件
  • public boolean exists ()∶判断是否存在
  • public boolean canRead():判断是否可读
  • public boolean canwrite():判断是否可写
  • public boolean isHidden ():判断是否隐藏
    实例:
    public class FileTest5 {
        public static void main(String[] args) throws Exception {
            //判断是否是文件
            File file1 = new File("D:\\12345");
            boolean file = file1.isFile();
            System.out.println(file);
            //判断是否是文件夹
            File file2 = new File("D:\\12345\\123456.txt");
            boolean directory = file2.isDirectory();
            System.out.println(directory);
            //判断为文件是否存在
            boolean exists = file2.exists();
            System.out.println(exists);
            //判断是否可读
            boolean b = file2.canRead();
            System.out.println(b);
            //判断是否可写
            boolean b1 = file2.canWrite();
            System.out.println(b1);
            //判断是否隐藏
            boolean hidden = file2.isHidden();
            System.out.println(hidden);
        }
    }
    
获取功能
  • public string getAbsolutePath ():获取绝对路径
  • public string getPath():获取相对路径
  • public string getName () :获取名称
  • public long length ():获取长度。字节数
  • public long lastModified():获取最后一次的修改时间,毫秒值

相对路径:从当前文件/文件夹所在的位置开始,一直到你想去的某个文件/文件夹下就叫做相对路径。
绝对路径:文件在系统磁盘上的路径,从盘符开始,一直到文件/文件夹的名称就叫做绝对路径。

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

实例:

public class FileTest6 {
    public static void main(String[] args) throws Exception {
        File file = new File("D:\\12345\\123456.txt");
        //获取绝对路径
        String absolutePath = file.getAbsolutePath();
        System.out.println(absolutePath);
        //获取相对路径
        String path = file.getPath();
        System.out.println(path);
        //获取名称
        String name = file.getName();
        System.out.println(name);
        //获取长度。字节数
        long length = file.length();
        System.out.println(length);
        //获取最后一次的修改时间 精确到毫秒
        long l = file.lastModified();
        Date date = new Date(l);
        System.out.println(date.toLocaleString());

        //获取指定目录下的所有文件或者文件夹的名称数组
        File files = new File("D:\\12345");
        String[] list = files.list();
        for (String s : list) {
            System.out.println(s);
        }
        //获取指定目录下的所有文件或者文件夹的File数组
        File[] files1 = files.listFiles();
        for (File fil2:files1) {
            System.out.println(fil2.getAbsolutePath());
        }
    }
}

File说完了再回到IO流

IO流的分类:

根据流向可以分为:(不管是输入流还是输出流都是根据你当前的程序而言的)

  • 输入流:(读read) input
  • 输出流:(写write) output

根据传输的内容分为:

  • 字节数据: 图片,视频,音频

    • 字节输入流:InputStream
    • 字节输出流:OutputStream
  • 字符数据:abcd

    • 字符输入流:Reader
    • 字符输出流:Writer
  • 不管是字符流还是字节流,底层流动的都是字节!

图解:
在这里插入图片描述
这里主要来看InputStream和OutputStream


字节流InputStream

概念
  • InputStream是所有字节输入流的顶层父类,是一个抽象类。如果要用,需要使用子类。(FileInputStream)
    • FileInputStream流被称为文件字节输入流,意思指对文件数据以字节的形式进行读取操作如读取图片视频等

换句话说呢就是不用管 InputStream 是干嘛的,只需要知道他的子类FileInputStream很有用就行,而他的子类怎么用呢,看下面 :

FileInputStream构造方法:
  1. FileInputStream​(File file): 传递一个File类型的文件
  2. FileInputStream​(String name): 传递一个String类型的文件路径
    推荐使用下面这种方法:

FileInputStream inputStream = new FileInputStream(“a.txt”);

  1. public FileOutputStream(File file, boolean append)
  2. public FileOutputStream(String name, boolean append)

创建一个FileinputStream对象,并绑定一个数据源文件
如果文件不存在,则会抛出异常(File Not Found Exception)

构造方法实例:

  •   public class FileInputStreamTest1 {
          public static void main(String[] args) throws FileNotFoundException {
              //使用file对象创建流对象
              File file =  new File("D:\\12345\\123.mp4");
              FileInputStream fileInputStream = new FileInputStream(file);
              //使用文件名称创建流对象
              FileInputStream fileInputStreams = new FileInputStream("D:\\12345\\123.mp4");
          }
      }
    
FileInputStream读取字节数据:
  • 1.读取字节:read()方法,每次可以读取一个字节的数据,提升为int类型,读取到文件末尾,返回-1
    • 实例:
          public class FileInputStreamTest2 {
            public static void main(String[] args) throws IOException {
                //使用read()方法,读取一个字节的数据
                //使用文件名称创建流对象
                FileInputStream fileInputStream = new FileInputStream("D:\\12345\\123456.txt");
                int read = fileInputStream.read();
                System.out.println((char)read);
                read = fileInputStream.read();
                System.out.println((char)read);
                read = fileInputStream.read();
                System.out.println((char)read);
                read = fileInputStream.read();
                System.out.println((char)read);//已经读不到数据了
                System.out.println(read);//读取到最后没有信息了会返回-1
                fileInputStream.close();//关闭资源
            }
        }
      
  • 2.使用字节数组读取:***read(byte[] b)***,每次读取b的长度个字节到数组中,返回读取到的有效字节个数,读取到末尾时,返回-1
    • 实例:
        public class FileInputStreamTest3 {
           public static void main(String[] args) throws IOException {
                //使用read(byte[] b)方法,读取数据
                //使用文件名称创建流对象
                FileInputStream fileInputStream = new FileInputStream("D:\\12345\\123456.txt");
                int len;
                byte[] b = new byte[2];
                while ((len=fileInputStream.read(b))!=-1){
                    System.out.println(new String(b));
                }
                fileInputStream.close();//关闭资源
            }
        }
      

字节流OutputStream

概念
  • OutputStream是所有字节输出流的顶层父类,是一个抽象类,如果要用,需要使用子类。 常用的子类FileOutputStream 文件输出流
  • 字节输出流的基本共性功能方法:
    • public void close() :关闭此输出流并释放与此流相关联的任何系统资源。
    • public void flush() :刷新此输出流并强制任何缓冲的输出字节被写出。
    • public void write(byte[] b):将 b.length个字节从指定的字节数组写入此输出流。
    • public void write(byte[] b, int off, int len) :从指定的字节数组写入 len字节,从偏移量 off开始输出到此输出流。 也就是说从off个字节数开始读取一直到len个字节结束
    • public abstract void write(int b) :将指定的字节输出流。

以上五个方法则是字节输出流都具有的方法,由父类OutputStream定义提供,子类都会共享以上方法

FileOutputStream构造方法
  • FileOutputStream​(File file): 传递File类型的文件。
  • FileOutputStream​(String name): 传递一个字符串类型的文件路径。
    推荐下面这种写法

FileOutputStream outputStream = new FileOutputStream(“abc.txt”);

注意:创建输出流对象的时候,系统会自动去对应位置创建对应文件,而创建输出流对象的时候,文件不存在则会报FileNotFoundException异常,也就是系统找不到指定的文件异常。

  • 当你创建一个流对象时,必须直接或者间接传入一个文件路径。在该路径下,如果没有这个文件,会创建该文件。如果有这个文件,会清空这个文件的数据。
    实例:
      public class FileOutputStreamTest1 {
          public static void main(String[] args) throws FileNotFoundException {
              //使用FIle对象创建流对象
              File file = new File("D:\\12345\\123456.txt");
              FileOutputStream fileOutputStream = new FileOutputStream(file);
              //使用文件名创建流对象
              FileOutputStream fileOutputStream2 = new FileOutputStream("D:\\12345\\123456.txt");
      
          }
      }
    
FileOutputStream导出字节数据

使用FileOutputStream写出字节数据主要通过Write方法,而write方法分如下三种:

  • public void write(int b)
  • public void write(byte[] b)
  • public void write(byte[] b,int off,int len) //从off索引开始,len个字节
1.写出字节,write(int b) 方法,每次可以写出一个字节数据

实例:

	class FileOutputStreamTest2 {
	    public static void main(String[] args) throws IOException {
	        //使用FIle对象创建流对象
	        FileOutputStream fos = new FileOutputStream("D:\\12345\\123456.txt");
	        //写出数据
	        fos.write(97);
	        fos.write(98);
	        fos.write(99);
	        fos.close();
	    }
	}

虽然参数为int类型四个字节,但是只会保留一个字节的信息写出。
流操作完毕后,必须释放系统资源,调用close方法,千万记得。

2.写出字节数组 ,write(byte[] b),每次可以写出数组中的数据

实例:

class FileOutputStreamTest3 {
    public static void main(String[] args) throws IOException {
        //使用FIle对象创建流对象
        FileOutputStream fos = new FileOutputStream("D:\\12345\\123456.txt");
        //字符串转换为数组
        byte[] b = "一给我里GIAO".getBytes();
        //写出字节组数据
        fos.write(b);
        //关闭资源
        fos.close();
    }
}
3.写出指定长度字节数组:write(byte[] b, int off, int len) ,每次写出从off索引开始,len个字节

实例:

class FileOutputStreamTest4 {
    public static void main(String[] args) throws IOException {
        //使用FIle对象创建流对象
        FileOutputStream fos = new FileOutputStream("D:\\12345\\123456.txt");
        //字符串转换为数组
        byte[] b = "qwertyuiop".getBytes();
        //写出字节组数据
        fos.write(b,2,2);
        //关闭资源
        fos.close();
    }
}

字节流在这就告一段落了,更深一点的方法也不说了(我也不会,还在学 hhhh~),再说一说字符流:

什么时候用字符流,什么时候用字节流呢?
答案很简单:
如果处理纯文本数据的情况,优先考虑字符流!而处理图片,音频,视频...使用字节流比较好

字符流(Reader,Writer)

Reader字符输入流
  • java.io.Reader抽象类是字符输入流的所有类的超类(父类),可以读取字符信息到内存中。它定义了字符输入流的基本共性功能方法。
FileReader类
  • java.io.FileReader类是读取字符文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区。
构造方法
  • FileReader(File file): 创建一个新的 FileReader ,给定要读取的File对象。
  • FileReader(String fileName): 创建一个新的 FileReader ,给定要读取的文件的字符串名称。

实例:

public class ReaderTest1 {
    public static void main(String[] args) throws FileNotFoundException {
        //使用file对象创建流对象
        File file = new File("D:\\12345\\123456.txt");
        FileReader fileReader = new FileReader(file);
        //使用文件名称创建流对象
        FileReader fileReader1 = new FileReader("D:\\12345\\123456.txt");
    }
}
FileReader读取字符数据
  • 读取字符:read方法,每次可以读取一个字符的数据,提升为int类型,读取到文件末尾,返回-1,循环读取

实例:

public class ReaderTest2 {
    public static void main(String[] args) throws IOException {
        //使用文件名称创建流对象
        FileReader file = new FileReader("D:\\12345\\123456.txt");
        // 定义变量,保存数据
        int b;
        // 循环读取
        while ((b = file.read())!=-1) {
            System.out.println((char)b);
        }
        // 关闭资源
        file.close();
    }
}
Writer字符输出流
  • java.io.Writer抽象类是字符输出流的所有类的超类(父类),将指定的字符信息写出到目的地。它同样定义了字符输出流的基本共性功能方法。
字符输出流的基本共性功能方法:
  • void write(int c) 写入单个字符。
  • void write(char[] cbuf)写入字符数组。
  • abstract void write(char[] cbuf, int off, int len)写入字符数组的某一部分,off数组的开始索引,len写的字符个数。
  • void write(String str)写入字符串。
  • void write(String str, int off, int len) 写入字符串的某一部分,off字符串的开始索引,len写的字符个数。
  • void flush()刷新该流的缓冲。
  • void close() 关闭此流,但要先刷新它。
FileWriter类
  • java.io.FileWriter类是写出字符到文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区。
构造方法
  • FileWriter(File file): 创建一个新的 FileWriter,给定要读取的File对象。
  • FileWriter(String fileName): 创建一个新的 FileWriter,给定要读取的文件的名称。

实例:

public class WriterTest1 {
    public static void main(String[] args) throws IOException {
        //使用file对象创建流对象
        File file = new File("D:\\12345\\123456.txt");
        FileWriter fileWriter = new FileWriter(file);
        //使用文件名称创建流对象
        FileWriter fileWriter2 = new FileWriter("D:\\12345\\123456.txt");
    }
}
写出数据
  • 写出字符:write(int b) 方法,每次可以写出一个字符数据
    public class WriterTest2 {
        public static void main(String[] args) throws IOException {
            //使用文件名称创建流对象
            FileWriter fw = new FileWriter("D:\\12345\\123456.txt");
            //写出数据
            fw.write(97); //写出第一个字符
            fw.write('b');//写出第二个字符
            fw.write('c');//写出第三个字符
    
            //关闭资源时,与FileOutputStream不同。 如果不关闭,数据只是保存到缓冲区,并未保存到文件
            fw.close();
        }
    }
    

关闭资源时,与FileOutputStream不同。 如果不关闭,数据只是保存到缓冲区,并未保存到文件

关闭close和刷新flush
  • 因为内置缓冲区的原因,如果不关闭输出流,无法写出字符到文件中。但是关闭的流对象,是无法继续写出数据的。如果我们既想写出数据,又想继续使用流,就需要flush 方法了。
  • flush :刷新缓冲区,流对象可以继续使用。
  • close:先刷新缓冲区,然后通知系统释放资源。流对象不可以再被使用了。
    实例:
    public class WriterTest3 {
        public static void main(String[] args) throws IOException {
            //源   也就是输入流【读取流】 读取a.txt文件
            FileReader fr=new FileReader("D:\\12345\\123456.txt");  //必须要存在123456.txt文件,否则报FileNotFoundException异常
            //目的地  也就是输出流
            FileWriter fw=new FileWriter("D:\\12345\\123.txt");  //系统会自动创建123.txt,因为它是输出流!
            int len;
            while((len=fr.read())!=-1){
                fw.write(len);
            }
            fr.close();
            fw.flush();
            fw.close();
        }
    }
    

IO流中的压缩

  • 压缩压缩,肯定是将数据压缩成压缩包,这就是输出流.因为不确定数据是什么类型,纯文本啊,还是音视频之类的.所以建议直接就写成字节流
  • 实例:
      public class ZipTest1 {
          public static void main(String[] args) throws Exception {
          	//使用文件名称创建流对象
              FileOutputStream fos = new FileOutputStream("D:\\12345\\123456789.zip") ;
              ZipOutputStream zos= new ZipOutputStream(fos) ;
              //写入一个条目,我们需要给这个条目起个名字,相当于起一个文件名称
              zos.putNextEntry(new ZipEntry("qwe"));
              //往这个条目中写入一定的数据
              zos.write("QQQ".getBytes());
              //关闭条目
              zos.closeEntry();
      
              zos.putNextEntry(new ZipEntry("asd"));
              zos.write("WWW".getBytes());
              zos.closeEntry();
      
              zos.putNextEntry(new ZipEntry("zxc"));
              zos.write("EEE".getBytes());
              zos.closeEntry();
              zos.close();
          }
      }
    
  • 解压!
      public class UnZipTest {
          public static void main(String[] args) throws Exception {
              FileInputStream fis = new FileInputStream("D:\\12345\\123456789.zip");
              ZipInputStream zis = new ZipInputStream(fis);
              ZipEntry entry = null ;
              byte[] buf = new byte[1024] ;
              int len = 0 ;
              //此处我们需要判断是否zis流中存在条目,你可以理解为是否存在文件内容
              while((entry = zis.getNextEntry()) != null){
                  //此处我们获取条目名称
                  String name = entry.getName();
                  System.out.println(name);
                  //我们将每一个条目进行解压,我们需要指定一个输出路径
                  FileOutputStream fos = new FileOutputStream("D:\\12345\\"+ name) ;
                  while((len = zis.read(buf)) != -1){
                      fos.write(buf , 0 , len);
                  }
                  fos.close();
              }
              zis.close();
              fis.close();
          }
      }
    

IO流的转换

编码

  • InputStreamReader 继承于Reader,是字节流通向字符流的桥梁,可以把字节流按照指定编码 解码 成字符流。

实例:

public class InputStreamReaderTest {
    public static void main(String[] args) throws IOException {
        File file = new File("D:\\12345\\123456.txt");
        String haha="i like you too";
        //1.创建通道
        FileOutputStream fileOutputStream=new FileOutputStream(file);
        //2.创建转换流
        OutputStreamWriter writer=new OutputStreamWriter(fileOutputStream,"UTF-8");
        //3.写入数据
        writer.write(haha);
        //4.刷新缓冲区
        writer.flush();
        //5.关闭通道
        writer.close();
        //6.关闭转换流
        fileOutputStream.close();
    }
}

解码

  • InputStreamReader 继承于Reader,是字节流通向字符流的桥梁,可以把字节流按照指定编码 解码 成字符流。

实例:

public class InputStreamWriter {
    public static void main(String[] args) throws IOException {
        File file = new File("D:\\12345\\123456.txt");
        FileInputStream fileInputStream = new FileInputStream(file);
        InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream,"UTF-8");
        char[] cbuf=new char[2];
        int len;
        StringBuilder sb=new StringBuilder();
        while((len=inputStreamReader.read(cbuf))!=-1){
            sb.append(cbuf, 0, len);
        }
        System.out.println(sb.toString());
    }
}

本节完
文中借鉴内容摘抄自:
https://www.cnblogs.com/yichunguo/p/11775270.html
https://www.cnblogs.com/luojack/p/10823365.html

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Java面经是指在面试过程中常被问到的与Java相关的问题和知识点。下面是一些常见的Java面经问题及其解答: 1. Java的特点是什么? Java是一种面向对象的编程语言,具有跨平台性、简单性、可靠性、安全性和高性能等特点。 2. 什么是Java虚拟机(JVM)? JVM是Java程序运行的环境,它负责将Java源代码编译成字节码,并在不同的操作系统上执行。 3. 什么是面向对象编程(OOP)? 面向对象编程是一种编程范式,它将数据和操作数据的方法封装在一起,通过创建对象来实现程序的功能。 4. Java中的四种访问修饰符分别是什么? Java中的四种访问修饰符分别是public、protected、default和private,用于控制类、方法和变量的访问权限。 5. 什么是Java中的异常处理机制? 异常处理机制是Java中用于处理程序运行过程中出现的异常情况的一种机制,通过try-catch-finally语句块来捕获和处理异常。 6. 什么是Java中的多线程? 多线程是指在一个程序中同时执行多个线程,每个线程都可以独立执行不同的任务,提高程序的并发性和效率。 7. 什么是Java中的集合框架? 集合框架是Java中用于存储和操作一组对象的类库,包括List、Set、Map等常用的数据结构和算法。 8. 什么是Java中的反射机制? 反射机制是指在运行时动态地获取和操作类的信息,可以通过反射来创建对象、调用方法和访问属性等。 9. 什么是Java中的IO流IO流Java中用于输入和输出数据的一种机制,包括字节流和字符流,用于读取和写入文件、网络等数据源。 10. 什么是Java中的设计模式? 设计模式是一种解决常见软件设计问题的经验总结,包括单例模式、工厂模式、观察者模式等常用的设计模式。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值