【Java 基础】File & IO流

简介: 【Java 基础】File & IO流

1. File


java.io.File类是文件和目录路径名的抽象表示形式,主要用于文件和目录的创建、查找和删除等操作。


1.1 File类概述和构造方法


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


  • 文件和目录可以通过File封装成对象


  • File封装的对象仅仅是一个路径名。它可以是存在的,也可以是不存在的。


方法名

说明

 File(String pathname)

通过将给定的路径名字符串转换为抽象路径名来创建新的 File实例 

File(String parent, String child)

从父路径名字符串和子路径名字符串创建新的 File实例

File(File parent, String child) 

从父抽象路径名和子路径名字符串创建新的 File实例


1.2 绝对路径和相对路径


  1. 绝对路径:从盘符开始


File file1 = new File(“D:\\snow\\a.txt”);


  1. 相对路径:相对当前项目下的路径


File file2 = new File(“a.txt”);
File file3 = new File(“模块名\\a.txt”);


1.3 File 类的常用方法


创建和删除


方法名 说明
public boolean createNewFile() 创建一个新的空的文件
public boolean mkdir() 创建一个单级文件夹
public boolean mkdirs() 创建一个多级文件夹
public boolean delete() 删除由此抽象路径名表示的文件或目录


删除目录时的注意事项:


  1. delete方法直接删除不走回收站。


  1. 如果删除的是一个文件,直接删除。


  1. 如果删除的是一个文件夹,需要先删除文件夹中的内容,最后才能删除文件夹。


File类判断和获取功能


方法名 说明
public boolean isDirectory() 测试此抽象路径名表示的File是否为目录
public boolean isFile() 测试此抽象路径名表示的File是否为文件
public boolean exists() 测试此抽象路径名表示的File是否存在
public String getAbsolutePath() 返回此抽象路径名的绝对路径名字符串
public String getPath() 将此抽象路径名转换为路径名字符串(File对象给定的路径)
public String getName() 返回由此抽象路径名表示的文件或目录的名称


File类高级获取功能


//  返回此抽象路径名表示的目录中的文件和目录的File对象数组
public File[] listFiles();


listFiles方法注意事项:


  • 当调用者不存在时,返回null


  • 当调用者是一个文件时,返回null


  • 当调用者是一个空文件夹时,返回一个长度为0的数组


  • 当调用者是一个有内容的文件夹时,将里面所有文件和文件夹的路径放在File数组中返回


  • 当调用者是一个有隐藏文件的文件夹时,将里面所有文件和文件夹的路径放在File数组中返回,包含隐藏内容


1.4 递归删除文件夹及其下面的文件


public static void main(String[] args) {
    File f = new File("D:\\aaa");
    deleteFiles(f);
}
private static void deleteFiles(File f) {
    File[] files = f.listFiles();
    for (File file : files) {
        if (file.isDirectory()) {
            // 递归
            deleteFiles(file);
        } else {
            // 删除文件
            file.delete();
        }
    }
    // 删除当前文件夹
    f.delete();
}


2. IO


I 表示intput ,是数据从硬盘进内存的过程,称之为读数据。


O 表示output ,是数据从内存到硬盘的过程。称之为写数据。


在数据传输的过程中,是谁在读?是谁在写?这个参照物是谁?


IO的数据传输,可以看做是一种数据的流动,按照流动的方向,以内存为参照物,进行读写操作。


简单来说:内存在读,内存在写。



2.1 分类



2.2 字节输出流


OutputStream有很多子类,我们从最简单的一个子类开始。


java.io.FileOutputStream类是文件输出流,用于将数据写出到文件:


构造方法:


  • public FileOutputStream(File file):创建文件输出流以写入由指定的 File对象表示的文件。


  • public FileOutputStream(String name): 创建文件输出流以指定的名称写入文件。


import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
    字节输出流写数据快速入门 :
        1 创建字节输出流对象。
        2 写数据
        3 释放资源
 */
public class OutputStreamDemo1 {
    public static void main(String[] args) throws IOException {
        // 创建字节输出流对象
        // 如果指定的文件不存在 , 会自动创建文件
        // 如果文件存在 , 会把文件中的内容清空
        FileOutputStream fos = new FileOutputStream("test\\a.txt");
        // 写数据
        // 写到文件中就是以字节形式存在的
        // 只是文件帮我们把字节翻译成了对应的字符 , 方便查看
        fos.write(97);
        fos.write(98);
        fos.write(99);
        // 释放资源
        // while(true){}
        // 断开流与文件中间的关系
        fos.close();
    }
}


字节流写数据的3种方式


方法名 说明
void write(int b) 一次写一个字节数据
void write(byte[] b) 一次写一个字节数组数据
void write(byte[] b, int off, int len) 一次写一个字节数组的部分数据


