栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java I/O流入门

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java I/O流入门

I/O流入门
  • 前言
  • 一、IO简介
    • 1、什么是IO流?
    • 2、数据源(Data Source)
    • 3、流的概念
    • 4、Java四大IO抽象类
    • 5、IO流分类
    • 6、Java IO流体系
  • 二、IO流入门案例
  • 三、File类的使用
    • 1、File的常见方法
  • 四、常用流对象
    • 1、文件字节流
    • 2、定义文件拷贝工具类
    • 3、文件字符流
    • 4、为每行添加行号
    • 5、转换流
    • 6、字符输出流
    • 7、字节数组流
    • 8、数据流
    • 9、对象流
    • 10、随机访问流
  • 五、Apache IO包
    • 1、下载Apache IO包
    • 2、添加jar包
    • 3、FileUtils
    • 4、IOUtils
  • 总结
  • 参考文献

前言

Java IO流入门,了解IO简介、IO流入门案例、File类的使用、常用流对象、Apache IO包。

一、IO简介 1、什么是IO流?

1)与外部设备进行通信,进行数据交换,即Input/Output data。
2)Java IO API 屏蔽外部设备的差异性。

2、数据源(Data Source)

以程序为参考对象。
1)源设备:向程序传输所需数据的设备。
2)目的设备:程序将数据存储到外部的设备。

3、流的概念

流是一个抽象、动态的概念,这里指的数据流,数据以一定容量为单位不断流入程序或外部设备。
数据流即一连串连续动态的数据集合。

4、Java四大IO抽象类

这四个抽象类奠定了IO的基础,分别为:
1)字节流,以一字节(8bit)作为基本单位。
A)InputStream
int read(),返回一个0-255的十进制 或 -1,分别表示读取的字符和已读完。
void close(),关闭字节流输入对象,释放相关系统资源。
B)OutputStream
void write(int n),向目的设备写一个字节的二进制。
void close(),关闭字节流输出对象,释放相关系统资源。
2)字符流,以一个字符为基本单位。
A)Reader
int read(),读取字符数据,返回一个0-65535 的十进制,即Unicode字符,或者返回-1。分别表示读出的字符和已读完。
void close(),关闭字节流输出对象,释放相关系统资源。
B)Writer
void write(int n),向目的设备写入一个字符的二进制。
void close(),关闭字节流输出对象,释放相关系统资源。

5、IO流分类

1)按流方向
A)输入流:Data Source -> Program
B)输出流:Program -> Destination
2)按处理单元
A)字节流,以字节为基本单位。
B)字符流,以字符为基本单位,即Unicode字符。
3)按处理对象
A)节点流,直接链接到数据源。
B)处理流,对节点流的包装,让流有更加强大的功能,处理流的流对象。如BufferedInputStream、BufferedOutputStream。

6、Java IO流体系

重点类介绍
1)File,处理目录或文件,包装成类,就能够更好的操作目录和文件。
2)InputStream、OutputStream、Reader、Writer,四大基本抽象类,Java 中IO的规范。
3)FileInputStream / FileOutputStream
节点流,以字节为单位,直接操作文件。
4)ByteArrayInputStream / ByteArrayOutputStream
节点流,以字节为单位,直接处理“字节数组对象”。
5)ObjectInputStream / ObjectOutputStream
处理流,以字节为单位,操作字节流中的对象。
6)DataInputStream / DataOutputStream
处理流,以字节为单位,操作字节流中的基本数据类型与字符串类型。
7)FileReader / FileWriter
节点流,以字符为基本单位,直接操作文本文件。
8)BufferedReader / BufferedWriter
处理流,包装了Reader、Writer,增加了缓存功能,通过缓存减少等待时间来提高读写的效率。
9)BufferedInputStream / BufferedOutputStream
处理流,包装InputStream、OutputStream,增加缓存功能,提高读写效率。
10)InputStreamReader / OutputStreamWriter
处理流,将字节流对象包装成字符流对象。
11)PrintStream
处理流,包装OutputStream,方便输出字符。

二、IO流入门案例

1)只能展示0-255的字符

package com.xhu.java;

import java.io.*;

public class TestIO {
    public static void main(String[] args) {
        //1.创建字节输入流
        try (FileInputStream fis = new FileInputStream("d:/IOCase.txt")) {
            int n = 0;
            while ((n = fis.read()) != -1)
                System.out.print((char) (n));
        } catch (IOException e) {
            System.out.println(e.getMessage());
        }

    }
}

