Java IO流

简介: Java IO流

一、File类的使用File类的使用

  java.io.File 类: 文件和文件目录路径 的抽象表示形式,与平台无关

  File 能新建、删除、重命名文件和目录,但 File 不能访问文件内容本身。

如果需要访问文件内容本身,则需要使用输入 / 输出流。

想要在 Java 程序中表示一个真实存在的文件或目录,那么必须有一个 File

象,但是 Java 程序中的一个 File 对象,可能没有一个真实存在的文件或目录。

  File 对象可以作为参数传递给流的构造器

File类常用构造器:

public File(String pathname)

pathname 为路径创建 File 对象,可以是 绝对路径或者相对路径 ,如果

pathname 是相对路径,则默认的当前路径在系统属性 user.dir 中存储。

绝对路径:是一个固定的路径 , 从盘符开始

相对路径:是相对于某个位置开始

public File(String parent,String child)

parent 为父路径, child 为子路径创建 File 对象。

public File(File parent,String child)

根据一个父 File 对象和子文件路径创建 File 对象

File类的获取功能

public String getAbsolutePath() 获取绝对路径

public String getPath() :获取路径

public String getName() :获取名称

public String getParent() 获取上层文件目录路径。若无,返回 null

 public long length() :获取文件长度(即:字节数)。不能获取目录的长度。

 public long lastModified() :获取最后一次的修改时间,毫秒值

 public String[] list() :获取指定目录下的所有文件或者文件目录的名称数组

 public File[] listFiles() :获取指定目录下的所有文件或者文件目录的 File 数组

File类的重命名功能

public boolean renameTo(File dest): 把文件重命名为指定的文件路径

File类的判断功能

public boolean isDirectory() 判断是否是文件目录

 public boolean isFile() : 判断是否是文件

 public boolean exists() :判断是否存在

 public boolean canRead() :判断是否可读

public boolean canWrite() :判断是否可写

public boolean isHidden() :判断是否隐藏

File类的创建功能

 public boolean createNewFile()  创建文件。若文件存在,则不创建,返回 false

public boolean mkdir() :创建文件目录。如果此文件目录存在,就不创建了。

如果此文件目录的上层目录不存在,也不创建。

 public boolean mkdirs() : 创建文件目录。如果上层文件目录不存在,一并创建

注意事项:如果你创建文件或者文件目录没有写盘符路径,那么,默认在项目

路径下。

File类的删除功能

public boolean delete() 删除文件或者文件夹

删除注意事项:

Java 中的删除不走 回收站

要删除一个文件目录,请注意该文件目录内不能包含文件或者文件目录

练习

1. 利用 File 构造器, new 一个文件目录 file

1) 在其中创建多个文件和目录

2) 编写方法,实现删除 file 中指定文件的操作

 @Test
    /**
     * 1. 利用File构造器,new 一个文件目录file
     * 1)在其中创建多个文件和目录
     * 2)编写方法,实现删除file中指定文件的操作
     */
    public void test1() throws IOException {
        File file = new File("d:/File","file");
        if(file.createNewFile()){
            System.out.println("文件目录创建成功!");
        }
        File file1 = new File("d:/file/Smile.txt");
        if(file1.createNewFile()){
            System.out.println("子文件创建成功!");
        }
        File dir=new File("d:/file/dir");
        if(dir.mkdir()){
            System.out.println("子文件目录创建成功!");
        }
        deleteFile(dir);
        deleteFile(file);
        deleteFile(file1);
    }
    public void deleteFile(File file){
        if(file.delete()){
            System.out.println("文件删除成功!");
        }
    }

2. 判断指定目录下是否有后缀名为 .jpg 的文件,如果有,就输出该文件名称

public void test2(){
        File file = new File("d:");
        judgeJpg(file);
 
    }
    public void judgeJpg(File file){
        String[] strings=file.list();
        for (int i = 0; i <strings.length ; i++) {
            if(strings[i].endsWith(".jpg")){
                System.out.println(strings[i]);
            }
        }
    }

3. 遍历指定目录所有文件名称,包括子文件目录中的文件。

@Test
    /**
     * 遍历指定目录所有文件名称,包括子文件目录中的文件。
     */
    public void test3(){
        File file = new File("c:");
        String[] strings=file.list();
        for (String str:strings) {
            System.out.println(str);
        }
    }

