【程序员养成之路】Java基础篇 7-流进流出的IO流(一)

以下内容若有误,欢迎私信我或在下方留言,谢谢^_−


IO流(一)

1.File类

1.1 File类概述

File是以抽象的方式代表文件名和目录路径名,文件和目录能够通过File封装成对象。该类主要用于文件和目录的创建、文件的查找和文件的删除等。

1.2 File类常用方法
(1)创建功能
方法名说明
boolean createNewFile()若该名称的文件不存在,则创建新文件(以该抽象路径名命名)
boolean mkdir()创建目录
boolean mkdirs()多级创建目录
(2)判断和获取功能
方法名说明
boolean isDirectory()判断是否为目录
boolean isFile()判断是否为文件
boolean exists()判断是否存在该文件
String getAbsolutePath()返回该抽象路径名对应的绝对路径字符串
String getPath()将该抽象路径名转换为路径名字符串
String getName()返回文件或目录的名称
String[] list()获取该路径下的文件和目录(仅仅获得名称)
File[] listFiles()获取该路径下的文件和目录(获得绝对路径)
(3)删除功能
方法名说明
boolean delete()删除文件或目录

注意:删除目录时,若目录中有内容,则需先删除内容再删除目录,不能直接删除含有内容的目录。

绝对路径:完整描述文件所在位置的路径,不需要借助任何信息即可定位到。比如C:\Program Files\Microsoft Office\FileSystemMetadata.xml
相对路径:顾名思义,就是相对于其它位置来说的路径,必须借助其他路径的信息才能准确定位到。比如Microsoft Office\FileSystemMetadata.xml
个人理解:可以通过地理位置理解,比如说腾讯深圳总部的绝对路径是中华人民共和国广东省深圳市南山区海天二路33号腾讯滨海大厦,而相对路径则可以是南山区海天二路33号腾讯滨海大厦

2.IO流

2.1 概述

IO即输入/输出(Input/Output),而“流”则是一种抽象概念,是对数据传输的总称,即数据在设备间的传输称为流。IO流就是用来处理设备间数据传输问题的,比如文件复制、上传、下载等。

2.2 分类

(1)按照数据流向来分

  • 输入流:读数据
  • 输出流:写数据

(2)按照数据类型来分

  • 字节流
  • 字符流

(3)按功能来分

  • 节点流
  • 缓冲流/处理流/包装流

在这里插入图片描述

什么情况下使用这两种流?
将文件通过windows自带的记事本打开,若能够正常显示内容,则使用字符流,否则使用字节流。若不清楚使用哪种流,就使用字节流,因为任何数据的底层说到底还是字节。

3.字节流

3.1 字节输入/输出流

内容全在代码里了,认真看完,相信总能有所收获~

