学习笔记08--JavaIO流

File

File类概述和构造方法

  • File:它是文件和目录路径名的抽象表示

    • 文件和目录是可以通过File封装成对象的
    • 对于File而言,其封装的并不是一个真正存在的文件,仅仅是一个路径名而已。它可以是存在的,也可以是不存在的。将来是要通过具体的操作把这个路径的内容转换为具体存在的
  • 绝对路径和相对路径

    • 绝对路径:完整的路径名,不需要任何其他信息就可以定位它所表示的文件。例如:G:\\文件\\java.txt
    • 相对路径:必须使用取自其他路径名的信息进行解释。例如:myFile\\java.txt
  • 构造方法

    • File(String pathname):通过将给定的路径名字符串转换为抽象路径名来创建新的File实例
    • File(String parent,String child):从父路径名字符串和子路径名字符串创建新的File实例
    • File(File parent,Stringn child):从父抽象路径名和子路径名字符串创建新的File实例
public static void main(String[] args) {
    //File(String pathname):通过将给定的路径名字符串转换为抽象路径名来创建新的File实例
    File file = new File("G:\\一些文件\\新建文件夹");
    System.out.println(file);

    //File(String parent,String child):从父路径名字符串和子路径名字符串创建新的File实例
    File file1 = new File("G:\\一些文件","新建文件夹");
    System.out.println(file1);

    //File(File parent,Stringn child):从父抽象路径名和子路径名字符串创建新的File实例
    File file2 = new File("G:\\一些文件");
    File file3 = new File(file2,"新建文件夹");
    System.out.println(file3);
}
  • File类创建功能
    • public boolean createNewFile():当具有该名称的文件不存在时,创建一个由该抽象路径名命名的新空文件,并返回true,如果文件存在则返回false
    • public boolean mkdir():创建由此抽象路径名命名的目录
    • public boolean mkdirs():创建由此抽象路径名命名的目录,包括任何必需但不存在的父目录
  • File类删除功能
    • public boolean delete():删除由此抽象路径名表示的文件或目录
    • 删除目录时,如果目录下还有其他文件,则该目录不能直接删除,要先删除其内容,再删除目录
public static void main(String[] args) throws IOException {
    //需求1:在G:\\一些文件\\新建文件夹目录下创建一个文件java.txt
    File file = new File("G:\\一些文件\\新建文件夹\\java.txt");
    System.out.println(file.createNewFile());

    //需求2:在G:\\一些文件\\新建文件夹下创建一个目录JavaSE
    File file1 = new File("G:\\一些文件\\新建文件夹\\JavaSE");
    System.out.println(file1.mkdir());

    //需求3:在G:\\一些文件\\新建文件夹下创建一个多级目录JavaWeb\\html
    File file2 = new File("G:\\一些文件\\新建文件夹\\JavaWeb\\html");
    System.out.println(file2.mkdirs());

    //需求4:在G:\\一些文件\\新建文件夹目录下创建一个文件javase.txt
    File file3 = new File("G:\\一些文件\\新建文件夹\\javase.txt");
    //这样会导致生成一个名为javase.txt的文件夹
    //System.out.println(file3.mkdir());
    System.out.println(file3.createNewFile());
    
    //需求5:在G:\\一些文件\\新建文件夹目录下删除javase.txt文件
    System.out.println(file3.delete());
    
    //需求6:在G:\\一些文件\\新建文件夹目录下删除javaSE目录
    System.out.println(file1.delete());    
}
  • File类判断和获取功能
    • public boolean isDirectory():测试此抽象路径名表示的File是否为目录
    • public boolean isFile():测试此抽象路径名表示的File是否为文件
    • public boolean exists():测试此抽象路径名表示的File是否存在
    • public String getAbsolutePath():返回此抽象路径名的绝对路径名字符串
    • public String getPath():将此抽象路径名转换为路径名字符串
    • public String getName():返回由此抽象路径名表示的文件或目录的名称
    • public String[] list():返回此抽象路径名表示的目录中的文件和目录的名称字符串数组
    • public File[] listFiles():返回此抽象路径名表示的目录中的文件和目录的File对象数组
