Java中的IO流

IO流的分类

按照数据类型划分:字符流和字节流

按照数据流向划分:输入流和输出流

对于纯文本数据,优先使用字符流。除此之外都使用字节流。

File类

java.io.File:不能对文件内容(流)进行读写,只能对文件和文件夹进行操作

绝对路径和相对路径

路径不区分大小写,一个反斜杠是转义字符,两个反斜杠代表一个普通的反斜杠

绝对路径:一个完整的路径,以盘符开头,例如 F:\\aaa.txt
相对路径:一个简化的路径,不以盘符开头,例如 \\aaa.txt\\b.txt

构造方法

File类构造方法不会给你检验这个文件或文件夹是否真实存在,因此无论该路径下是否存在文件或者目录,都不影响File对象的创建。

// 文件路径名
String path2 = "D:\\1\\2.txt";
File file2 = new File(path2);     -------------相当于D:\\1\\2.txt

// 通过父路径和子路径字符串
 String parent = "F:\\aaa";
 String child = "bbb.txt";
 File file3 = new File(parent, child);  --------相当于F:\\aaa\\bbb.txt

// 通过父级File对象和子路径字符串
File parentDir = new File("F:\\aaa");
String child = "bbb.txt";
File file4 = new File(parentDir, child); --------相当于F:\\aaa\\bbb.txt

常用方法

方法 用途 public String getAbsolutePath() 获取此File的绝对路径名字符串。 public String getPath() 获取此File转换的路径名字符串。 public String getName() 获取由此File表示的文件或目录的名称。 public long length() 获取由此File表示的文件的长度。 public boolean exists() 判断此File表示的文件或目录是否实际存在。 public boolean isDirectory() 判断此File表示的是否为目录。 public boolean isFile() 判断此File表示的是否为文件。 public boolean createNewFile() 文件不存在,创建一个新的
空文件

并返回 true

,文件存在,不创建文件并返回 false

public boolean delete() 删除由此File表示的
文件或目录

。 public boolean mkdir() 创建由此File表示的
目录

。 public boolean mkdirs() 创建由此File表示的目录,包括任何必需但不存在的父目录。(创建
多级目录

) public String[] list() 返回一个
String

数组,表示该File目录中的
所有子文件或目录

。 public File[] listFiles() 返回一个
File

数组,表示该File目录中的
所有的子文件或目录

练习

递归遍历目录以及子目录下的所有文件(见同目录下的IDEA文件)

输入输出流

字节流概述

IO分类之后的父类

输入流 输出流 字节流 字节输入流
InputStream

字节输出流
OutputStream

字符流 字符输入流
Reader

字符输出流
Writer

OutputStream与InputStream的继承关系

Java中的IO流

字节流基流

3.1.1)InputStream:

字节输入流基类,抽象类是表示字节输入流的所有类的超类。

方法 功能 abstract int read() //每次可以读取
一个字节

的数据,提升为int类型,读取到文件末尾,返回 -1

int read(byte[] b) // 每次
读取b的长度

个字节到
数组b

中,返回读取到的有效字节个数,读取到末尾时,返回 -1

int read(byte[] b, int off, int len) // 将输入流中从 off 开始最多 len 个数据字节读入 byte 数组 long skip(long n) // 跳过和丢弃此输入流中数据的 n个字节 void close() // 关闭此输入流并释放与该流关联的所有系统资源

3.1.2)OutputStream

OutputStream:字节输出流基类,抽象类是表示输出字节流的所有类的超类。

方法 功能 void write(byte[] b) // 将 b.length 个字节从指定的 byte 数组写入此输出流 void write(byte[] b, int off, int len) // 将指定 byte 数组中从偏移量 off 开始的 len 个字节写入此输出流 abstract void write(int b) // 将指定的字节写入此输出流 void close() // 关闭此输出流并释放与此流有关的所有系统资源 void flush() // 刷新此输出流并强制写出所有缓冲的输出字节

字节流文件操作流

字节文件输入流 (FileInputStream)

FileInputStream:字节文件输入流,从文件系统中的某个文件中获得输入字节,用于读取诸如图像数据之类的原始字节流。

①构造函数

构造方法 解释 FileInputStream(File file) // 通过打开一个到实际文件的连接来创建一个FileInputStream,该文件通过文件系统中的File对象file指定 FileInputStream(String name) // 通过打开一个到实际文件的连接来创建一个FileInputStream,该文件通过文件系统中的路径name指定