public class OutputStreamDemo2 {
    public static void main(String[] args) throws IOException {
        // 创建字节输出流对象
        FileOutputStream fos = new FileOutputStream("test\\a.txt");
        // 写数据
//        1 void write(int b) 一次写一个字节数据
        fos.write(97);
        fos.write(98);
        fos.write(99);
//        2 void write(byte[] b)  一次写一个字节数组数据
        byte[] bys = {65, 66, 67, 68, 69};
        fos.write(bys);
//        3 void write(byte[] b, int off, int len)  一次写一个字节数组的部分数据
        fos.write(bys, 0, 3);
        // 释放资源
        fos.close();
    }
}


字节流写数据的换行和追加写入


字节流写数据如何实现换行呢?


写完数据后,加换行符


windows : \r\n


linux : \n


mac : \r


字节流写数据如何实现追加写入呢?


public FileOutputStream(String name,boolean append)


创建文件输出流以指定的名称写入文件。如果第二个参数为true ,不会清空文件里面的内容。


2.3 字节输入流


InputStream


FileInputStream extends InputStream


FileInputStream 构造方法


  • public FileInputStream(File file) : 从file类型的路径中读取数据


  • public FileInputStream(String name) : 从字符串路径中读取数据


import java.io.FileInputStream;
import java.io.IOException;
/*
    字节输入流写数据快速入门 : 一次读一个字节
            第一部分 : 字节输入流类
                InputStream类 : 字节输入流最顶层的类 , 抽象类
                --- FileInputStream类 : FileInputStream extends InputStream
            第二部分 : 构造方法
                public FileInputStream(File file) :  从file类型的路径中读取数据
                public FileInputStream(String name) : 从字符串路径中读取数据
            第三部分 : 字节输入流步骤
                1 创建输入流对象
                2 读数据
                3 释放资源
 */
public class FileInputStreamDemo1 {
    public static void main(String[] args) throws IOException {
        // 创建字节输入流对象
        // 读取的文件必须存在 , 不存在则报错
        FileInputStream fis = new FileInputStream("day11_demo\\a.txt");
        // 读数据 , 从文件中读到一个字节
        // 返回的是一个int类型的字节
        // 如果想看字符, 需要强转
        int by = fis.read();
        System.out.println((char) by);
        // 释放资源
        fis.close();
    }
}


字节输入流 读多个字节


import java.io.FileInputStream;
import java.io.IOException;
/*
    字节输入流写数据快速入门 : 读多个字节
            第一部分 : 字节输入流类
                InputStream类 : 字节输入流最顶层的类 , 抽象类
                --- FileInputStream类 : FileInputStream extends InputStream
            第二部分 : 构造方法
                public FileInputStream(File file) :  从file类型的路径中读取数据
                public FileInputStream(String name) : 从字符串路径中读取数据
            第三部分 : 字节输入流步骤
                1 创建输入流对象
                2 读数据
                3 释放资源
 */
public class FileInputStreamDemo2 {
    public static void main(String[] args) throws IOException {
        // 创建字节输入流对象
        // 读取的文件必须存在 , 不存在则报错
        FileInputStream fis = new FileInputStream("day11_demo\\a.txt");
        // 读数据 , 从文件中读到一个字节
        // 返回的是一个int类型的字节
        // 如果想看字符, 需要强转
        // 循环改进
        int by;// 记录每次读到的字节
        while ((by = fis.read()) != -1) {
            System.out.print((char) by);
        }
        // 释放资源
        fis.close();
    }
}


2.4 文件的拷贝


import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
    需求 : 把 "图片路径\xxx.jpg" 复制到当前模块下
    分析:
        复制文件,其实就把文件的内容从一个文件中读取出来(数据源),然后写入到另一个文件中(目的地)
        数据源:
            xxx.jpg  --- 读数据 --- FileInputStream
        目的地:
            模块名称\copy.jpg --- 写数据 --- FileOutputStream
 */
public class CopyFile2 {
    public static void main(String[] args) throws IOException {
        // 创建字节输入流对象
        FileInputStream fis = new FileInputStream("D:\\安装包\\好看的图片\\liqin.jpg");
        // 创建字节输出流
        FileOutputStream fos = new FileOutputStream("day11_demo\\copy.jpg");
        // 一次读写一个字节
        int by;
        while ((by = fis.read()) != -1) {
            fos.write(by);
        }
        // 释放资源
        fis.close();
        fos.close();
    }
}


2.5 文件拷贝效率优化


import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/*
    需求 : 对复制图片的代码进行使用一次读写一个字节数组的方式进行改进
    FileInputStream类 :
        public int read(byte[] b):
        1 从输入流读取最多b.length个字节的数据
        2 返回的是真实读到的数据个数
 */