public static void main(String[] args) {
    File file = new File("G:\\一些文件\\新建文件夹\\java.txt");

    //public boolean isDirectory():测试此抽象路径名表示的File是否为目录
    System.out.println(file.isDirectory());
    //public boolean isFile():测试此抽象路径名表示的File是否为文件
    System.out.println(file.isFile());
    //public boolean exists():测试此抽象路径名表示的File是否存在
    System.out.println(file.exists());
    //public String getAbsolutePath():返回此抽象路径名的绝对路径名字符串
    System.out.println(file.getAbsolutePath());
    //public String getPath():将此抽象路径名转换为路径名字符串
    System.out.println(file.getPath());
    //public String getName():返回由此抽象路径名表示的文件或目录的名称
    System.out.println(file.getName());
    System.out.println("===========================");

    File file1 = new File("G:\\一些文件\\新建文件夹");
    //public String[] list():返回此抽象路径名表示的目录中的文件和目录的名称字符串数组
    String[] strings = file1.list();
    for (String s:strings){
        System.out.println(s);
    }

    //public File[] listFiles():返回此抽象路径名表示的目录中的文件和目录的File对象数组
    File[] files = file1.listFiles();
    for (File f:files){
        System.out.println(f);
    }
}

字节流

IO流概述和分类

  • IO流概述:

    • IO:输入/输出(Input/Output)
    • 流:是一种抽象概念,是对数据传输的总称。也就是说数据在设备间的传输成为流,流的本质是数据传输
    • IO流就是用来处理设备间数据传输问题的
      • 常见的应用:文件复制,文件上传、下载
  • IO流分类:

    • 按照数据的流向
      • 输入流:读数据
      • 输出流:写数据
    • 按照数据类型
      • 字节流:字节输入流,字节输出流
      • 字符流:字符输入流,字符输出流
  • 一般来说,IO流的分类是按照数据类型来分的,如果可以通过Windows自带的记事本软件打开,还可以读懂里面的内容,就使用字符流,否则使用字节流,如果不知道该用哪种类型,就使用字节流

字节流写数据

  • 字节流抽象基类
    • InputStream:这个抽象类是表示字节输入流的所有类的超类
    • OutputStream:这个抽象类是表示字节输出流的所有类的超类
    • 子类名特点:子类名称都是以其父类名作为子类名的后缀
  • FileOutputStream:文件输出流用于将数据写入File
    • FileOutputStream(String name):创建文件输出流以指定的名称写入文件
  • 使用字节输出流写数据的步骤
    • 创建字节输出流对象(调用系统功能创建了文件,创建字节输出流对象,让字节输出流对象指向文件)
    • 调用字节输出流对象的写数据方法
    • 释放资源(关闭此文件输出流并释放与此流相关联的任何系统资源)
  • 字节流写数据的三种方式
    • void write(int b):将指定的字节写入此文件输出流,一次写一个字节数据
    • void write(byte[] b):将b.length字节从指定的字节数组写入此文件输出流,一次写一个字节数组数据
    • void write(byte[] b,int off,int len):将len字节从指定的字节数组开始,从偏移量off开始写入此文件输出流,一次写一个字节数组的部分数据