拓展 1 :并计算指定目录占用空间的大小

 @Test
    /**
     * 遍历指定目录所有文件名称,包括子文件目录中的文件。
     * 并计算指定目录占用空间的大小
     */
    public void test3(){
        File file = new File("c:");
        String[] strings=file.list();
        File[] files=file.listFiles();
        int sum=0;
        for (String str:strings) {
            System.out.println(str);
        }
        for (File file1:files) {
            sum+=file1.length();
        }
        System.out.println(sum);
    }

拓展 2 :删除指定文件目录及其下的所有文件

public void deleteAll(File file){
        if(file==null||!file.exists()){
            System.out.println("文件路径输入有误!");
        }else{
            File[] files = file.listFiles();
            //遍历该目录下的文件对象
            for (File f: files){
                //打印文件名
                String name = file.getName();
                System.out.println(name);
                //判断子目录是否存在子目录,如果是文件则删除
                if (f.isDirectory()){
                    deleteFile(f);
                }else {
                    f.delete();
                }
            }
            //删除空文件夹  for循环已经把上一层节点的目录清空。
            file.delete();
 
        }
 
    }

二、IIO流原理及流的分类

IO原理

I/O Input/Output 的缩写, I/O 技术是非常实用的技术,用于 处理设备之间的数据传输 。如读 / 写文件,网络通讯等。

Java 程序中,对于数据的输入 / 输出操作以 “流 (stream)

方式进行。

  java.io 包下提供了各种“流”类和接口,用以获取不同种类的

数据,并通过 标准的方法 输入或输出数据。

 输入 input : 读取外部数据(磁盘、光盘等存储设备的数据)到 程序(内存)中。

 输出 output : 将程序(内存)数据输出到磁盘、光盘等存储设 备中。

流的分类

按操作 数据单位 不同分为: 字节流 (8 bit) ,字符流 (16 bit)

按数据流的 流向 不同分为: 输入流,输出流

按流的 角色 的不同分为: 节点流,处理流

节点流:直接从数据源或目的地读写数据

处理流:不直接连接到数据源或目的地,而是“连接”在已存

在的流(节点流或处理流)之上,通过对数据的处理为程序提

供更为强大的读写功能。

InputStream & Reader

InputStream Reader 是所有 输入流 的基类。

 InputStream (典型实现: FileInputStream )

 int read()

 int read(byte[] b)

 int read(byte[] b, int off, int len)

 Reader (典型实现: FileReader )

 int read()

 int read(char [] c)

 int read(char [] c, int off, int len)

 程序中打开的文件 IO 资源不属于内存里的资源,垃圾回收机制无法回收该资

源,所以应该 显式关闭文件 IO 资源 。

 FileInputStream 从文件系统中的某个文件中获得输入字节。 FileInputStream

用于读取非文本数据之类的原始字节流。要读取字符流,需要使用 FileReader

OutputStream & Writer

 OutputStream 和 Writer 也非常相似:

 void write( int b / int c );

 void write( byte[] b / char[] cbuf );

 void write( byte[] b / char[] buff, int off, int len);

 void flush();

 void close(); 需要先刷新,再关闭此流

 因为字符流直接以字符作为操作单位,所以 Writer 可以用字符串来替换字符数组,

即以 String 对象作为参数

 void write(String str);

 void write(String str, int off, int len);

 FileOutputStream 从文件系统中的某个文件中获得输出字节。 FileOutputStream

用于写出非文本数据之类的原始字节流。要写出字符流,需要使用 FileWriter

三、节点流(或文件流)

读取文件

1.利用字符流