②代码示例
常用方法:覆盖和重写了父类的的常用方法。
        //构造方法1
        //InputStream inputStream = new FileInputStream(new File("f://hello//test.txt"));

        //构造方法2
        InputStream inputStream2 = new FileInputStream("f://hello/test.txt");
        // 字节数组
        byte[] b = new byte[2];
        int i2 = 0;
        //  一次读取一个字节数组 -->int read(byte[] b) 从输入流中读取一定数量的字节,并将其存储在缓冲区数组 b中
        while ((i2 = inputStream2.read(b)) != -1) {
            //表示从缓冲区数组中输出从0开始的1个字节,也就是一个字母,如果改成2,就输出AB CD
            System.out.print(new String(b, 0, 1) + " ");// A B C D
        } //关闭IO流
        inputStream2.close();
字节文件输出流 (FileOutputStream)

FileOutputStream:字节文件输出流是用于将数据写入到File,从程序中写入到其他位置。

①构造函数

构造方法 解释 FileOutputStream(File file) // 创建一个向指定File对象表示的文件中写入数据的文件输出流 FileOutputStream(File file, boolean append) // 创建一个向指定File对象表示的文件中
追加数据

的文件输出流 FileOutputStream(String name) // 创建一个向具有指定名称的文件中写入数据的输出文件流 FileOutputStream(String name, boolean append) // 创建一个向具有指定name的文件中
追加数据

的输出文件流

②代码示例
     OutputStream outputStream = new FileOutputStream(new File("test.txt"));
        // 写出数据
        outputStream.write("ABCD".getBytes());
        // 关闭IO流
        outputStream.close();
        // 当布尔值为真,表示进行内容追加。当布尔值为假,表示清空原数据再添加
        OutputStream outputStream2 = new FileOutputStream("test.txt", true);
        // 输出换行符
        outputStream2.write("\r\n".getBytes());
        // 输出追加内容
        outputStream2.write("hello".getBytes());
        // 关闭IO流
        outputStream2.close();

注:输出的目的地文件不存在,则会自动创建,不指定盘符的话,默认创建在项目目录下;输出换行符时一定要写\r\n不能只写\n,因为不同文本编辑器对换行符的识别存在差异性。