public static void main(String[] args) throws IOException {
    FileOutputStream fos = new FileOutputStream("fos.txt");
    //void write(int b):将指定的字节写入此文件输出流,一次写一个字节数据
    fos.write(97);
    fos.write(98);
    fos.write(99);
    fos.write(100);
    fos.write(101);
    
    //void write(byte[] b):将b.length字节从指定的字节数组写入此文件输出流,一次写一个字节数组数据
    byte[] bytes = {97,98,99,100,101};
    fos.write(bytes);

    //void write(byte[] b,int off,int len):将len字节从指定的字节数组开始,从偏移量off开始写入此文件输出流,一次写一个字节数组的部分数据
    fos.write(bytes,2,2);
    
    //释放资源
    fos.close();
}
  • 字符流写数据如何实现换行?
    • 写完数据后,加上换行符
  • 字节流写数据如何实现追加写入呢?
    • public FileOutputStream(String name,boolean append)
    • 创建文件输出流以指定的名称写入文件。如果第二个参数为true,则字节将写入文件的末尾而不是开头
    public static void main(String[] args) throws IOException {
        //创建字节输出流对象
        FileOutputStream fos = new FileOutputStream("fos.txt",true);
        //写数据
        for (int i = 0; i < 10;i++){
            fos.write("hello\n".getBytes());
        }
        //释放资源
        fos.close();
    }

字节流读数据

  • FileInputStream:从文件系统中的文件获取输入字节
    • FileInputStream(String name):通过打开与实际文件的连接来创建一个FileInputStream,该文件由文件系统中的路径名name命名
  • 使用字节输入流读数据的步骤
    • 创建字节输入流对象
    • 调用字节输入流的读数据方法
    • 释放资源
public static void main(String[] args) throws IOException {
    //创建字节输入流对象
    FileInputStream fis = new FileInputStream("fos.txt");

    //调用字节输入流的读数据方法
    int by;
    while ((by = fis.read()) != -1) {//用于判断文件是否结束,如果到达文件的末尾,read()返回值为-1,
        System.out.print((char) by);
    }

    //释放资源
    fis.close();
}
  • 一次读取一个字节数组
public static void main(String[] args) throws IOException {
    //创建字节输入流对象
    FileInputStream fis = new FileInputStream("fos.txt");
    //创建一个数组
    byte[] bytes = new byte[1024];

    int len;//实际读取数据的个数
    while ((len=fis.read(bytes))!=-1){
        System.out.println(new String(bytes,0,len));
    }
    //释放资源
    fis.close();
}

字节缓冲流

  • 字节缓冲流
    • BufferedOutputStream:该类实现缓冲输出流。通过设置这样的输出流,应用程序可以向底层输出流写入字节,而不必为写入的每个字节导致底层系统的调用
    • BufferedInputStream:创建BufferedInputStream将创建一个内部缓冲区数组。当从流中读取或跳过字节时,内部缓冲区将根据需要从所包含的输入流中重新填充,一次很多字节
    • 字节缓冲流仅仅提供缓冲区,而真正的读写数据还得依靠基本的字节流对象进行操作
  • 构造方法:
    • 字节缓冲输出流:BufferedOutputStream(OutputStream out)
    • 字节缓冲输入流:BufferedInputStream(IntputStream in)
//需求:把 G:\一些文件\新建文件夹\测试.mkv 这个视频复制到模块目录下
//要求:用四种方法实现,并且记录时间
public class CopyVideoDemo {
    public static void main(String[] args) throws IOException {
        long startTime = System.currentTimeMillis();
        //method1();
        //method2();
        //method3();
        method4();
        long endTime = System.currentTimeMillis();
        System.out.println("花费时间为:" + (endTime - startTime));
    }

	//基本字节流一次读写一个字节              花费时间为:104675
    public static void method1() throws IOException {
        FileInputStream fis = new FileInputStream("G:\\一些文件\\新建文件夹\\测试.mkv");
        FileOutputStream fos = new FileOutputStream("测试副本.mkv");
        int len;
        while ((len = fis.read()) != -1) {
            fos.write(len);
        }
        fis.close();
        fos.close();
    }

    //基本字节流一次读写一个字节数组           花费时间为:140
    public static void method2() throws IOException {
        FileInputStream fis = new FileInputStream("G:\\一些文件\\新建文件夹\\测试.mkv");
        FileOutputStream fos = new FileOutputStream("测试副本.mkv");
        int len;
        byte[] bytes = new byte[1024];
        while ((len = fis.read(bytes)) != -1) {
            fos.write(bytes, 0, len);
        }
        fis.close();
        fos.close();
    }