public class FileInputStreamDemo7 {
    public static void main(String[] args) throws IOException {
        // 创建字节输入流对象
        FileInputStream fis = new FileInputStream("D:\\好看的图片\\liqin.jpg");
        // 创建字节输出流
        FileOutputStream fos = new FileOutputStream("day11_demo\\copy.jpg");
        byte[] bys = new byte[1024];
        int len;// 每次真实读到数据的个数
        //int by;//好像没用上啊
        while ((len = fis.read(bys)) != -1) {
            fos.write(bys, 0, len);
        }
        // 释放资源
        fis.close();
        fos.close();
    }
}


2.6 释放资源


JDK7版本优化处理方式 : 自动释放资源


JDK7优化后可以使用 try-with-resource 语句 , 该语句确保了每个资源在语句结束时自动关闭。简单理解 : 使用此语句,会自动释放资源 , 不需要自己在写finally代码块了


格式 :  
try (创建流对象语句1 ; 创建流对象语句2 ...) {
        // 读写数据
} catch (IOException e) {
        处理异常的代码...
}
举例 :
try ( 
    FileInputStream fis1 = new FileInputStream("day11_demo\\a.txt") ; 
    FileInputStream fis2 = new FileInputStream("day11_demo\\b.txt") ) 
{
    // 读写数据
} catch (IOException e) {
    处理异常的代码...
}


代码实践


import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/*
    JDK7版本优化处理方式
    需求 : 对上一个赋值图片的代码进行使用捕获方式处理
 */
public class FileInputStreamDemo5 {
    public static void main(String[] args) {
        try (
                // 创建字节输入流对象
                FileInputStream fis = new FileInputStream("D:\\图片\\liqin.jpg");
                // 创建字节输出流
                FileOutputStream fos = new FileOutputStream("day11_demo\\copy.jpg")
        ) {
            // 一次读写一个字节
            int by;
            while ((by = fis.read()) != -1) {
                fos.write(by);
            }
            //  释放资源 , 发现已经灰色 , 提示多余的代码 
            //  所以使用 try-with-resource 方式会自动关流
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}


注意:自动释放的资源是实现了 AutoCloseable 接口的才可以。


2.7 缓冲流


字节缓冲流:


  • BufferOutputStream:缓冲输出流


  • BufferedInputStream:缓冲输入流


构造方法:


  • 字节缓冲输出流:BufferedOutputStream(OutputStream out)


  • 字节缓冲输入流:BufferedInputStream(InputStream in)


copy 文件实操


copyFile2("D:\\work\\test\\file_io\\xian.jpg",
                "D:\\work\\test\\file_io\\xian2.jpg");
static void copyFile2(String fileUrl1, String fileUrl2){
    try(
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(fileUrl1));
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(fileUrl2))
    ){
        byte[] readArray = new byte[1024];
        //  每次真实读到数据的个数
        int len;
        while((len = bis.read(readArray)) != -1){
            bos.write(readArray, 0 ,len);
        }
    } catch (FileNotFoundException e) {
        e.printStackTrace();
        throw new RuntimeException("文件未找到!");
    } catch (IOException e) {
        e.printStackTrace();
        throw new RuntimeException("异常啦!");
    }
}


2.8 编码表


  • 计算机中储存的信息都是用二进制数据表示的;我们在屏幕上看到的英文、汉字等字符是二进制数转换之后的结果


  • 按照编码表规则,将字符存储到计算机中,称为编码


  • 按照同样的编码表规则,将存储在计算机中的二进制数据解析显示出来,称为解码


  • 编码和解码使用的码表必须一致,否则会导致乱码。


常见编码表:


  1. ASCII码表:ASCII(American Standard Code for Information Interchange,美国信息交换标准码表):


包括了数字字符,英文大小写字符和一些常见的标点符号字符。


注意:ASCII码表中是没有中文的。


  1. GBK:window系统默认的码表。兼容ASCII码表,也包含了21003个汉字,并支持繁体汉字以及部分日韩文字。


注意:GBK是中国的码表,一个中文以两个字节的形式存储。但不包含世界上所有国家的文字。



  1. Unicode码表:


由国际组织ISO 制定,是统一的万国码表,计算机科学领域里的一项业界标准,容纳世界上大多数国家的所有常见文字和符号。


但是因为表示的字符太多,所以Unicode码表中的数字不是直接以二进制的形式存储到计算机的,会先通过UTF-7,UTF-7.5,UTF-8,UTF-16,以及 UTF-32的编码方式再存储到计算机,其中最为常见的就是UTF-8。


注意: Unicode是万国码表,以UTF-8编码后一个中文以三个字节的形式存储。



3. commons-io 工具包


3.1 API


org.apache.commons.io.IOUtils类