练习:使用字节流文件操作流进行文件复制
public static void copy() {
        //不能把两个对象写在try中,否则finally无法调用这两个对象
        InputStream inputStream = null;
        OutputStream fileOutputStream = null;
        try {
            inputStream = new FileInputStream("F:\\FileTest.txt");
            fileOutputStream = new FileOutputStream("F:\\Copy.txt");
            byte[] b = new byte[1024];
            int len;
            //len表明当前字节长度,b是用于存储读到的数据
            while ((len = inputStream.read(b)) != -1) {
                fileOutputStream.write(b,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                inputStream.close();
                fileOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

字符流概述

为什么要用字符流

字节流读取中文字符时,可能不会显示完整字符,那是因为一个中文字符占用多个字节存储。因此,当需要高效处理字符时,最佳的选择往往是字符流操作

当文件内含有中文时,下面的使用字节流的代码将输出乱码。

         //FileInputStream为操作文件的字符输入流
        FileInputStream inputStream = new FileInputStream("a.txt");
        int len;
        while ((len=inputStream.read())!=-1){
           System.out.print((char)len);
        }

虽然可以通过字节组来缓存文件的数组大小个字节,以达到一次读出多个字节的目的,但是仍然比较麻烦。

        FileInputStream inputStream = new FileInputStream("a.txt");
        byte[] bytes = new byte[1024];
        int len;
        while ((len=inputStream.read(bytes))!=-1){
           //利用了String构造方法的解码功能
           System.out.print(new String(bytes,0,len));
        }
字符流Reader和Writer的关系

Java中的IO流

字符流基类

读取字符流(Reader )

Reader:读取字符流的抽象类.

①常用方法

方法 作用 int read() // 读取单个
字符

int read(char[] cbuf) // 将字符读入数组 abstract int read(char[] cbuf, int off, int len) // 将字符读入数组的某一部分 long skip(long n) // 跳过字符 abstract void close() // 关闭该流并释放与之关联的所有资源

②构造方法
FileReader类

java.io.FileReader类是读取字符文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区。

方法 作用 FileReader(File file) 创建一个新的 FileReader ,给定要读取的
File对象

。 FileReader(String fileName) 创建一个新的 FileReader ,给定要读取的文件的
字符串名称

③代码示例
/**
 * 字符流:读
 */
public class FRRead {
    public static void main(String[] args) throws IOException {
        // 使用文件名称创建流对象
        FileReader fr = new FileReader("a.txt");
        // 定义变量,保存数据
        int b ;
        // 一次可以读出一个字符,不需要再设定字节数组
        while ((b = fr.read())!=-1) {
            System.out.println((char)b);
        }
        // 关闭资源
        fr.close();
    }
}
写入字符流(Writer)

Writer:写入字符流的抽象类

①常用方法

方法 作用 void write(char[] cbuf) // 写入字符数组 abstract void write(char[] cbuf, int off, int len) // 写入字符数组的某一部分 void write(int c)

void write(String str)

void write(String str, int off, int len) // 写入单个字符

// 写入字符串

// 写入字符串的某一部分 Writer append(char c)

Writer append(CharSequence csq)

Writer append(CharSequence csq, int start, int end) // 将指定字符添加到此 writer

// 将指定字符序列添加到此 writer

// 将指定字符序列的子序列添加到此 writer.Appendable abstract void close() // 关闭此流,但要先刷新它 abstract void flush() // 刷新该流的缓冲

②构造方法
FileWriter类

java.io.FileWriter类是写出字符到文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区。

方法 作用 FileWriter(File file) 创建一个新的 FileWriter,给定要读取的File对象。 FileWriter(String fileName) 创建一个新的 FileWriter,给定要读取的文件的名称。

③代码示例
public class FWWrite {
    public static void main(String[] args) throws IOException {
        // 使用文件名称创建流对象
        FileWriter fw = new FileWriter("fw.txt");
        // 写出数据
        fw.write(97); // 写出第1个字符
        fw.write('b'); // 写出第2个字符
        fw.write('C'); // 写出第3个字符

        //关闭资源时,与FileOutputStream不同。 如果不关闭,数据只是保存到缓冲区,并未保存到文件。
        // fw.close();
    }
}
输出结果:
abC

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

关闭close和刷新flush

因为内置缓冲区的原因,如果不关闭输出流,无法写出字符到文件中。但是关闭的流对象,是无法继续写出数据的。如果我们既想写出数据,又想继续使用流,就需要 flush 方法了。

flush :刷新缓冲区,流对象可以继续使用。
close :先刷新缓冲区,然后通知系统释放资源。流对象不可以再被使用了。

练习:FileReader和FileWriter类完成文本文件复制
public class CopyFile {
    public static void main(String[] args) throws IOException {
        //创建输入流对象
        FileReader fr=new FileReader("F:\\新建文件夹\\aa.txt");//文件不存在会抛出java.io.FileNotFoundException
        //创建输出流对象
        FileWriter fw=new FileWriter("C:\\copyaa.txt");
        //文本文件复制,一次读一个字符
        copyMethod1(fr, fw);
        //文本文件复制,一次读一个字符数组
        copyMethod2(fr, fw);
        fr.close();
        fw.close();
    }

    public static void copyMethod1(FileReader fr, FileWriter fw) throws IOException {
        int ch;
        while((ch=fr.read())!=-1) {//读数据
            fw.write(ch);//写数据
        }
        //写一个字符刷新一次
        fw.flush();
    }

    public static void copyMethod2(FileReader fr, FileWriter fw) throws IOException {
        char chs[]=new char[1024];
        int len=0;
        while((len=fr.read(chs))!=-1) {//读数据
            fw.write(chs,0,len);//写数据
        }
        //写一个字符数组刷新一次
        fw.flush();
    }
}

`

IO异常的处理

我们在学习的过程中可能习惯把异常抛出,而实际开发中并不能这样处理,建议使用 try...catch...finally 代码块,处理异常部分

缓冲流

创建流对象时,会创建一个内置的默认大小的 缓冲区数组,通过缓冲区读写,减少系统IO次数,从而提高读写的效率。

字节缓冲流

构造方法
//构造方式一: 创建字节缓冲输入流【但是开发中一般常用下面的格式申明】
FileInputStream fps = new FileInputStream(b.txt);
BufferedInputStream bis = new BufferedInputStream(fps)

//构造方式一: 创建字节缓冲输入流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("b.txt"));

///构造方式二: 创建字节缓冲输出流
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("b.txt"));

字符缓冲流

构造函数
// 创建字符缓冲输入流
BufferedReader br = new BufferedReader(new FileReader("b.txt"));
// 创建字符缓冲输出流
BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));

总结:使用缓冲流对文件进行读写操作,效率将会快很多!

转换流

避免因编码问题导致的乱码现象。字符流=字节流+编码表

字符集

Java中的IO流

InputStreamReader类

字节流到字符流的桥梁,是 Reader的子类。它读取字节,并使用指定的字符集将其解码为字符。它的字符集可以由名称指定,也可以接受平台的默认字符集。

构造方法
InputStreamReader isr = new InputStreamReader(new FileInputStream("in.txt"));

InputStreamReader isr2 = new InputStreamReader(new FileInputStream("in.txt") , "GBK");
使用转换流解决编码问题的例子
public class ReaderDemo2 {
    public static void main(String[] args) throws IOException {
        // 定义文件路径,文件为gbk编码
        String FileName = "C:\\A.txt";
        // 创建流对象,默认UTF8编码
        InputStreamReader isr = new InputStreamReader(new FileInputStream(FileName));
        // 创建流对象,指定GBK编码
        InputStreamReader isr2 = new InputStreamReader(new FileInputStream(FileName) , "GBK");
        // 定义变量,保存字符
        int read;
        // 使用默认编码字符流读取,乱码
        while ((read = isr.read()) != -1) {
            System.out.print((char)read); // �����ʺ
        }
        isr.close();

        // 使用指定编码字符流读取,正常解析
        while ((read = isr2.read()) != -1) {
            System.out.print((char)read);// 叶斯摩拉
        }
        isr2.close();
    }
}

OutputStreamWriter类

字符流到字节流的桥梁,是Writer的子类.使用指定的字符集 将字符编码为字节。它的字符集可以由名称指定,也可以接受平台的默认字符集。

构造方法
OutputStreamWriter isr = new OutputStreamWriter(new FileOutputStream("a.txt")); //默认为UTF-8编码方式

OutputStreamWriter isr2 = new OutputStreamWriter(new FileOutputStream("b.txt") , "GBK"); //指定文件写出为GBK编码
指定编码构造代码的一个例子
public class OutputDemo {
    public static void main(String[] args) throws IOException {
        // 定义文件路径
        String FileName = "C:\\s.txt";
        // 创建流对象,默认UTF8编码
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(FileName));
        // 写出数据
        osw.write("加油"); // 保存为6个字节
        osw.close();

        // 定义文件路径
        String FileName2 = "D:\\A.txt";
        // 创建流对象,指定GBK编码
        OutputStreamWriter osw2 = new OutputStreamWriter(new FileOutputStream(FileName2),"GBK");
        // 写出数据
        osw2.write("哥们");// 保存为4个字节
        osw2.close();
    }
}

为了达到 最高效率,可以考虑在 BufferedReader 内包装 InputStreamReader

BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

打印流

print方法和 println方法都来自于 java.io.PrintStream类。PrintStream是OutputStream的子类,PrintWriter是Writer的子类,打印操作效率最高

字节输出打印流PrintStream复制文本文件

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintStream;

public class PrintStreamDemo {
    public static void main(String[] args) throws IOException {
        BufferedReader br=new BufferedReader(new FileReader("copy.txt"));
        PrintStream ps=new PrintStream("printcopy.txt");
        String line;
        while((line=br.readLine())!=null) {
            ps.println(line);
        }
        br.close();
        ps.close();
    }
}

字符输出打印流PrintWriter复制文本文件

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
/**
 * 使用打印流复制文本文件
 */
public class PrintWriterDemo {
    public static void main(String[] args) throws IOException {
        BufferedReader br=new BufferedReader(new FileReader("aa.txt"));
        PrintWriter pw=new PrintWriter("printcopyaa.txt");
        String line;
        while((line=br.readLine())!=null) {
            pw.println(line);
        }
        br.close();
        pw.close();
    }
}

I/O操作好文

史上最骚的I/O操作

Original: https://www.cnblogs.com/Tayoou/p/16556179.html
Author: Tayoou
Title: Java中的IO流

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/593975/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 题目:模拟网站的登录,客户端录入账号密码,然后服务器端进行验证(TCP)(完善)

    完善(加入完整的处理异常的方式、多线程接收用户请求)(TCP) 封装的类 package com.gao.Project.Pro5; import java.io.Serializ…

    Java 2023年6月5日
    095
  • 创建Springboot工程接收acticemq消息

    1、JMSFactory配置 <beans xmlns="http://www.springframework.org/schema/beans" xml…

    Java 2023年5月30日
    0123
  • 归并排序

    归并排序 本文分为以下几个部分 问题引入 master 公式 归并排序 写在最后 问题引入 求一串非空数组中的最大值,使用O(n)的时间复杂度。 最直接想到的代码就是直接一次遍历 …

    Java 2023年6月5日
    069
  • Spring DefaultResourceLoader

    Spring DefaultResourceLoader Spring DefaultResourceLoader继承ResourceLoader接口,用来加载资源, 通过Reso…

    Java 2023年6月7日
    076
  • IDEA一键部署SpringBoot项目到服务器

    1. 安装Alibaba Cloud Toolkit插件 2. 配置部署环境 2.1 为本次部署设置一个名字 2.2 选择被部署文件的生成方式 IDEA提供了三种方式: Maven…

    Java 2023年6月7日
    088
  • day01-数据库的安装和使用

    Java数据库的安装和使用 1.数据库的作用 一个问题:淘宝网、京东、微信抖音,都有各自的功能,那么我们退出系统的时候,为什么信息还在? 解决之道-文件,数据库 为了解决上诉问题,…

    Java 2023年6月15日
    093
  • Git 12 IDEA上传本地项目到远程

    这里以上传 Spring 开源项目到 Gitee 为例: 1、点击 Create Git Repository 2、选择项目目录 3、添加到缓存库 4、提交到本地库 5、复制远程库…

    Java 2023年6月6日
    080
  • MySQL索引

    MySQL索引 1、MySQL中InnoDB存储引擎索引概述 在InnoDB存储引擎中支持以下几种常见的索引 B+树索引 全文索引 哈希索引 InnoDB存储引擎支持的索引是自适应…

    Java 2023年6月8日
    074
  • Linux基操

    1 解压命令:tar -zxcf [压缩包名] 2 &…

    Java 2023年6月8日
    088
  • Rocket Mq 常用API 及简单运维

    RocketMQ 常用API 消息 消息消费模式 消息消费模式由消费者来决定,可以由消费者设置MessageModel来决定消息模式。 消息模式默认为集群消费模式 consumer…

    Java 2023年6月7日
    091
  • 难搞的偏向锁终于被 Java 移除了

    背景 在 JDK1.5 之前,面对 Java 并发问题, synchronized 是一招鲜的解决方案: 普通同步方法,锁上当前实例对象 静态同步方法,锁上当前类 Class 对象…

    Java 2023年6月5日
    094
  • leetcode 110. Balanced Binary Tree 平衡二叉树(简单)

    一、题目大意 给定一个二叉树,判断它是否是高度平衡的二叉树。 本题中,一棵高度平衡二叉树定义为: 一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。 示例 1: 输入…

    Java 2023年6月13日
    074
  • Mysql异常——com.alibaba.druid.sql.parser.ParserException

    今天写业务逻辑时候,写完发现控制台出现报错,但是程序可以正常运行。在控制台报错中发现是因为SQL模糊查询格式问题 修改模糊查询 写法后 成功解决该报错 Original: http…

    Java 2023年6月9日
    097
  • shell 编程

    shell 编程 Shell 是一个命令行解释器,它为用户提供了一个向 Linux 内核发送请求以便运行程序的界面系统级程序,用户可以用 Shell 来启动、挂起、停止甚至是编写一…

    Java 2023年6月5日
    091
  • Takeown、Cacls、Icacls-文件、文件夹夺权用法

    本文补充下常用的文件、文件夹夺权或者夺取所有者的方法,涉及Takeown、Cacls、Icacls用法。 takeown /f 文件名 获取该文件的所属权 takeown /f /…

    Java 2023年5月30日
    082
  • Spring Bean的作用域

    Spring Bean的作用域或者说范围主要有五种: 作用 描述 singleton 在spring IoC容器仅存在一个Bean实例,Bean以单例方式存在,bean作用域范围的…

    Java 2023年6月14日
    086
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球