    //字节缓冲流一次读写一个字节              花费时间为:504
    public static void method3() throws IOException {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("G:\\一些文件\\新建文件夹\\测试.mkv"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("测试副本.mkv"));
        int len;
        while ((len = bis.read()) != -1) {
            bos.write(len);
        }
        bis.close();
        bos.close();
    }

    //字节缓冲流一次读写一个字节数组           花费时间为:36
    public static void method4() throws IOException {
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("G:\\一些文件\\新建文件夹\\测试.mkv"));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("测试副本.mkv"));
        int len;
        byte[] bytes = new byte[1024];
        while ((len = bis.read(bytes)) != -1) {
            bos.write(bytes, 0, len);
        }
        bis.close();
        bos.close();
    }
}

字符流

  • 由于字节流操作中文不是特别方便,所以Java提供了字符流
  • 字符流 = 字节流 + 编码表
  • 汉字在存储的时候,无论选择哪种编码存储,第一个字节都是负数

字符串中的编码解码问题

  • 编码:
    • byte[] getBytes():使用平台默认字符集将该String编码为一系列字节,将结果存储到新的字节数组中
    • byte[] getBytes(String charsetName):使用指定的字符集将该String编码为一系列字节,将结果存储到新的字节数组中
  • 解码:
    • String(byte[] bytes):通过使用平台的默认字符集解码指定的字节数组来构造新的String
    • String(byte[] bytes,String charsetName):通过指定的字符集解码指定的字节数组来构造新的String
public static void main(String[] args) throws UnsupportedEncodingException {
    //定义一个字符串
    String s ="中国";
    //编码
    byte[] bytes = s.getBytes("UTF-8");
    System.out.println(Arrays.toString(bytes));//[-28, -72, -83, -27, -101, -67]
    //解码
    String s1 = new String(bytes,"UTF-8");
    System.out.println(s1);//中国
}

字符流中的编码解码问题

  • 字符流抽象基类

    • Reader:字符输入流的抽象类
    • Writer:字符输出流的抽象类
  • 字符流中和编码解码问题相关的两个类

    • InputStreamReader
    • OutputStreamWriter
  • 字符流写数据的五种方法

    • void write(int c):写一个字符
    • void write(char[] cbuf):写一个字符数组
    • void write(char[] cbuf,int off,int len):写一个字符数组的一部分
    • void write(String str):写一个字符串
    • void write(String str,int off,int len):写一个字符串的一部分
public static void main(String[] args) throws IOException {
    OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("osw.txt"));

    //void write(int c):写一个字符
    osw.write(97);
    osw.write(98);
    osw.flush();//用来刷新流
    osw.write(99);

    //void write(char[] cbuf):写一个字符数组
    char[] chars ={'我','爱','你','中','国','\n'};
    osw.write(chars);

    //void write(char[] cbuf,int off,int len):写一个字符数组的一部分
    osw.write(chars,1,2);.

    //void write(String str):写一个字符串
    osw.write("富强民主\n");

    //void write(String str,int off,int len):写一个字符串的一部分
    osw.write("我爱你中国",2,2);
    osw.close();//关闭流,释放资源
}
  • 字符流读数据的两种方法
    • int read():一次读一个字符数据
    • int read(char[] cbuf):一次读一个字符数组数据
public static void main(String[] args) throws IOException {
    InputStreamReader isr = new InputStreamReader(new FileInputStream("isr.txt"));

    //int read():一次读一个字符数据
/*  int ch;
    while ((ch = isr.read()) != -1) {
        System.out.print((char) ch);
    }
*/
    //int read(char[] cbuf):一次读一个字符数组数据
    char[] chars = new char[1024];
    int len;
    while ((len = isr.read(chars)) != -1) {
        System.out.print(new String(chars, 0, len));
    }

    isr.close();
}
  • 常用功能
    • flush():刷新流,还可以继续写数据
    • close():关闭流,释放资源,但是关闭之前会先刷新流。一旦关闭,就不能再写数据