public class ByteStreamDemo {
    public static void main(String[] args) throws Exception {
        /*
         FileOutputStream(String name, boolean append)
              创建文件输出流以写入由指定的File对象表示的文件(即创建输出流,并指定写入的文件)。
              第二个参数可以不写,默认为false。
              若需要将字节写入文件的末尾(追加写入),则需添加并改为true。
         */
        FileOutputStream fos = new FileOutputStream("test.txt");
        /*
         字节输入流写输入的三种方式:
             1.void write(int b)
                  将指定的字节写入此文件输出流(单个写入)。
             2.void write(byte[] b)
                  将b.length个字节从指定的字节数组写入此文件输出流(多个写入)。
             3.void write(byte[] b, int off, int len)
                  将len字节从位于偏移量off的指定字节数组写入此文件输出流(指定量写入)。
         
         public byte[] getBytes()
              使用平台的默认字符集将此String编码为字节序列,将结果存储到新的字节数组中(字符串→字节数组)。
         
         字节流写数据实现换行:
              通过getBytes()方法将“\r\n”转换为字节数组并写入文件
         */
        fos.write('a');                   // 第一种方式
        byte[] b = {'b', 'c', 'd', 'e'};
        fos.write(b);                       // 第二种方式
        fos.write(b, 0, b.length);      // 第二种方式
        fos.write("\r\n".getBytes());       // 实现换行

        /*
         FileInputStream(String name)
              通过打开与实际文件的连接来创建一个FileInputStream,
              该文件由文件系统中的路径名name命名(即创建输入流,并指定读取的文件)。
         */
        FileInputStream fis = new FileInputStream("test.txt");

        /*
         字节输出流读输出的三种方式(如果达到文件末尾,返回-1):
             1.int read()
                  从该输入流读取一个字节的数据(单个读取)。
             2.int read(byte[] b)
                  从该输入流读取最多b.length个字节的数据为字节数组(多个读取)。
             3.int read(byte[] b, int off, int len)
                  从该输入流读取最多len字节的数据为字节数组(指定量读取)。
         */

        // 第一种方式
        int res = fis.read();       // 返回int类型,即读取到其实是数据的ASCII码
        System.out.println(res);    // 97

        /*
            采用第一种方式读取文件全部内容,方法如下:
                int by;
                while((by = fis.read()) != -1){
                    System.out.print((char)by);
                }
            解释:
                fis.read():读取数据
                by = fis.read():赋值给by
                by != -1:判断是否到达文件末尾
         */

        // 第二种方式
        byte[] bys = new byte[4];
        fis.read(bys);   // 获取相应长度的数据
        System.out.println(new String(bys));    // bcde

        // 第三种方式
        fis.read(bys, 0, bys.length);
        System.out.println(new String(bys));     // bcde

        /*
            public String(byte[] bytes, int offset, int length)
                通过使用平台的默认字符集解码指定的字节子阵列来构造新的String(字节数组→字符串)。

            采用第二、三种方式读取文件全部内容,方法如下:
                byte[] bytes = new byte[1024];      // 一般为1024或1024的整数倍
                int len;
                while ((len = fis.read(bytes)) != -1) {
                    System.out.println(new String(bytes, 0, len));
                }
         */

        // 释放资源
        fis.close();
        fos.close();
    }
}
3.2 字节缓冲流

(1)概述

字节缓冲流分为BufferedOutputStreamBufferedInputStream两种,相较于字节流,字节缓冲流具有更高的传输效率其本质原理大概就是不像字节流那样一个一个字节输出、一个一个字节读入,而是攒到一定量(取决于缓冲区大小)后一次性输出或读入,这样就大大减少了对底层系统的调用。

(2)构造方法

  • 字节缓冲输出流:BufferedOutputStream(OutputStream out)
  • 字节缓冲输入流:BufferedInputStream(InputStream in)

为什么构造方法的参数是字节流,而不是具体的路径或文件?
字节缓冲流仅仅提供了缓冲区,而真正的读写操作还是需要基本的字节流对象进行操作。

4.字符流

4.1 字符流的出现
  • 字符流由字节流编码表组成,目的是为了方便对中文的操作
  • 有的人便会问,用字节流复制文本文件(比如.txt)时,里面不也有中文,但是却毫无问题,这是为什么?这是因为在底层对数据进行操作时,会自动将字节拼接成中文
  • 那么,如何识别中文?为了能够准确识别出是中文,各编码存储格式都对汉字的第一个字节进行了设置,即设置第一个字节为负数
public class CodeFormatDemo {
    public static void main(String[] args) throws Exception {
        String s1 = "java";
        String s2 = "爪哇";
        byte[] bys1 = s1.getBytes();
        byte[] bys2 = s2.getBytes();
        byte[] bys3 = s2.getBytes("UTF-8");
        byte[] bys4 = s2.getBytes("GBK");
        System.out.println(Arrays.toString(bys1));
        System.out.println(Arrays.toString(bys2));
        System.out.println(Arrays.toString(bys3));
        System.out.println(Arrays.toString(bys4));
        /*
          输出结果:
            [106, 97, 118, 97]
            [-25, -120, -86, -27, -109, -121]
            [-25, -120, -86, -27, -109, -121]
            [-41, -90, -51, -37]
         */
    }
}

不同的编码格式,汉字所占用的字节不同,GBK占用两个字节,UTF-8占用三个字节。

