Java IO基础(同步阻塞IO)

简介: Java IO是一套Java 用来读写数据(输入和输出)的API,大部分程序都需要处理一些输入,并由输入产生一些输出(PS: 输入和输出是相对CPU而言的,input 就是从外面到CPU,output就是从CPU到外面,CPU是主人公)。java.io 包下有大约80多个类,大概可以分成四组:

概述

Java IO是一套Java 用来读写数据(输入和输出)的API,大部分程序都需要处理一些输入,并由输入产生一些输出(PS: 输入和输出是相对CPU而言的,input 就是从外面到CPU,output就是从CPU到外面,CPU是主人公)。java.io 包下有大约80多个类,大概可以分成四组:

1.基于字节操作的I/O接口: InputStream和OutputStream

2.基于字符操作的I/O接口:Writer和Reader

3.基于磁盘操作的I/O接口:File

4.基于网络操作的I/O接口:Socket

java.io 包下的类如下:

1aa45a1ae823cc916ac66629d0ad17d4_watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTQ1MzQ4MDg=,size_16,color_FFFFFF,t_70.png

File类

Java IO API中的File类可以让你访问底层文件系统,通过File类。你可以做到如下几点:

1.检测文件是否存在 (file.exists())

2.读取文件长度 (file.length())

3.重命名或者移动文件(file.renameTo(new File(“c:\data\new-file.txt”));)

4.删除文件(file.delete())

5.检测某个路径是文件还是目录。(file.isDirectory())

6.读取目录中的文件列表。(String[] fileNames = file.list())

PS: 在项目中用相对路径读取文件

运用相对路径读取文件,其实就是要找到Java编译(class 文件所在的目录)后的存放目录,然后在该目录下找文件。读取方法有如下两种。

public class RelativePath {
    public static void main(String[] args) {
//        方法一
        String fileName = ReaderTest.class.getResource("/inputTest.txt").getFile();
        System.out.println("*****方法一相对路径读取到的文件地址:"+fileName);
//        方法二
        String fileName1 = Thread.currentThread().getContextClassLoader().getResource("inputTest.txt").getFile();
        System.out.println("*****方法二相对路径读取到的文件地址:"+fileName1);
    }
}

运行结果:

401ccceeae00b9a9d3926613520b8579_watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTQ1MzQ4MDg=,size_16,color_FFFFFF,t_70.png

输入和输出

输入流 用来表示那些从不同数据源产生输入的类。这些数据源包括:

1.字节数组

2.String 对象

3.文件

4.“管道”,工作方式与实际管道类似,即,从一端输入,从另一端输出

5.一个由其他种类的流组成的序列,以便我们可以将它们收集合并到一个流内

输出流: 决定输出所要去往的目标,目标包括:

字节数组

文件

管道

基于字节操作的I/O接口: InputStream和OutputStream

InputStream 的类图

ea47771e94902b8401924e3be897de08_watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTQ1MzQ4MDg=,size_16,color_FFFFFF,t_70.png

每个子类的功能以及使用如下图表所示:

8df66266d03ef706a0a834a078624638_watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTQ1MzQ4MDg=,size_16,color_FFFFFF,t_70.png

运用InputStream的实现类读取文件

1.方法1️⃣

/**
     * 以字节为单位读取文件,常用于读二进制文件,如图片、声音、影像等文件。
     * 当然也是可以读字符串的。
     *
     * @param fileName
     */
    public static void readString1(String fileName) throws IOException {
//        FileInputStream 用于读取诸如图像数据之类的原始字节流,读取字符流,请使用FileReader
        InputStream is = new FileInputStream(fileName);
        StringBuilder stringBuilder;
        try {
            stringBuilder = new StringBuilder();
            byte[] bytes = new byte[1024];
            int len;
            while ((len=is.read(bytes))>0) {
                stringBuilder.append(bytes,0,len);
            }
        } finally {
            if (is != null) {
                is.close();
            }
        }
        System.out.println("读取到的结果:" + stringBuilder.toString());
    }

2.方法2️⃣

 

/**
     * 按字节读取字符串,一次性读取完
     * @param fileName
     * @throws IOException
     */
    public static void readString2(String fileName) throws IOException {
        InputStream inputStream = new FileInputStream(fileName);
        try {
            // size  为字串的长度 ,这里一次性读完
            byte[] bytes = new byte[inputStream.available()];
            inputStream.read(bytes);
            System.out.println("读取到的结果是:"+new String(bytes,"UTF-8"));
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }
        }
    }

按行读取数据

InputStreamReader   inputStreamReader = new InputStreamReader(new FileInputStream(file),"UTF-8");
         BufferedReader  bufferedReader = new BufferedReader(inputStreamReader);
      while (StringUtils.isNotBlank(line = bufferedReader.readLine())) {
          System.out.println("读取到的结果是:"+line);
     }