字符缓冲流

  • 字符缓冲流
    • BufferedWriter:将文本写入字符输出流,缓冲字符,以提供单个字符,数组和字符串的高效写入,可以指定缓冲区大小,或者可以接受默认大小,默认值足够大,可用于大多数用途
    • BufferedWriter:从字符输出流读取文本,缓冲字符,以提供字符,数组和行的高效读取,可以指定缓冲区大小,或者可以使用默认大小,默认值足够大,可用于大多数用途
  • 构造方法
    • BufferedWriter(Writer out):
    • BufferedReader(Reader in):
public static void main(String[] args) throws IOException {
   //创建字符缓冲输出流
    BufferedWriter bw = new BufferedWriter(new FileWriter("bs.txt"));
    bw.write("hello\n");
    bw.write("world\n");
    bw.close();
    
	//创建字符缓冲输入流
    BufferedReader br = new BufferedReader(new FileReader("bs.txt"));
//        int ch;
//        while ((ch = br.read()) != -1) {
//            System.out.print((char) ch);
//        }
    int len;
    char[] chars = new char[1024];
    while ((len = br.read(chars)) != -1) {
        System.out.print(new String(chars, 0, len));
    }

    br.close();
}
  • 字符缓冲流特有功能
    • BufferedWriter:
      • void newLine():写一行行分隔符,行分隔符字符串由系统属性定义
    • BufferedReader:
      • public String readLine():读一行文字。结果包含行的内容的字符串,不包括任何行终止字符,如果流的结尾已经到达,则为null

标准输入输出流

  • System类中有两个静态的成员变量:
    • public static final InputStream in:标准输入流。通常该流对应于键盘输入或由主机环境或用户指定的另一个输入源
    • public static final PrintStream out:标准输出流。通常该留对应于显示输出或由主机环境或用户指定的另一个输出目标
  • 自己实现键盘录入数据:
    • BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
  • 因为太过麻烦,所以Java就提供了一个类实现键盘录入
    • Scanner sc = new Scanner(System.in);
  • 输出语句的本质:是一个标准的输出流
    • PrintStream ps = System.out;
    • PrintStream类有的方法,System.out都可以使用

打印流

  • 打印流分类:
    • 字节打印流:PrintStream
      • PrintStream(String fileName):使用指定的文件名创建新的打印流
      • 使用继承父类的方法写数据,查看的时候会转码;使用自己的特有方法写数据,查看的数据原样输出
    • 字符打印流:PrintWriter
      • PrintWriter(String fileName):使用指定的文件名创建一个新的PrintWriter,而不需要自动执行刷新
      • PrintWriter(Writer out,boolean autoFlush):创建一个新的PrintWriter,out:字符输出流,autoFlush:一个布尔值,如果为真,则println,printf,或format方法将刷新输出缓冲区
  • 打印流的特点:
    • 只负责输出数据,不负责读取数据
    • 有自己的特有方法

对象序列化流

  • 对象序列化:就是将对象保存到磁盘中,或者在网络中传输对象
  • 这种极致就是使用一个字节序列表示一个对象,该字节序列包含:对象的类型、对象的数据和对象中存储的属性等信息,字节序列写到文件之后,相当于文件中持久保存了一个对象的信息
  • 反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化
  • 对象序列化流:ObjectOutputStream
    • 构造方法:ObjectOutputStream(OutputStream out):创建一个写入指定的OutputStream的ObjectOutputStream
    • 序列化对象的方法:将指定的对象写入ObjectOutputStream
    • 一个对象想要被序列化,该对象所属的类必须实现Serializable接口
    • Serializable是一个标记接口,实现该接口,不需要重写任何方法