4.2 字符流中的读写方法
public class CharStreamDemo {
    public static void main(String[] args) throws IOException {
        /*
            字符流写数据的方式:
                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) 写一个字符串的一部分。
                void flush() 刷新流,将缓冲区中的数据存入文件。
                void close() 关闭流,关闭之前先刷新再释放资源,调用之后将无法写入数据。

            字符流读数据的方式:
                int read() 读一个字符。
                int read(char[] cbuf) 将字符读入数组。
         */
        // 创建字符输出流对象
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("test.txt"));
        // 创建字符输入流对象
        InputStreamReader isr = new InputStreamReader(new FileInputStream("test.txt"));

        // void write(int c) 写一个字符
        osw.write(73);
        // void write(char[] cbuf) 写入一个字符数组
        char[] chars = {' ', 'l', 'o', 'v', 'e'};
        osw.write(chars);
        // void write(char[] cbuf, int off, int len) 写入字符数组的一部分(字符数组,起始下标,写入长度)
        osw.write(chars, 0, 1);
        // void write(String str) 写入一个字符串
        osw.write("java");
        // 刷新流
        osw.flush();
        // int read() 读一个字符
        int ch;
        while ((ch = isr.read()) != -1) {
            System.out.print((char)ch);         // I love java
        }

        // void write(String str, int off, int len) 写一个字符串的一部分
        String str = " 爪哇IO流";
        osw.write(str, 0, str.length());
        // 关闭流
        osw.close();
        // int read(char[] cbuf) 将字符读入数组
        char[] chs = new char[1024];
        int len;
        while ((len = isr.read(chs)) != -1) {
            System.out.println(new String(chs, 0, len));        // I love java 爪哇IO流
        }
        // 关闭流
        isr.close();
    }
}
4.3 字符缓冲流

(1)概述

  • 字符缓冲流同样有两种,分别为BufferedWriterBufferedReader

  • BufferedWriter:将文本写入到字符输出流中,缓冲字符,能够指定缓冲区大小。

  • BufferedReader:从字符输入流中读取文本,缓冲字符,能够指定缓冲区大小。

(2)构造方法

  • 字符缓冲输出流:BufferedWriter(Writer out)
  • 字符缓冲输入流:BufferedReader(Reader in)

(3)特有方法

方法名说明
void newLine()写一行行分隔符(换行)。
String readLine()读一行文字,不包含任何终止字符,如果到达流的末尾,则为null。
/**
 * 小小案例:随机点名
 */
public class CallNameDemo {
    public static void main(String[] args) throws IOException {
        // 存入数据
        // 创建字符缓冲输出流对象
        BufferedWriter bw = new BufferedWriter(new FileWriter("test.txt"));
        bw.write("阿毛");
        bw.newLine();
        bw.write("阿苟");
        bw.newLine();
        String str = "阿吉\n阿俄\n阿雅";
        bw.write(str);
        // 释放资源
        bw.close();

        // 读出数据
        // 创建字符缓冲输入流对象
        BufferedReader br = new BufferedReader(new FileReader("test.txt"));
        // 创建集合对象,用于存储读出的数据
        ArrayList<String> al = new ArrayList<>();
        String line;
        // 调用字符缓冲输入流对象的方法读数据
        while ((line = br.readLine()) != null) {
            al.add(line);
        }
        // 释放资源
        br.close();

        Random r = new Random();
        // 根据集合的长度,生成随机数
        int i = r.nextInt(al.size());
        // 从数组中获取随机数对应的元素
        String s = al.get(i);
        System.out.println("幸运者:" + s);
    }
}

【程序员养成之路】Java基础篇 1-聊聊Java那些事

【程序员养成之路】Java基础篇 2-初学Java必知的基础语法

【程序员养成之路】Java基础篇 3-反手就能写个冒泡排序的数组

【程序员养成之路】Java基础篇 4-从面向对象里找对象

【程序员养成之路】Java基础篇 5-从异常机制认识常见bug

【程序员养成之路】Java基础篇 6-啥都能“装”的集合

【程序员养成之路】Java基础篇 8-流进流出的IO流(二)

【程序员养成之路】Java基础篇 9-认识一下类加载器与反射


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

正则表达式1951

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值