Java学习42-Java 流(Stream)、文件(File)和IO - FileReader\FileWriter的使用

news2024/11/29 16:41:35

IO流

IO流的概述,分类等

Java程序中,对于数据的输入输出以stream方式进行,可以看作是一种数据的流动。
IO流中的IO是Input和Output的缩写,是非常实用的技术,用于处理设备之间的数据传输。读写文件,网络通讯等。

(以下视角,都是站在程序(内存)内部角度观察的。)
输入Input:读取外部数据(磁盘,光盘等存储设备的数据)到程序(内存)中
输出Output:将程序(内存)数据输出到磁盘,光盘等存储设备中

流的分类:

java.io包下提供了各种“流”类和接口,用以获取不同种类的数据,并通过下列方法输入或输出数据。

  • 按数据的流向不同分为:输入流和输出流。

    • 输入流:把数据从其他设备上读取到内存中的流。(以InputStream / Reader结尾)
    • 输出流:把数据从内存中写出到其他设备上的流。(以OutputStream / Writer结尾)
  • 按操作数据单位的不同分为:字节流(8 bit)和字符流(16 bit)

    • 字节流: 以字节为单位,读写数据的流。字节Byte是计算机数据处理的基本单位,通常由8位(bit)组成。(以InputStream, OutputStream结尾)
    • 字符流:以字符为单位,读写数据的流。字符Character用于表示文本中的单个字母、数字或符号。在Java中,char是一个基本数据类型,char类型占用16位(2字节)。(以Reader Writer结尾)
  • 根据IO流的角色不同分为节点流和处理流。

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

在这里插入图片描述

    • 处理流:不直接连接到数据源或目的地,而是连接在以存在的流(节点流或处理流)之上,通过对数据的处理为程序提供更为强大的读写功能。

在这里插入图片描述

流的分类图示:

在这里插入图片描述

流的API

java的IO流共涉及40多个类,实际上非常规则,都是从如下4个抽象类派生出来的。

抽象基类输入流输出流
字节流InputStreamOutputStream
字符流ReaderWriter

由这四个类派生出来的子类名称都是以其父类名作为子类名后缀。

分类字节输入流字节输出流字符输入流字符输出流
抽象基类InputStreamOutputStreamReaderWriter
访问文件FileInputStreamFileOutputStreamFileReaderFileWriter
访问数组ByteArrayInputStreamByteArrayOutputStreamCharArrayReaderCharArrayWriter
访问管道PipeInputStreamPipeOutputStreamPipedReaderPipedWriter
访问字符串StringReaderStringWriter
缓冲流BufferedInputStreamBufferedOutputStreamBufferedReaderBufferedWritter
转换流InputStreamReaderOutputStreamWriter
对象流ObjectInputStreamObjectOutputStream
FilterInputStreamFilterOutputStreamFilterReaderFilterWriter
打印流PrintStreamPrintWriter
推回输入流PushbackInputStreamPushbackReader
特殊流DataInputStreamDataOutputStream

总结一下:

抽象基类(基本类)4个节点流(也称文件流,能处理文件)
InputStreamFileInputStream
OutputStreamFileOutputStream
ReaderFileReader
WriterFileWriter

说明:本章虽然涉及到的流很多,但是使用流进行数据的读写操作是非常标准和规范的。

练习1:读取hello.txt中的内容,显示在控制台上。
建议使用try-catch-finally的方式处理异常,确保流一定被关闭了,避免内存泄漏。

提示:
File f1= new File("xxx.txt");

FileReader myfr1 = new FileReader(f1)

int mydata = myfr1.read();

if(mydata != -1){ System.out.print((char)mydata); }

//提示:因为当读取数值为-1时候,是文件全部读取完成的标记。

package IOTest;