public static void main(String[] args) throws IOException {
    //创建一个能写入指定OutputStream的ObjectOutputStream
    ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("fos.txt"));

    //创建对象
    Student s = new Student("张三",80);

    //将指定的对象写入ObjectOutputStream
    oos.writeObject(s);

    //释放资源
    oos.close();
}
  • 对象反序列化流:ObjectItputStream

    • 构造方法:ObjectItputStream(InputStream in):创建从指定的InputStream读取的ObjectInputStream
    • 反序列化对象的方法:Object readObject():从ObjectInputStream读取一个对象
  • 关于对象序列化流的问题

    • 用对象序列化流序列化了一个对象后,假如我们修改了对象所属的类文件,读取数据会抛出一个InvalidClassException异常
    • 这个问题可以通过给对象所属的类加一个serialVersionUID来解决,如:private static final long serialVersionUID = 42L;
    • 如果一个对象中的某个成员变量的值不想被序列化,那么可以给该成员变量加transient关键字修饰,该关键字标记的成员变量不参与序列化过程

Properties

  • Properties概述:
    • 是一个Map体系的集合类
    • Properties可以保存到流中或从流中加载
public static void main(String[] args) {
    //创建集合对象
    Properties prop = new Properties();

    //存储元素
    prop.put("21","tian");
    prop.put("22","uzi");
    prop.put("23","faker");

    //遍历集合
    Set<Object> keySet = prop.keySet();
    for (Object key:keySet){
        Object value = prop.get(key);
        System.out.println(key + "," + value);
    }
}
  • Properties作为集合的特有方法:
    • Object setProperty(String key,String value):设置集合的键和值,都是String类型,底层调用Hashtable方法put
    • String getProperty(String key):使用此属性列表中指定的键搜索属性,键不存在则返回null
    • Set stringPropertyNames():从该属性列表中返回一个不可修改的键集,其中键及其对应的值是字符串
public static void main(String[] args) {
    //创建集合对象
    Properties prop = new Properties();

    //Object setProperty(String key,String value):设置集合的键和值,都是String类型,底层调用Hashtable方法put
    prop.setProperty("22", "tian");
    prop.setProperty("21", "369");
    prop.setProperty("25", "faker");

    //String getProperty(String key):使用此属性列表中指定的键搜索属性,键不存在则返回null
    //Set<String> stringPropertyNames():从该属性列表中返回一个不可修改的键集,其中键及其对应的值是字符串
    Set<String> keySet = prop.stringPropertyNames();
    for (String key : keySet) {
        String value = prop.getProperty(key);
        System.out.println(key + "," + value);
    }
}
  • Properties和IO流结合的方法
    • void load(InputStream inStream):从输入字节流读取属性列表(键和元素对)
    • void load(Reader reader):从输入字符流读取属性列表(键和元素对)
    • void store(OutputStream out,String comments):将此属性列表(键和元素对)写入此Properties表中,以适合于使用load(InputStream)方式的格式写入输出字节流
    • void store(Writer writer,String comments):将此属性列表(键和元素对)写入此Properties表中,以适合于使用load(Reader)方式的格式写入输出字符流
public static void main(String[] args) throws IOException {
    //把集合中的数据保存到文件
    propertiesToFile();
    //把文件中的数据加载到集合
    fileToProperties();
}

private static void fileToProperties() throws IOException {
    Properties prop = new Properties();

    FileReader fr = new FileReader("fos.txt");
    //void load(Reader reader):从输入字符流读取属性列表(键和元素对)
    prop.load(fr);
    fr.close();

    System.out.println(prop);
}

private static void propertiesToFile() throws IOException {
    Properties prop = new Properties();

    prop.setProperty("25","imp");
    prop.setProperty("26","duke");
    prop.setProperty("27","bang");

    FileWriter fw = new FileWriter("fos.txt");
    //void store(Writer writer,String comments):将此属性列表(键和元素对)写入此Properties表中,以适合于使用load(Reader)方式的格式写入输出字符流
    prop.store(fw,null);
    fw.close();
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值