@Test
    /**
     * 读取文件
     */
    public void test1() {
        FileReader fr= null;
        try {
            //1.建立一个流文件,将已存在的文件加载进流
            fr = new FileReader("Hello.txt");
            //2.创建一个存放临时文件的char型数组
            char[] buffer=new char[1024];
            //3.调用对象流的方法将文件读到数组中
            int len=0;
            while ((len=fr.read(buffer))!=-1) {
                System.out.println(new String(buffer, 0, len));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.关闭文件流
            if (fr!=null){
                try {
                    fr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
 
        }

2.利用字节流

@Test
    /**
     * 2.利用字节流读取文件
     */
    public void test2() {
        FileInputStream fi= null;
        try {
            //1.建立一个流文件,将已存在的文件加载进流
            fi = new FileInputStream("Hello.txt");
            //2.创建一个存放临时文件的char型数组
            byte[] buffer=new byte[1024];
            //3.调用对象流的方法将文件读到数组中
            int len=0;
            while ((len=fi.read(buffer))!=-1) {
                System.out.println(new String(buffer, 0, len));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //4.关闭文件流
            if (fi!=null){
                try {
                    fi.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
 
        }
 
    }

写入文件

1.利用字符流写文件

 @Test
    /**
     * 1.利用字符流写文件
     */
    public void test1(){
        FileWriter fw= null;
        try {
            //1.创建流文件,建立数据存放文件
            fw = new FileWriter("Hello.txt");
            //2.调用对象的写入方法,将数据存入文件
            fw.write("加油!!!");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //3.关闭流文件
            if(fw!=null){
                try {
                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
 
        }
 
    }

注意点

定义文件路径时,注意:可以用“ /” 或者“\\”。

 在 写入 一个文件时,如果使用构造器 FileOutputStream(file) ,则 目录下有同名文 件将被覆盖。

 如果使用构造器 FileOutputStream(file,true) ,则目录下的同名文件不会被覆盖,  在文件内容末尾追加内容。

 在 读取 文件时,必须保证该文件已存在,否则报异常。

 字节流操作字节,比如: .mp3 , .avi , .rmvb , mp4 , .jpg , .doc , .ppt

 字符流操作字符,只能操作普通文本文件。最常见的文本文 件:.txt , .java , .c , .cpp 等语言的源代码。尤其注意 .doc,excel,ppt 这些不是文本文件。

四、缓冲流

为了提高数据读写的速度 Java API 提供了带缓冲功能的流类,在使用这些流类时,会创建一个内部缓冲区数组,缺省使用 8192 个字节 (8Kb) 的缓冲区

 缓冲流要“套接”在相应的节点流之上,根据数据操作单位可以把缓冲流分为:

 BufferedInputStream 和 BufferedOutputStream

 BufferedReader 和 BufferedWriter

 当读取数据时,数据按块读入缓冲区,其后的读操作则直接访问缓冲区

 当使用 BufferedInputStream 读取字节文件时, BufferedInputStream 会一次性从

文件中读取 8192 个 (8Kb) ,存在缓冲区中,直到缓冲区装满了,才重新从文件中

读取下一个 8192 个字节数组。

 向流中写入字节时,不会直接写到文件,先写到缓冲区中直到缓冲区写满,

BufferedOutputStream 才会把缓冲区中的数据一次性写到文件里。使用方法

flush() 可以强制将缓冲区的内容全部写入输出流

 关闭流的顺序和打开流的顺序相反。只要关闭最外层流即可,关闭最外层流也

会相应关闭内层节点流

 flush() 方法的使用:手动将 buffer 中内容写入文件

 如果是带缓冲区的流对象的 close() 方法,不但会关闭流,还会在关闭流之前刷

新缓冲区,关闭后不能再写出

练习: 实现图片加密操作。

@Test
    /**
     * 实现对图片的加密
     */
    public void encrypt()  {
        BufferedInputStream bis= null;
        BufferedOutputStream bos= null;
        try {
            bis = new BufferedInputStream(new FileInputStream("20204.jpg"));
            bos = new BufferedOutputStream(new FileOutputStream("20206.jpg"));
            byte[] buffer=new byte[1024];
            int len=0;
            while((len=bis.read())!=-1){
                bos.write(len^5);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(bis!=null){
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(bos!=null){
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
 
 
        }
 
    }
    @Test
    /**
     * 实现对图片的解密
     */
    public void decrypt()  {
        BufferedInputStream bis= null;
        BufferedOutputStream bos= null;
        try {
            bis = new BufferedInputStream(new FileInputStream("20206.jpg"));
            bos = new BufferedOutputStream(new FileOutputStream("20208.jpg"));
            byte[] buffer=new byte[1024];
            int len=0;
            while((len=bis.read())!=-1){
                bos.write(len^5);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(bis!=null){
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(bos!=null){
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
 
 
        }
 
    }

五、转换流

转换流提供了在字节流和字符流之间的转换

Java API 提供了两个转换流:

InputStreamReader :将 InputStream 转换为 Reader

OutputStreamWriter :将 Writer 转换为 OutputStream

字节流中的数据都是字符时,转成字符流操作更高效。

很多时候我们使用转换流来处理文件乱码问题。实现编码和解码的功能

  public static void main(String[] args) {
        BufferedReader br= null;
        BufferedWriter bw= null;
        try {
            FileInputStream fis = new FileInputStream("D:/IDEA/day01/Smile.txt");
            InputStreamReader isr=new InputStreamReader(fis);
            br = new BufferedReader(isr);
            FileOutputStream fos=new FileOutputStream("new.txt");
            OutputStreamWriter osw=new OutputStreamWriter(fos);
            bw = new BufferedWriter(osw);
            String str;
            while((str=br.readLine())!=null){
                bw.write(str);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(bw!=null){
                try {
                    bw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(br!=null){
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
 
 
    }
    @Test
    public void test()
    {
        FileReader fr= null;
        try {
            fr = new FileReader("Hello.txt");
            char[] buffer=new char[1024];
            int len=0;
            while((len=fr.read(buffer))!=-1){
                System.out.println(new String(buffer, 0, len));
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(fr!=null){
                try {
                    fr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
 
    }

目录
相关文章
|
2月前
|
存储 Java
【IO面试题 四】、介绍一下Java的序列化与反序列化
Java的序列化与反序列化允许对象通过实现Serializable接口转换成字节序列并存储或传输,之后可以通过ObjectInputStream和ObjectOutputStream的方法将这些字节序列恢复成对象。
|
3月前
|
Java 大数据
解析Java中的NIO与传统IO的区别与应用
解析Java中的NIO与传统IO的区别与应用
|
21天前
|
安全 Java API
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
String常量池、String、StringBuffer、Stringbuilder有什么区别、List与Set的区别、ArrayList和LinkedList的区别、HashMap底层原理、ConcurrentHashMap、HashMap和Hashtable的区别、泛型擦除、ABA问题、IO多路复用、BIO、NIO、O、异常处理机制、反射
【Java面试题汇总】Java基础篇——String+集合+泛型+IO+异常+反射(2023版)
|
15天前
|
Java 大数据 API
Java 流(Stream)、文件(File)和IO的区别
Java中的流(Stream)、文件(File)和输入/输出(I/O)是处理数据的关键概念。`File`类用于基本文件操作,如创建、删除和检查文件;流则提供了数据读写的抽象机制,适用于文件、内存和网络等多种数据源;I/O涵盖更广泛的输入输出操作,包括文件I/O、网络通信等,并支持异常处理和缓冲等功能。实际开发中,这三者常结合使用,以实现高效的数据处理。例如,`File`用于管理文件路径,`Stream`用于读写数据,I/O则处理复杂的输入输出需求。
|
1月前
|
数据采集 Java 数据挖掘
Java IO异常处理:在Web爬虫开发中的实践
Java IO异常处理:在Web爬虫开发中的实践
|
2月前
|
Java 数据处理
Java IO 接口(Input)究竟隐藏着怎样的神秘用法?快来一探究竟,解锁高效编程新境界!
【8月更文挑战第22天】Java的输入输出(IO)操作至关重要,它支持从多种来源读取数据,如文件、网络等。常用输入流包括`FileInputStream`,适用于按字节读取文件;结合`BufferedInputStream`可提升读取效率。此外,通过`Socket`和相关输入流,还能实现网络数据读取。合理选用这些流能有效支持程序的数据处理需求。
28 2
|
2月前
|
XML 存储 JSON
【IO面试题 六】、 除了Java自带的序列化之外,你还了解哪些序列化工具?
除了Java自带的序列化,常见的序列化工具还包括JSON(如jackson、gson、fastjson)、Protobuf、Thrift和Avro,各具特点,适用于不同的应用场景和性能需求。
|
2月前
|
缓存 Java
【IO面试题 一】、介绍一下Java中的IO流
Java中的IO流是对数据输入输出操作的抽象,分为输入流和输出流,字节流和字符流,节点流和处理流,提供了多种类支持不同数据源和操作,如文件流、数组流、管道流、字符串流、缓冲流、转换流、对象流、打印流、推回输入流和数据流等。
【IO面试题 一】、介绍一下Java中的IO流
|
2月前
|
Java
"揭秘Java IO三大模式:BIO、NIO、AIO背后的秘密!为何AIO成为高并发时代的宠儿,你的选择对了吗?"
【8月更文挑战第19天】在Java的IO编程中,BIO、NIO与AIO代表了三种不同的IO处理机制。BIO采用同步阻塞模型,每个连接需单独线程处理,适用于连接少且稳定的场景。NIO引入了非阻塞性质,利用Channel、Buffer与Selector实现多路复用,提升了效率与吞吐量。AIO则是真正的异步IO,在JDK 7中引入,通过回调或Future机制在IO操作完成后通知应用,适合高并发场景。选择合适的模型对构建高效网络应用至关重要。
40 2
|
2月前
|
Java Android开发
解决Android编译报错:Unable to make field private final java.lang.String java.io.File.path accessible
解决Android编译报错:Unable to make field private final java.lang.String java.io.File.path accessible
153 1
下一篇
无影云桌面