import org.junit.Test;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class FileReaderWriterTest {
    /*
    * 需求:读取hello.txt中的内容,显示在控制台上。
    * 建议使用try-catch-finally的方式处理异常,确保流一定被关闭了,避免内存泄漏。
    * 举例见如下的test2
    * */
    @Test
    public void test1() throws IOException {
        //1.创建File类的对象,对应hello.txt文件
        File f1 = new File("hello.txt");
        //2.创建输入型字符流,用于读取数据
        FileReader fr1 = new FileReader(f1);
        //3.读取数据并且显示在控制台上

        //方式1:
        //   int readfr1 = fr1.read();
        //   while (readfr1 !=-1)
        //   //一旦等于-1说明读到最末尾了,读完毕了
        //   {
        //       System.out.print((char)readfr1);
        //       readfr1 = fr1.read();
        //   }


        /* 这种写法也是类似的,都可以用
        while(true){
            int ff1 = fr1.read();
            if(ff1 == -1) break;
            else System.out.print((char)ff1);
            }
        */

        //方式2:
        int data;
        while ((data = fr1.read()) != -1) {

            System.out.print((char) data);
        }
        //4.流资源的关闭操作(必须关闭,否则资源泄漏)
        fr1.close();

    }

        @Test
        public void test2(){
            //1.创建File类的对象,对应hello.txt文件
            File f2 = new File("hello.txt");
            //2.创建输入型字符流,用于读取数据
            FileReader filereader1= null;
            //3.读取数据并且显示在控制台上(读取结果为int类型,当获得-1时说明读到了末尾)
            try {
                filereader1 = new FileReader(f2);
                int data2;
                while( ( data2=filereader1.read() ) != -1){

                    System.out.print((char)data2);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                //4.流资源的关闭操作(必须关闭,否则资源泄漏)
                try {
                    if(filereader1 != null)//这里是为了优化添加的,如果fread为null,说明某种原因创建fread失败了,直接关闭资源就可以了。
                        filereader1.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }


    /*
     * 需求:读取hello.txt中的内容,显示在控制台上。
     * 对test2()进行优化,每次读取多个字符串存放到字符数组中,减少与磁盘的交互次数,从而提高效率。
     *
     * */

    @Test
    public void test3() throws FileNotFoundException {
        FileReader filereader1= null;

        try {
            //1.创建File类的对象,对应hello.txt文件
            File f2 = new File("hello.txt");
            //2.创建输入型字符流,用于读取数据
            filereader1 = new FileReader(f2);

            //3.读取数据,并显示在控制台上
            char[] cbuffer =new char[5];
            int len= filereader1.read(cbuffer);
            //当filereader1.read(cbuffer)一般返回的是读取到数组char[]cbuffer里面的数据个数,当返回-1说明读完了
             while(len!=-1){
             //遍历数组
                //for (int i = 0; i < cbuffer.length; i++) {
                for (int i = 0; i < len; i++) {
                    System.out.print(cbuffer[i]);
                }
                len = filereader1.read(cbuffer);
            }




        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            //4.流资源的关闭操作(必须关闭,否则资源泄漏)
            try {
                if(filereader1 != null)//这里是为了优化添加的,如果fread为null,说明某种原因创建fread失败了,直接关闭资源就可以了。
                    filereader1.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    }


运行结果:

helloWorld123

举例2:往文件hello.txt中写入自定义的的内容。
比如原文件hello.txt文件内容为

this is line 1
this is line 2
this is line 3

代码结构类似这样

File myf1 = new File("hello.txt");
filewriter1=new FileWriter(myf1);
filewriter1.write("写进文件的内容");

//注意,如果文件不存在,系统会自动创建。

  • 如果想要覆盖原文件内容,直接写
    filewriter1=new FileWriter(myf1);
    或者写
    filewriter1=new FileWriter(myf1,flase);

  • 如果想要直接在原文件内容后面直接追加内容:
    filewriter1=new FileWriter(myf1,true);

参考代码:


    /*
    * 需求:将内存中的数据写入到指定文件中
    *
    * */

package IOTest;

import org.junit.Test;

import java.io.*;

public class FileReaderWriterTest {
    @Test
    public void test04()  {
        FileWriter wr1= null;
        try {
            //1.创建File类的对象,指明要写出的文件的名称
            File filedest= new File("hello.txt");
            //2.创建输出流

            //覆盖文件内容,使用构造器:
            //wr1 = new FileWriter(filedest);
            // 这一句等同于wr1 = new FileWriter(filedest,false);会覆盖文件内容

            //在现有的文件上追加内容使用构造器:
            wr1 = new FileWriter(filedest,true);
            //3.写出具体过程

            wr1.write("写入的内容");
            System.out.println("输出完毕");
        } catch (IOException e) {
            e.printStackTrace();
        } finally { //4.关闭资源
            try {
                if(wr1 != null)
                wr1.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }


    }


    }



输出结果:

输出完毕

Process finished with exit code 0

/*
*
* 需求:复制一份hello.txt文件(以及其内容),命名为hello_copy.txt
*
* */

提示:
1.创建file文件(src & desination)
File file_src = new File("src_file.txt");
File file_des = new File("des_file.txt");
2. 创建输入输出流
FileReader filereader1 = new FileReader(file_src);
FileWriter filewriter1 = new FileWriter(file_des);
3. 构建数据读入写出char当然这一步也可以不用
char [] cart = new char[5];
4. 读写文件

int len = filereader1.read(cart);
while(len !=-1){
	for(i=0;i<len;i++){
	filewriter1.write(cart,0,len);			
						}
len=filereader1.read(cart);
	}
filewriter1.close();
filereader1.close();

程序示例:

package IOTest;

import org.junit.Test;

import java.io.*;

public class FileReaderWriterTest {
@Test
    public void test05(){

        //替代方案(注意这种方法会将原始文件删除):
        //File myf1 = new File("hello.txt");
        //myf1.renameTo(new File("hello_copy.txt"));

        //方式2:
        FileReader filereader1 = null;
        FileWriter filewriter1 = null;
        try {
            //1.创建File类的对象
            File f_org = new File("hello_copy.txt");
            File f_dest = new File("hello_3.txt");
  //File f_dest = new File("hello_3.txt",true); //在现有的文件后面直接追加内容,而不是简单覆盖原文件内容

            //2.创建输入流,输出流
            filereader1 = new FileReader(f_org);
            filewriter1 = new FileWriter(f_dest);
            //3.数据的读入和写出的过程
            char[] charbuff = new char[5];

            //原本的程序如下:
            int len = filereader1.read(charbuff);//记录每次读到charbuff中的字符个数。
            while(len!=-1) {
                for (int i = 0; i < len; i++) {
                    System.out.print(charbuff[i]);
                    //filewriter1.write(charbuff[i]);
                   //filewriter1.write(charbuff,0,len);//这样写是错误的。因为这句其实没有用到i,在i=0到len的循环会一遍又一遍写入至少5次同样的信息。正确的写法,这一句话放在for循环的外面就行。
                    //filewriter1.write(charbuff);//这样写是也错误的。在不是5的倍数情况下,比如12345hi有可能读出12345hi345,
                    // 因为内存中的345还在,而hi后面又没有数据了。
//
                }
                filewriter1.write(charbuff,0,len);
                len=filereader1.read(charbuff);
            }

            //可优化为如下:len写入while循环括号内(但是确保是在for循环外面,或者直接不要for循环了)
           // int len;
           // while((len = filereader1.read(charbuff)) != -1){
           //     filewriter1.write(charbuff,0,len);//0角标开始写,一共写len个角标
           // }

            System.out.println("复制成功");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if(filereader1 != null)
                filereader1.close();

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

            try {
                if(filewriter1 !=null)
                filewriter1.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }


    }

    }



运行结果提示,文件内容复制成功:

this is line 1
this is line 2
this is line 3
this is my writting stamp
一二三四物流七八
写入的内容复制成功

Process finished with exit code 0

总结:FileReader\FileWriter的使用
执行步骤:

  1. 创建读取或写出File类的对象
  2. 创建输入流或输出流
  3. 具体的读如或写出的过程
    读入:read(char[] charbuffer)
    写出:write(String str) / write(char[] chabuffer,0,len)
  4. 关闭流资源,避免内存泄漏

注意:

  • 因为涉及到流资源的关闭操作,所以出现异常的话,需要使用try-catch-finally的方式来处理异常。
  • 对于输入流来讲,要求File类的对象对应的物理磁盘上的文件必须存在。否则报错FileNotFoundException;
  • 对于输出流来讲,File类的对象对应的物理磁盘上的文件可以不存在。
    如果此文件不存在,则在此输出的过程中,会自动创建此文件,并写出数据到此文件中。
    如果此文件存在,使用FileWriter(File file)或 FileWriter(File file,false):输出数据过程中,会新建同名的文件,对现有的文件进行覆盖。
    如果用FileWriter(File file,true):表示输出数据过程中,会在现有的文件的末尾追加写出的内容。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1586567.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux下批量的批量操作

批量删除docker 镜像 docker images | grep ent-form-web |awk ‘{print $3}’ | xargs docker rmi docker images: 列出所有的docker 镜像 docker images | grep ent-form-web : 选取出结果带 ent-form-web的信息 docker images | grep ent-form-web |awk ‘{print $3}’ 选取…

黑白图像彩色化

黑白图像彩色化 黑白图像彩色化&#xff0c;调用训练好的模型&#xff0c;将图片加上彩色&#xff0c;只需要OPENCV&#xff0c;支持C/PYTHON

【Python函数和类3/6】函数的返回值

目录 知识回顾 目标 函数的返回值 Tips 练习 ​编辑return的其它特性 任意类型的返回值 返回多个值 return的位置 小结 局部变量 局部变量的作用域 全局变量 全局变量的作用域 同名变量 pi的作用域 总结 知识回顾 在上篇博客中&#xff0c;我们学习给函数设置参…

基于 S2-LP 实现 802.15.4g 帧格式的数据透传

1. 引言 S2-LP 硬件上支持 802.15.4g 的帧格式&#xff0c;但是现有的 SDK 包并没有基于该帧格式的示例工程&#xff0c;因此本篇文章将介绍如何实现基于 802.15.4g 帧格式的数据透传。 2. 802.15.4g 帧格式 在开始之前&#xff0c;需要对 802.15.4g 帧格式有一个初步的了解…

VS中使用QT的UI提升类时,找不到头文件的情况

1、情况简述 在使用VS时&#xff0c;会发现与QCreator存在一些差异。最主要的就是要设置很多东西&#xff0c;如果不配置的话&#xff0c;就会遇到一些问题。下面我分享下我调试过程中遇到的一个问题。使用Qdesigner的UI提升类时&#xff0c;找不到头文件的情况&#xff1a; …

Flutter - 环境配置提示 cmdline-tools component is missing

问题&#xff1a; flutter doctor运行命令 flutter doctor 报错&#xff1a; Android toolchain - develop for Android devices (Android SDK version 30.0.2) ✗ cmdline-tools component is missing Run path/to/sdkmanager --install "cmdline-tools;lates…

ChatGPT国内镜像站大全(全都是能白嫖的)

今天在知乎看到一个问题&#xff1a;“平民不参与内测的话没有账号还有机会使用ChatGPT吗&#xff1f;” 从去年GPT大火到现在&#xff0c;关于GPT的消息铺天盖地&#xff0c;真要有心想要去用&#xff0c;途径很多&#xff0c;别的不说&#xff0c;国内GPT的镜像站到处都是&a…

OpenHarmony4.0分布式任务调度浅析

1 概述 OpenHarmony 分布式任务调度是一种基于分布式软总线、分布式数据管理、分布式 Profile 等技术特性的任务调度方式。它通过构建一种统一的分布式服务管理机制&#xff0c;包括服务发现、同步、注册和调用等环节&#xff0c;实现了对跨设备的应用进行远程启动、远程调用、…

ES13:类的新增特性、最外层的await、at...

1-类的新增特性 类私有属性和方法&#xff1a;# class Person{// 不需要传参、一开始就需要初始化的&#xff0c;就可以在类的最外面直接声明这个成员state{a:1,b:2}constructor(name,age){this.namename;this.ageage;}}在属性和方法前加#表示私有 #obj{} #prest(){}静态成员…

DP例题详解(二)最短编辑距离和编辑距离

902. 最短编辑距离 - AcWing题库 #include<bits/stdc.h>using namespace std;const int N1010;int n,m; char a[N],b[N]; int f[N][N];int main() {cin>>n>>a1;cin>>m>>b1;for(int i0;i<m;i)f[0][i]i;for(int i0;i<n;i)f[i][0]i;//先初始化…

Leetcode算法训练日记 | day20

一、合并二叉树 1.题目 Leetcode&#xff1a;第 617 题 给你两棵二叉树&#xff1a; root1 和 root2 。 想象一下&#xff0c;当你将其中一棵覆盖到另一棵之上时&#xff0c;两棵树上的一些节点将会重叠&#xff08;而另一些不会&#xff09;。你需要将这两棵树合并成一棵新…

linux中rpm包与deb包的区别及使用

文章目录 1. rpm与deb的区别2. deb软件包的格式和使用2.1 deb软件包命令遵行如下约定2.2 dpkg命令2.3 apt-命令 3. Unix和Linux的区别Reference 1. rpm与deb的区别 有的系统只支持使用rpm包安装&#xff0c;有的只支持deb包安装&#xff0c;混乱安装会导致系统问题。 关于rpm和…

绿联 安装火狐浏览器(Firefox),支持访问路由器

绿联 安装火狐浏览器&#xff08;Firefox&#xff09;&#xff0c;支持访问路由器 1、镜像 linuxserver/firefox:latest 前置条件&#xff1a;动态公网IP。 已知问题&#xff1a; 直接输入中文时&#xff0c;不能完整输入&#xff0c;也可能输入法无法切换到中文&#xff0c;可…

【LeetCode刷题笔记】LeetCode 1365.有多少小于当前数字的数字

创作不易&#xff0c;本篇文章如果帮助到了你&#xff0c;还请点赞 关注支持一下♡>&#x16966;<)!! 主页专栏有更多知识&#xff0c;如有疑问欢迎大家指正讨论&#xff0c;共同进步&#xff01; 更多算法知识专栏&#xff1a;算法分析&#x1f525; 给大家跳段街舞感谢…

【STM32G431RBTx】备战蓝桥杯嵌入式→省赛试题→第十四届

文章目录 前言一、题目二、模块初始化三、代码实现interrupt.h:interrupt.c:main.h:main.c: 四、完成效果五、总结 前言 无 一、题目 二、模块初始化 1.LCD这里不用配置&#xff0c;直接使用提供的资源包就行 2.KEY, 四个按键IO口都要配置&#xff0c;分别是PB0, PB1,PB2,PA…

看了下雷军的两份个人简历,的确厉害。。。

最近在网上浏览信息时&#xff0c;偶然看到了雷军的两份简历&#xff0c;一份是详细的工作履历&#xff0c;另一份则是他的干部履历表。 从大学时期开始&#xff0c;雷军就展现出了非凡的才华和毅力。高考成绩惊人&#xff0c;仅仅丢了2分&#xff0c;堪称完美&#xff0c;被武…

Linux网络名称空间和虚拟机有何区别

在Linux系统中&#xff0c;网络名称空间和虚拟机都是实现资源隔离和虚拟化的技术&#xff0c;但它们在设计理念、实现机制、资源消耗、使用场景等方面存在着显著的区别。本文旨在全方位、系统性地分析这两种技术的区别。&#x1f50d; 1. 设计理念与实现机制 1.1. 网络名称空…

Qt Creator 12.0.2 debug 无法查看变量的值 Expression too Complex

鼠标放在局部变量上提示“expression too complex”。 在调试窗口也看不到局部变量的值。 这应该是qt的一个bug&#xff0c;https://bugreports.qt.io/browse/QTCREATORBUG-24180 暂时解决方法&#xff1a; 如下图&#xff0c;需要右键项目然后执行"Clean"和&quo…

LeetCode第十六题: 掌握双指针技巧 最接近的三数之和 【python】

&#x1f464;作者介绍&#xff1a;10年大厂数据\经营分析经验&#xff0c;现任大厂数据部门负责人。 会一些的技术&#xff1a;数据分析、算法、SQL、大数据相关、python 欢迎加入社区&#xff1a;码上找工作http://t.csdnimg.cn/Q59WX 作者专栏每日更新&#xff1a; LeetCode…

ssm038汽车养护管理系统+jsp

汽车养护管理系统设计与实现 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本汽车养护管理系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短…