OutputStream 的类图

b187d7fa4e724786ffde5280cd98e513_20190609203902434.png

每个子类的功能和使用如下图表所示:

a906029aa841ecaadc599af58e9bcfb8_watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTQ1MzQ4MDg=,size_16,color_FFFFFF,t_70.png

运用OutputStream的实现类写入文件

1.方法1️⃣

使用FileOutputStream进行写入。

/**
     * 使用FileOutputStream
     * @param file
     * @throws IOException
     */
    public static void  writeStringToFile1(File file) throws IOException {
        FileOutputStream fos = new FileOutputStream(file);
        try {
            fos.write("www.jay".getBytes());
            fos.flush();
        } finally {
            if (fos != null) {
                fos.close();
            }
        }
    }

2.方法2️⃣

使用PrintStream进行写入

/**
     * 使用PrintStream写入
     * @param file
     * @throws FileNotFoundException
     */
    public static void writeStringToFile2(File file) throws FileNotFoundException {
        PrintStream printStream = null;
        try {
            printStream = new PrintStream(new FileOutputStream(file));
            printStream.append("你好");
            printStream.append("java");
        } finally {
            if (printStream != null) {
                printStream.close();
            }
        }
    }

3.方法3

通过 IOUtil 进行数据操作

ByteArrayOutputStream outputStream  = new ByteArrayOutputStream();
   IOUtils.copy(inputStream, outputStream);
   byte[]  buffer=outputStream.toByteArray()

或者

byte[] buff = new byte[1024];
        BufferedInputStream bis = null;
        OutputStream os = null;
        try {
            os = new ByteArrayOutputStream();
            bis = new BufferedInputStream(stream);
            int len;
            while ((len = bis.read(buff)) >0) {
                os.write(buff, 0, len);
            }
              os.flush();
        }catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (bis != null) {
                IOUtils.closeQuietly(bis);
            }
            IOUtils.closeQuietly(os);
        }

基于字符操作的I/O接口:Writer和Reader

Reader 和Writer 与InputStream和OutputStream 的最大区别是,InputStream和OutputStream是基于字节操作的I/O接口。而Reader 和Writer是基于字符操作I/O 接口。通过InputStreamReader适配器可以把InpuStream转换成Reader。通过OutputStreamWriter 适配器可以把OutputStream 转换成Writer。

如下图表示在两个继承层次结构中,信息的来源于去处。

17f8b3b90abaa960cb55cd3e46687f8a_watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTQ1MzQ4MDg=,size_16,color_FFFFFF,t_70.png

Reader 的类图

0655d1e44825908e02c8bb0cdc7c411f_watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTQ1MzQ4MDg=,size_16,color_FFFFFF,t_70.png

运用Reader的实现类读取文件内容(只能读取字符流)

1.方法1️⃣

 

public static void readFileToString1(String fileName ) throws IOException {
        File file = new File(fileName);
        FileReader fileReader = new FileReader(file);
        int length = Integer.valueOf(String.valueOf(file.length()));
  //定义一个大小等于文件大小的字符数组
        char[] chars = new char[length];
        StringBuilder str = new StringBuilder();
        try {
            int data;
            while ((data=fileReader.read(chars))>0) {
                System.out.println("读取到的字符是="+data);
                str.append(chars);
            }
            System.out.println("读取到的结果:"+str.toString());
        } finally {
            if (fileReader != null) {
                fileReader.close();
            }
        }
    }

2.方法2️⃣

/**
     * InputStreamReader+BufferedReader读取字符串 ,
     * InputStreamReader类是从字节流到字符流的桥梁,
     * 按行读对于要处理的格式化数据是一种读取的好方式
     * @param fileName
     * @throws IOException
     */
    public static void readFileToString2(String fileName) throws IOException {
        BufferedReader bufferedReader = new BufferedReader(new FileReader(fileName));
        try {
            StringBuilder stringBuilder = new StringBuilder();
            String data = null;
            while ((data = bufferedReader.readLine()) != null) {
                stringBuilder.append(data);
            }
            System.out.println("读取到的结果:"+stringBuilder.toString());
        } finally {
            if (bufferedReader != null) {
                bufferedReader.close();
            }
        }
    }

Writer 的类图

98bf0b4717c25b8528521809cc5f246e_watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTQ1MzQ4MDg=,size_16,color_FFFFFF,t_70.png

运用Writer的实现类写入内容到文件

1.方法1️⃣

/**
     * 使用BufferedWriter写入
     * @param file
     * @throws IOException
     */
    public static void writeStringToFile1(FileWriter file) throws IOException {
        BufferedWriter bufferedWriter = new BufferedWriter(file);
        bufferedWriter.append("bufferedWriter");
        bufferedWriter.append("测试2111");
        bufferedWriter.close();
    }

2.方法2️⃣