public static int copy(InputStream in, OutputStream out):
//把input输入流中的内容拷贝到output输出流中,返回拷贝的字节个数(适合文件大小为2GB以下)
public static long copyLarge(InputStream in, OutputStream out):
//把input输入流中的内容拷贝到output输出流中,返回拷贝的字节个数(适合文件大小为2GB以上)


org.apache.commons.io.FileUtils


public static void copyFileToDirectory(final File srcFile, final File destFile): 
  复制文件到另外一个目录下。
public static void copyDirectoryToDirectory(File src , File dest ):
  复制src目录到dest位置。
相关文章
|
3月前
|
Java 开发工具
【Azure Storage Account】Java Code访问Storage Account File Share的上传和下载代码示例
本文介绍如何使用Java通过azure-storage-file-share SDK实现Azure文件共享的上传下载。包含依赖引入、客户端创建及完整示例代码,助你快速集成Azure File Share功能。
398 5
|
6月前
|
监控 Java API
现代 Java IO 高性能实践从原理到落地的高效实现路径与实战指南
本文深入解析现代Java高性能IO实践,涵盖异步非阻塞IO、操作系统优化、大文件处理、响应式网络编程与数据库访问,结合Netty、Reactor等技术落地高并发应用,助力构建高效可扩展的IO系统。
193 0
|
3月前
|
Java Unix Go
【Java】(8)Stream流、文件File相关操作,IO的含义与运用
Java 为 I/O 提供了强大的而灵活的支持,使其更广泛地应用到文件传输和网络编程中。!但本节讲述最基本的和流与 I/O 相关的功能。我们将通过一个个例子来学习这些功能。
212 1
|
5月前
|
Java 测试技术 API
Java IO流(二):文件操作与NIO入门
本文详解Java NIO与传统IO的区别与优势,涵盖Path、Files类、Channel、Buffer、Selector等核心概念,深入讲解文件操作、目录遍历、NIO实战及性能优化技巧,适合处理大文件与高并发场景,助力高效IO编程与面试准备。
|
5月前
|
SQL Java 数据库连接
Java IO流(一):字节流与字符流基础
本文全面解析Java IO流,涵盖字节流、字符流及其使用场景,帮助开发者理解IO流分类与用途,掌握文件读写、编码转换、异常处理等核心技术,通过实战案例提升IO编程能力。
|
6月前
|
存储 Java Linux
操作系统层面视角下 Java IO 的演进路径及核心技术变革解析
本文从操作系统层面深入解析Java IO的演进历程,涵盖BIO、NIO、多路复用器及Netty等核心技术。分析各阶段IO模型的原理、优缺点及系统调用机制,探讨Java如何通过底层优化提升并发性能与数据处理效率,全面呈现IO技术的变革路径与发展趋势。
142 2
|
7月前
|
Linux C语言 网络架构
Linux的基础IO内容补充-FILE
而当我们将运行结果重定向到log.txt文件时,数据的刷新策略就变为了全缓冲,此时我们使用printf和fwrite函数打印的数据都打印到了C语言自带的缓冲区当中,之后当我们使用fork函数创建子进程时,由于进程间具有独立性,而之后当父进程或是子进程对要刷新缓冲区内容时,本质就是对父子进程共享的数据进行了修改,此时就需要对数据进行写时拷贝,至此缓冲区当中的数据就变成了两份,一份父进程的,一份子进程的,所以重定向到log.txt文件当中printf和fwrite函数打印的数据就有两份。此时我们就可以知道,
118 0
|
10月前
|
存储 网络协议 安全
Java网络编程,多线程,IO流综合小项目一一ChatBoxes
**项目介绍**:本项目实现了一个基于TCP协议的C/S架构控制台聊天室,支持局域网内多客户端同时聊天。用户需注册并登录,用户名唯一,密码格式为字母开头加纯数字。登录后可实时聊天,服务端负责验证用户信息并转发消息。 **项目亮点**: - **C/S架构**:客户端与服务端通过TCP连接通信。 - **多线程**:采用多线程处理多个客户端的并发请求,确保实时交互。 - **IO流**:使用BufferedReader和BufferedWriter进行数据传输,确保高效稳定的通信。 - **线程安全**:通过同步代码块和锁机制保证共享数据的安全性。
450 23
|
11月前
|
缓存 网络协议 Java
JAVA网络IO之NIO/BIO
本文介绍了Java网络编程的基础与历史演进,重点阐述了IO和Socket的概念。Java的IO分为设备和接口两部分,通过流、字节、字符等方式实现与外部的交互。
368 0
|
Java
java 中 IO 流
Java中的IO流是用于处理输入输出操作的机制,主要包括字节流和字符流两大类。字节流以8位字节为单位处理数据,如FileInputStream和FileOutputStream;字符流以16位Unicode字符为单位,如FileReader和FileWriter。这些流提供了读写文件、网络传输等基本功能。
241 10