Java 异常进阶
2)展示0-65535,即Unicode字符

package com.xhu.java;

import java.io.*;
import java.util.Arrays;

public class TestIO {
    public static void main(String[] args) {
        try (FileReader fr = new FileReader("d:/IOCase.txt")) {
            StringBuilder sb = new StringBuilder();
            int n = 0;
            while ((n = fr.read()) != -1) {
                sb.append((char) n);
            }
            System.out.println(sb.toString());
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
三、File类的使用 1、File的常见方法

File 常见方法

四、常用流对象 1、文件字节流

1)FileInputStream / FileOutputStream
以字节的方式读取文件,所有文件底层都为二进制,所以这个能读取所有类型的文件和写任意类型的文件。(图像、视频、文本文件)

package com.xhu.java;
import java.io.*;
import java.util.Arrays;

public class TestIO {
    public static void main(String[] args) {
        try (FileInputStream fis = new FileInputStream("d:/生物钟.jpg");
             FileOutputStream fos = new FileOutputStream("d:生物钟副本.png")) {
            int n = 0;
            while((n = fis.read()) != -1){
                fos.write(n);
            }
            //把内存缓存的数据写入磁盘中
            fos.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

2)通过缓存区提高读写效率

上面的操作是一个一个字节去读的,一个一个去写,IO的调用次数大多,当图片太大就会很慢。
A)指定长度的字节数组作为缓存区,该长度应为2的整数幂。

	public static void main(String[] args) {
        try (FileInputStream fis = new FileInputStream("d:/生物钟.jpg");
             FileOutputStream fos = new FileOutputStream("d:生物钟副本.png")) {
            //1024位bit,缓存区
            byte[] buffer = new byte[1024];
            //每次读到buffer中的长度
            int n = 0;
            //每次读写1024位
            while((n = fis.read(buffer)) != -1){
                fos.write(buffer,0,n);
            }
            //把内存缓存的数据写入磁盘中
            fos.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

B)根据文件大小来确定buffer长度,相当于一次性读写文件,文件太大,占用内存也会很大,所以推荐小文件。

	public static void main(String[] args) {
        try (FileInputStream fis = new FileInputStream("d:/生物钟.jpg");
             FileOutputStream fos = new FileOutputStream("d:/生物钟副本.png")) {
            //1024位bit,缓存区,文件太大,内存空间占用也大
            byte[] buffer = new byte[fis.available()];
            int n = fis.read(buffer);
            fos.write(buffer, 0, n);
            //把内存缓存的数据写入磁盘中
            fos.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

C)包装流BufferedInputStream / BufferedOutputStream

缓存区慢或手动提交时,才会把处理数据。底层缓冲数组。

	public static void main(String[] args) {
        //关闭流顺序,后开先关闭
        try (FileInputStream fis = new FileInputStream("d:/生物钟.jpg");
             FileOutputStream fos = new FileOutputStream("d:/生物钟副本.png");
             BufferedInputStream bis = new BufferedInputStream(fis);
             BufferedOutputStream bos = new BufferedOutputStream(fos)) {
            int n = 0;
            //buffer的默认长度为2的13次方8192
            //private static int DEFAULT_BUFFER_SIZE = 8192;
            while ((n = bis.read()) != -1) {
                //去写缓冲区的内容,字节转十进制为n
                bos.write(n);
            }
            //把内存缓存的数据写入磁盘中
            bos.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
2、定义文件拷贝工具类
package com.xhu.java;

import java.io.*;


public class CopyFileTools {

    
    public static void copy(String source, String dest) throws IOException {
        try (FileInputStream fis = new FileInputStream(source);
             FileOutputStream fos = new FileOutputStream(dest)) {
            copyFile(fis, fos);
        } catch (IOException e) {
            throw e;
        }
    }

    
    private static void copyFile(FileInputStream fis, FileOutputStream fos) throws IOException {
        BufferedInputStream bis = new BufferedInputStream(fis);
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        int n = 0;
        while ((n = bis.read()) != -1) {
            bos.write(n);
        }
        bos.flush();
    }

}

3、文件字符流

1)FileReader / FileWriter

	public static void main(String[] args) {
        try (FileReader fr = new FileReader("d:/IOCase.txt");
             FileWriter fw = new FileWriter("d:/IOCase_copy.txt")) {
            int n = 0;
            while ((n = fr.read()) != -1) {
                fw.write(n);
            }
            fw.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

2)用buffer来提高效率

	public static void main(String[] args) throws IOException {
        try (FileReader fr = new FileReader("d:/IOCase.txt");
             FileWriter fw = new FileWriter("d:/IOCase_copy.txt");
             BufferedReader br = new BufferedReader(fr);
             BufferedWriter bw = new BufferedWriter(fw)) {
            int n = 0;
            while ((n = br.read()) != -1) {
                bw.write(n);
            }
            //换行
            bw.newline()
            bw.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
	String str = null;
    while ((str = br.readLine()) != null) {
          bw.write(str);
    }
4、为每行添加行号
	public static void main(String[] args) throws IOException {
        try (FileReader fr = new FileReader("d:/IOCase.txt");
             FileWriter fw = new FileWriter("d:/IOCase_copy.txt");
             BufferedReader br = new BufferedReader(fr);
             BufferedWriter bw = new BufferedWriter(fw)) {
            int n = 0;
            String str = null;
            StringBuilder sb = new StringBuilder();
            while ((str = br.readLine()) != null) {
                bw.write(sb.append(++n).append(":").append(str).toString());
                //读完一行就换还
                bw.newline();
                sb.delete(0, sb.length());
            }
            bw.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
5、转换流

InputStreamReader / OutputStreamWriter ,将字节流转换为字符流。
如键盘输入一行System.in,用BufferedReader 读一行,键盘输入的是字节流,而BufferedReader是字符流;显示在屏幕的System.out也是字节流,但是我们需要把它变成字符显示在屏幕上。所以需要用到转换流,即一种包装流。

package com.xhu.java;

import java.io.*;

public class TestInputStreamReader {
    public static void main(String[] args) {
        //把键盘作为数据源
        InputStream is = System.in;
        //把显示屏作为目的设备
        OutputStream os = System.out;
        try (InputStreamReader ism = new InputStreamReader(is);
             OutputStreamWriter osw = new OutputStreamWriter(os);
             BufferedReader br = new BufferedReader(ism);
             BufferedWriter bw = new BufferedWriter(osw)) {
            //输入exit为出口
            while (true) {
                //将请输入flush到屏幕上
                bw.write("请输入:");
                bw.flush();

                String str = br.readLine();
                if ("exit".equals(str)) {
                    break;
                }
                //将输入的一行flush到屏幕上
                bw.write("你输入的是:" + str);
                bw.flush();
                //手动换行
                bw.newline();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

6、字符输出流

PrintWriter自带换行(print)和flush。

public static void main(String[] args) {
        try (FileInputStream fis = new FileInputStream("d:/IOCase.txt");
             InputStreamReader isr = new InputStreamReader(fis);
             BufferedReader br = new BufferedReader(isr);
             PrintWriter pw = new PrintWriter("d:/IOCase_copy.txt");
        ) {
            int n = 0;
            String str = null;
            StringBuilder sb = new StringBuilder();
            while ((str = br.readLine()) != null) {
                pw.println(sb.append((++n)).append(',').append(str));
                sb.delete(0, sb.length());
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
7、字节数组流

ByteArrayInputStream / ByteArrayOutStream
以字节数组为处理对象,进行读取和写入。

package com.xhu.java;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

public class TestByteArrayInputStream {
    public static void main(String[] args) {
        byte[] bytes = "abc".getBytes();
        try (ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
             ByteArrayOutputStream baos = new ByteArrayOutputStream();) {
            int n = 0;
            while ((n = bais.read()) != -1) {
                //写回字符数组
                baos.write(n);
            }
            //得到字节数组
            byte[] res = baos.toByteArray();
            for (byte b : res) {
                System.out.print((char) b);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

8、数据流

DataInputStream / DataOutputStream
字节和字符流便于存储和读取Java中的基本数据类型。

package com.xhu.java;

import java.io.*;

public class TestDataInputStream {
    public static void main(String[] args) {
        try (DataOutputStream dps = new DataOutputStream(new BufferedOutputStream(new FileOutputStream("d:/data.txt")));
             DataInputStream dis = new DataInputStream(new FileInputStream("d:/data.txt"))) {
            int[] data = new int[]{1122211111, 2, 3};
            for (int n : data) {
                dps.writeInt(n);
            }
            dps.flush();
            int n = 3;
            while (n-- != 0) {
                System.out.println(dis.readInt());
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
9、对象流

将对象以二进制的形式进行输入和写出。
1)序列化和反序列化
含义)将Java对象转化为字节序列,为序列化;将二进制序列转化为Java对象,为反序列化。
作用)将对象持久化;网络通信。
序列化类)ObjectInputStream / ObjectOutputStream
writeObject(Object obj),将obj序列化,然后再写到目标输出流中。
Object readObject(),从数据流中读出序列数据,然后将字节序列反序列化为Object对象。
Serializable)一个空接口,起标记作用,只有实现了这个接口的类,其对象才能被序列化。

package com.xhu.java;

import java.io.*;

public class TestObjectInputStream {
    public static void main(String[] args) {
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("d:/data.txt"));
             ObjectInputStream ois = new ObjectInputStream(new FileInputStream("d:/data.txt"));
        ) {
            Person[] ps = new Person[]{new Person("林森"), new Person("李")};
            oos.writeInt(ps.length);
            for (Person p : ps) {
                oos.writeObject(p);
            }
            //oos.writeObject(null);
            //oos.flush();
            int len = ois.readInt();
            Object obj = null;
            while (len-- > 0) {
                System.out.println(((Person) ois.readObject()).name);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

10、随机访问流

1)RandomAccessFile
作用1)既可以读入文件,也可以写出文件。
作用2)可以访问文件的任意位置,不像其它流只能顺序读取。
核心函数)
A)RandomAccessFile(String name,String mode),name为文件名,mode为流的访问权限,如r(读)、rw(可读写)。
定位函数)seek(long a),定位流对象读写的位置,a是离文件头的字节数。
getFilePointer(),获取当前文件指针位置。

package com.xhu.java;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;

public class TestRandomAccessFile {
    public static void main(String[] args) {
        try (RandomAccessFile raf = new RandomAccessFile("d:data.txt", "rw")) {
            int[] data = new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
            for (int n : data) {
                raf.writeInt(n);
            }
            raf.writeInt(Integer.MAX_VALUE);
            //把指针移回来
            raf.seek(0);
            int n = 0;
            while ((n = raf.readInt()) != Integer.MAX_VALUE) {
                System.out.println(n);
                //打印偶数,int 4个字节,当前位置加4个字节就跳过了一位整数。
                raf.seek(raf.getFilePointer() + 4);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

注:当文件作为数据源或目标时,可以使用File类来表示。File file = new File("d:a.txt"); FileReader fr = new FileReader(file);

五、Apache IO包

为了简化实际开发中复杂的IO操作代码,第三方Apache提供了IO包来简化许多复杂繁琐的IO操作。
Apache-commons工具包中提供了IOUtils / FileUtils类。

1、下载Apache IO包

下载地址:commons.apache.org

2、添加jar包



3、FileUtils

进入docs查看API参考文档,该类提供了很多方法,功能强大。

package com.xhu.java;

import org.apache.commons.io.FileUtils;

import java.io.*;

public class TestFileUtils {
    public static void main(String[] args) throws IOException {
        File file = new File("d:data.txt");
        //读取所有内容
        String allContent = FileUtils.readFileToString(file, "UTF-8");
        System.out.println(allContent);
        //复制文件
        FileUtils.copyToFile(new FileInputStream(file), new File("d:data_copy.txt"));
        //拷贝文件夹
        FileUtils.copyDirectory(new File("d:/file"), new File("d:/file_copy"), new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                return pathname.isDirectory() || pathname.getName().endsWith(".txt") ? true : false;
            }
        });
    }
}

4、IOUtils

toString:将输入流或数组中的内容转化为字符串。其它查API参考文档。

package com.xhu.java;

import org.apache.commons.io.IOUtils;

import java.io.FileInputStream;
import java.io.IOException;

public class TestIOUtils {
    public static void main(String[] args) throws IOException {
        //字节转字符串
        String allContent = IOUtils.toString(new FileInputStream("d:data.txt"), "utf-8");
        System.out.println(allContent);
    }
}

总结

1)输入流、输出流、节点流、处理流
2)序列化、反序列化
3)常用流对象、FileUtils、IOUtils

参考文献

[1] [JDK 1.12]
[2] Java SE oldLu
[3] Apache IO

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/571408.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号