/**
     * 使用PrintWriter写入
     * @param fileWriter
     * @throws IOException
     */
    public static void writeStringToFile2(FileWriter fileWriter) throws IOException {
        PrintWriter printWriter = new PrintWriter(fileWriter);
        printWriter.append("printWriter");
        printWriter.append("实验");
        printWriter.close();
    }

3.方法三

利用字节流向文件中写入数据。

//创建文件
        File file = new File("test.txt");
        //写入数据
        OutputStream os = null;
        try {
            os = new FileOutputStream(file);
            String testStr = new String("I LOVE YOU");
            os.write(testStr.getBytes());
            os.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (os != null) {
                os.close();
            }
        }

总结

本文首先介绍了java.io 包中的重要接口和类,如InputStream接口,OutputStream接口,Reader接口和Writer接口。然后,通过几个小demo阐述了如何运用这些接口的实现类来操作文件。希望多读者朋友有所帮助。

源代码

https://github.com/XWxiaowei/JavaCode/tree/master/io-study-demo

相关文章
|
2月前
|
Java
java 中 IO 流
Java中的IO流是用于处理输入输出操作的机制,主要包括字节流和字符流两大类。字节流以8位字节为单位处理数据,如FileInputStream和FileOutputStream;字符流以16位Unicode字符为单位,如FileReader和FileWriter。这些流提供了读写文件、网络传输等基本功能。
59 9
|
3月前
|
存储 消息中间件 安全
JUC组件实战:实现RRPC(Java与硬件通过MQTT的同步通信)
【10月更文挑战第9天】本文介绍了如何利用JUC组件实现Java服务与硬件通过MQTT的同步通信(RRPC)。通过模拟MQTT通信流程,使用`LinkedBlockingQueue`作为消息队列,详细讲解了消息发送、接收及响应的同步处理机制,包括任务超时处理和内存泄漏的预防措施。文中还提供了具体的类设计和方法实现,帮助理解同步通信的内部工作原理。
JUC组件实战:实现RRPC(Java与硬件通过MQTT的同步通信)
|
3月前
|
存储 缓存 Java
java基础:IO流 理论与代码示例(详解、idea设置统一utf-8编码问题)
这篇文章详细介绍了Java中的IO流,包括字符与字节的概念、编码格式、File类的使用、IO流的分类和原理,以及通过代码示例展示了各种流的应用,如节点流、处理流、缓存流、转换流、对象流和随机访问文件流。同时,还探讨了IDEA中设置项目编码格式的方法,以及如何处理序列化和反序列化问题。
102 1
java基础:IO流 理论与代码示例(详解、idea设置统一utf-8编码问题)
|
2月前
|
Java 调度
Java 线程同步的四种方式,最全详解,建议收藏!
本文详细解析了Java线程同步的四种方式:synchronized关键字、ReentrantLock、原子变量和ThreadLocal,通过实例代码和对比分析,帮助你深入理解线程同步机制。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
Java 线程同步的四种方式,最全详解,建议收藏!
|
3月前
|
安全 Java 开发者
Java多线程中的`wait()`、`notify()`和`notifyAll()`方法,探讨了它们在实现线程间通信和同步中的关键作用
本文深入解析了Java多线程中的`wait()`、`notify()`和`notifyAll()`方法,探讨了它们在实现线程间通信和同步中的关键作用。通过示例代码展示了如何正确使用这些方法,并分享了最佳实践,帮助开发者避免常见陷阱,提高多线程程序的稳定性和效率。
63 1
|
3月前
|
存储 缓存 算法
如何优化阻塞IO的性能?
【10月更文挑战第6天】如何优化阻塞IO的性能?
67 5
|
3月前
|
数据库
同步IO模型是一种常见的编程模型
【10月更文挑战第5天】同步IO模型是一种常见的编程模型
25 2
|
3月前
|
Java 数据处理 开发者
揭秘Java IO流:字节流与字符流的神秘面纱!
揭秘Java IO流:字节流与字符流的神秘面纱!
52 1
|
3月前
|
自然语言处理 Java 数据处理
Java IO流全解析:字节流和字符流的区别与联系!
Java IO流全解析:字节流和字符流的区别与联系!
128 1
|
4月前
|
Java 大数据 API
Java 流(Stream)、文件(File)和IO的区别
Java中的流(Stream)、文件(File)和输入/输出(I/O)是处理数据的关键概念。`File`类用于基本文件操作,如创建、删除和检查文件;流则提供了数据读写的抽象机制,适用于文件、内存和网络等多种数据源;I/O涵盖更广泛的输入输出操作,包括文件I/O、网络通信等,并支持异常处理和缓冲等功能。实际开发中,这三者常结合使用,以实现高效的数据处理。例如,`File`用于管理文件路径,`Stream`用于读写数据,I/O则处理复杂的输入输出需求。
271 12