Java 输入输出流学习总结

article/2025/9/12 15:16:28

文章目录

  • 前言:为什么要有输入输出流
  • 一、Java 的标准输入输出
    • 标准输入 System.in
    • 标准输出 System.out
    • 程序 exp8_3:简单的输入输出
  • 二、输入输出流框架
  • 三、输入输出流类的应用
    • 课本程序 exp8.4
    • 改写 exp8.4(1)
    • 改写 exp_8.4(2)
  • 四、RandomAccessFile 类
  • 输入输出流总结


前言:为什么要有输入输出流

为什么 Java 要有输入输出流?我们先来看看用现有手段写一个简单的输入输出程序:

package big;import java.util.Scanner;public class Simlpe_input_and_output {public static void main(String[] args) {// TODO 自动生成的方法存根Scanner read = new Scanner (System.in);System.out.println("请输入你想输入的内容:");String a = read.next();System.out.println("接下来打印这句话:");System.out.println(a);}} 

你看看这多麻烦,要想从键盘上输入还得先导入 util 包里的 Scanner 类,在一开始学 Java 的时候差点因为这个导致厌学(C语言直接 scanfprintf 不好吗?为啥 Java还得三行代码?) 。
接下来还是看看课本上的介绍吧:Java 语言的输入输出功能是十分强大而灵活的(说实话,我现在都不信🥱🥱🥱),对于数据的输入和输出操作以 “ 流 ”(stream)的方式进行。JDK 提供了各种各样的 “ 流 ” 类,用以获取不同种类的数据,它们都定义在 java.io 包中。程序中通过标准的方法输入或输出数据。

嗯~~那下面我们就来看看这 Java 输入输出流到底咋回事吧,这里主要还是对课本中的示例代码进行复现来学习的,所以课本看不懂的小伙伴可以试试我的这篇学习笔记。


一、Java 的标准输入输出

标准输入输出功能是通过 Java 的 System 系统类来实现的。System 类在 java.lang 包中,是一个最终类,里面的大多数方法都是静态方法,所以在程序中可以直接调用它们(包括标准输入输出)。

什么?不知道 java.lang 是啥?老师上课讲过的,language 嘛,语言的缩写。java.lang包是java语言的核心,它提供了java中的基础类。包括基本Object类、Class类、String类、基本类型的包装类、基本的数学类等等最基本的类。也就是说,一个 Java 程序必备 java.lang 包(默认就存在的吧,我也没见课本示例程序里写啊,是吧?)

标准输入 System.in

System.in 作为 InputStream 类的对象实现标准输入,可以调用它的 read 方法(有以下三种格式)来读取键盘数据:

  1. public abstract int read()
  2. public int read (byte[] b)
  3. public int read (byte[] b, int off, int len)

输入流结束,返回 -1。

标准输出 System.out

System.out 作为 PrintStream 打印流类的对象实现标准输出,可以调用它的 ptintprintlnwrite 方法来输出各种类型的数据。

printprintln 都不用介绍了,目前用的最多的代码就是写这个的。还是说一下 wtite 方法吧,它用来输出字节数组,注意一点:write 方法在输出单个字节时并不能立即显示出来,还需调用 flushclose 方法来强制回调(??不懂)。

程序 exp8_3:简单的输入输出

package big;import java.io.IOException;public class exp8_3_simple_inputoutput {public static void main(String[] args) throws java.io.IOException {  //这里必须继承 IOException 异常,因为输入时可能会发生 I/O 错误byte buffer[] = new byte[40];System.out.println("从键盘上输入不超过40个字符,按回车键结束输入:");int count = System.in.read(buffer);  //读取标准输入流System.out.println("保存在缓冲区的元素个数为" + count);System.out.println("输出 buffer 元素值:");for (int i = 0; i < count; i ++) {System.out.print(" " + buffer[i]);}System.out.println();System.out.println("输出 buffer 字符元素:");System.out.write(buffer, 0, buffer.length);}}

输出如下:
在这里插入图片描述
下面做个小实验,对该程序做几点改变,看看有什么变化:

  1. 最后一行 write 方法中最后一个参数不应该是 buffer.length-1 吗?结果没有任何改变,看来没什么好说的了,我认为 Java 不严谨,支持我吗,同志们?
  2. 我不想在输出 buffer 元素值时看到的是 ASCII 码,我要看我输入的字母。简单,安排!这只是在 for 循环里面的输入加上一个强制转换符就行了System.out.print(" " + (char)buffer[i]);。问题是,多了两行空格,这怎么解释?🤔🤔🤔🤨🤨🤨
    在这里插入图片描述

如此简单一个程序,我以为搞懂了,可是回看一下课本上的说明,还是有问题滴:

  1. 我们在键盘上输入7个字符,可是控制台却显示保存在缓冲区的元素个数为 9,这是因为还有回车符 “ \r ” 占用了两个元素,且元素值为 ASCII 码值。(会不会那两行空格就是因为这个原因?)
  2. 对程序中的第一条注释,原来课本里给出了说明:本例用到了 read(byte[] b) 方法,因其会产生输入异常,可以放在 try···catch 块中执行,或令 main 方法将异常上交(即在声明语句中加入 throws java.io.IOException ),这样才能通过编译。
  3. 课本上说:本例使用了 write 方法直接输出了字节数组的内容,如果使用 println 方法可将字节数组的内容转换为字符串,否则不能正常显示。于是把System.out.write(buffer, 0, buffer.length) 改成了下面这样,但不行耶,老师怎么把字节数组里的内容转换成字符串啊?(我做了什么?最后为什么会有好多空格和 null 这几个字符输出?) :
String str = null;  //如果不赋初始值 null 的话,将会报错,原因是局部变量 str 尚未初始化
for (int i = 0; i < count; i ++) {str += (char)buffer[i];
}
System.out.println(str);

在这里插入图片描述
PS:这个问题已得到解决,后面的程序(第三小节输入输出流类的应用里最后一个实验)中会把字节数组转换成字符串,这里写好了就不动了吧,主要是懒,哈哈~~

二、输入输出流框架

课本上哇哇哇说了一大堆,实在没什么可讲的,就直接放图吧:

数据流以输入流的形式被程序获取,再以输出流的形式将数据输出到其它设备。图 1 为输入流模式,图 2 为输出流模式:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
输入输出流总框架图:
在这里插入图片描述
最后提一下关于输入输出流的分类,了解即可:

数据流是 Java 进行 I/O 操作的对象,它按照不同的标准可以分为不同的类别。

  1. 按照流的方向主要分为输入流和输出流两大类;
  2. 数据流按照数据单位的不同分为字节流和字符流;
  3. 按照功能可以划分为节点流和处理流;
  4. 依据类的作用,可以分为文件流、缓冲流、数据流、管道流、转换流、打印流、对象流等。

三、输入输出流类的应用

课本程序 exp8.4

例 8.4:创建两个 File 类的对象,分别判断两个文件是否存在;如果不存在,则新建。然后从键盘输入字符数据存入数组 b 里,通过文件输出流,把数组里的字符写入到 hello1.txt 文件,再从 hello1.txt 中读取数据,写到文件 hello2.txt 中。以下是源代码。

package big;import java.io.*;public class stream_exp8_4 {public static void main(String[] args) {int len;byte b[] = new byte[20];  //定义一个长度为20的字节型数组//创建文件对象(这里只是在程序中实例出对象,其实并不存在)File file1 = new File("D:\\学校课程学习\\java程序设计\\eclipse\\工作空间\\hello1.txt");File file2 = new File("D:\\学校课程学习\\java程序设计\\eclipse\\工作空间\\hello2.txt");FileOutputStream fos = null;  //先定义,后面会在下面字节流应用中再实例化对象(new)的try {  //如果文件不存在,就创建对象(经过这里的操作才是真的在 java 文件夹里创建了文件)if (!file1.exists())file1.createNewFile();if (!file2.exists());file2.createNewFile();//字节流应用System.out.println("请输入你想存入file1文件的内容:");len = System.in.read(b);  //从键盘输入的字符存入内存的 b 数组里的个数(一边实现了键盘输入,一遍统计了字符个数)fos = new FileOutputStream(file1, true);  //创建文件输出流到到 file1fos.write(b, 0, len);  //通过文件输出流 fos 把 b 数组中数据写入到 file1 文件尾部//字符流与缓冲流应用FileReader in = new FileReader(file1);  //打开字符文件输入流BufferedReader bin = new BufferedReader(in);  //传送数据到缓冲区(这一句代码就是装饰流,作用是加速读的速度)FileWriter out = new FileWriter(file2, true);  //打开字符文件输出流String str;System.out.println("完美复制到file2文件中的内容:");while ((str = bin.readLine()) != null) {  //将缓冲区中数据一行一行地送到字符串变量字符串变量 str 中System.out.println(str);  //输出 str 中数据到控制台out.write(str+"\n");  //将 str 中数据写入文件}out.close();in.close();fos.close();  //关闭流资源}catch(IOException e) {e.printStackTrace();}}}

运行结果如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
看着没问题是吧,再试试重复运行输入一遍。由此我们会发现打印在控制台中的有两个 “ 相信中国!” ,打开文件后发现 hello1.txt 里有两个 “ 相信中国!” ,文件 hello2.txt 里有三个 “ 相信中国!” 。仔细想一想,也就该是这样哈!
在这里插入图片描述
在这里插入图片描述

改写 exp8.4(1)

OK,接下来,我们再来做些实验,首先有一个问题是装饰类只是加快了读的速度,其实没它照样可以完成任务,我们这样来改写程序:

FileReader in = new FileReader(file1);
//BufferedReader bin = new BufferedReader(in);  //删掉装饰流
FileWriter out = new FileWriter(file2, true);
for (int i = 0; i < len; i ++) {System.out.print((char)b[i]);out.write(b[i]);
}

这样一来,运行结果会变成怎样呢?结果是识别不了汉字了(英文倒是可以),另外就是不管运行几遍,控制台打印的都只会是本次运行时键盘输入的内容,文本文件中也只会增加本次输入的内容,大家可以对比着来看看:
在这里插入图片描述
不明白,为啥啊???

改写 exp_8.4(2)

再来一个实验:在示例中,我们输出流用的是字节流,输出流用的是字符流,统一一下不好吗?我先来试试统一字节流输入输出好了。
终于,我成功了,就像写高考数学题,写的时候真难,写完了发现好简单😂😂😂

package big;import java.io.*;public class exp8_4_zijieliushurushuchu {public static void main(String[] args) {// TODO Auto-generated method stubint len;byte b[] = new byte[20];File file1 = new File("D:\\学校课程学习\\java程序设计\\eclipse\\工作空间\\hello1.txt");File file2 = new File("D:\\学校课程学习\\java程序设计\\eclipse\\工作空间\\hello2.txt");FileOutputStream fos = null;try {if (!file1.exists())file1.createNewFile();if (!file2.exists());file2.createNewFile();System.out.println("请输入你想存入file1文件的内容:");len = System.in.read(b);fos = new FileOutputStream(file1, true);fos.write(b, 0, len);FileInputStream in = new FileInputStream(file1);BufferedInputStream bin = new BufferedInputStream(in);FileOutputStream out = new FileOutputStream(file2, true);
//			for (int i = 0; i < len; i ++) {
//				out.write(b[i]);
//			}out.write(b);  //上面三行 for 循环其实就是这一句话的事情,算是了解一下 write 方法吧String str = new String(b);System.out.println(str);out.close();in.close();fos.close();}catch(IOException e) {e.printStackTrace();}		}}

就在这个程序里,我把字节数组转换成了字符串,顺利地在控制台(屏幕)上打印出来了(这也是为什么课上有同学问 “ 为什么可以用字节数组输出汉字 ” 问题的答案了,都转换成了字符串,那为什么还不能输出汉语呢,是吧?)。大家看那输入输出流框架图都是一愣一愣的,不过呢,这里有篇文章很好的总结了字节输入输出流的框架和方法,我就是照着这篇文章完成这个实验的,分享一下。

???还有统一字符输入输出流???再说吧,累了。

四、RandomAccessFile 类

课上老师讲:RandomAccessFile 类是一个随机存取文件类。虽然不明白这句话什么意思,但下一句确实醍醐灌顶:这个类可以实现 Java 输入输出流的任意操作。我了个乖乖,相比较框架图里那么多类,这样子只用一个类就方便多了呀!

例 8.5 :通过 RandomAccessFile 类从文件的不同位置读写不同长度的数据,讲字符串数据添加在文件尾部。

package big;import java.io.*;public class exp8_5 {public static void main(String[] args) {String str[] = {"First lint\n", "second line\n", "Last line\n"};try {//用 RandomAccessFile 类实例化出 rf 对象,参数表示可以对文件 demo.txt 进行读写操作RandomAccessFile rf = new RandomAccessFile("demo.txt", "rw"); System.out.println("\n光标的位置为:" + rf.getFilePointer());  //获取文件指针位置方法System.out.println("文件的长度为:" + rf.length());rf.seek(rf.length());  //把光标移到文件末尾(用的是 seek 方法)System.out.println("光标现在的位置为:" + rf.getFilePointer());for (int i = 0; i < 3; i ++)rf.writeBytes(str[i]);  //将字符串数组 str 里的三个字符串依次写入 rf 对象中rf.seek(0);  //把光标移到文件起始位置System.out.println("\n文件现在的内容:");String s;while ((s = rf.readLine()) != null)  //分行读取System.out.println(s);  //分行打印rf.close();  //关闭流资源}catch (FileNotFoundException fnoe) {}catch (IOException ioe) {}}	}

运行结果和课本里的一样:在这里插入图片描述

以下摘自课本中的说明:

  1. 从本例看,随机存取文件类的的使用方法,也是先建立文件流通道,打开文件,然后进行读写操作,最后关闭文件通道。只是不用分输入流和输出流。
  2. 可以用于多线程下载或多个线程同时写数据到文件。

怎么说?其实没什么,我打一遍代码试着运行也是为了看看到底有多方便,也确实比原始输入输出流分开写简单许多。

其实还有一个小节讲的是 “ 对象序列化与对象流类 ” ,课上老师好像也是一笔带过(是不是啊?我没有认真听这点内容,感觉还没讲就过去了,连示例程序都没啥印象)


输入输出流总结

我看课本上的小结讲的是使用输入输出流的参考步骤和流程,但我就 get 不到,没有感觉。看来还是对 Java 不熟悉,对输入输出流不熟悉( c++ 里不也是输入输出流 cin、cout 吗?感觉就像一个在天上,一个在地下。。。)

在最后我还是说一下输入输出和读写的关系吧,我上机的时候就把输入输出流的意思给搞反了。记住一点:输入输出都是以程序为参照物的

  • 输入流:用于从键盘或文件(数据源)获得数据传递给程序,只能读不能写;
  • 输出流:用于将数据从程序传递给数据接收者(宿点),如内存、显示器屏幕、打印机或文件,只能写不能读。

Java 中一切名词皆为类,一切类都要实例化对象,一切对象都有属性和方法,Java 就是靠着对象的属性和方法来完成编程解决问题的,这就是我学习 Java 以来的深刻体会,这就是面向对象编程!!!


http://chatgpt.dhexx.cn/article/cNOX3B0v.shtml

相关文章

java 输入输出流

java I/O流 在java中所有数据都是使用流读写的。流是一组有序的数据序列&#xff0c;将数据从一个地方带到另一个地方。根据数据流向的不同&#xff0c;可以分为输入&#xff08;Input&#xff09;流和输出&#xff08;Output&#xff09;流两种。 为什么要使用输入输出流 例…

Java(2)-Java IO输入输出流

一.什么是IO Java中I/O操作主要是指使用Java进行输入&#xff0c;输出操作. Java所有的I/O机制都是基于数据流进行输入输出&#xff0c;这些数据流表示了字符或者字节数据的流动序列。Java的I/O流提供了读写数据的标准方法。任何Java中表示数据源的对象都会提供以数据流的方式读…

Java——输入输出

本篇主要介绍Java的输入与输出&#xff0c;当然&#xff0c;这里说的是控制台下的输入与输出&#xff0c;窗口程序的设计将会再后续篇章中有详细说明。   Java的输出很简单&#xff0c;调用System.out.println()即可打印输出你想要输出的内容。我们之前也已经看到过。调用pr…

C语言之static关键字详解

目录 前言&#xff1a; 一、几个概念 1.变量 2.局部变量和全局变量 3.变量的作用域 4.变量的生命周期 二、static关键字的作用 三、static关键字修饰局部变量 四、static关键字修饰全局变量 五、static关键字修饰函数 写在最后&#xff1a; 前言&#xff1a; static&am…

static关键字你真的懂了吗?

文章目录 static关键字1、Java中的static1.1 static关键字的定义和性质1.2 实例变量与静态变量1.2.1 实例变量1.2.2 静态变量 1.3 静态代码块1.4 *实例语句块 / 代码块1.5 static总结1.5.1 对java语句的解读1.5.2 什么时候定义为静态的&#xff1f; 2、C/C中的static2.1 局部变…

C语言extern和static关键字详解

C语言extern和static关键字详解 文章目录 1 前言2 作用域2.1 代码块作用域2.2 文件作用域 3 存储类型4 链接属性5 extern和static关键字5.1 extern关键字5.2 static关键字 1 前言 在讲extern和static关键字前&#xff0c;先讲几点相关的基础知识——作用域、存储类型、链接属性…

什么是static关键字

什么是static关键字 static关键字我们经常接触&#xff0c;不过我们一直没有讨论过它到底是什么&#xff0c;有什么具体的作用&#xff0c;那static关键字是什么呢&#xff0c;有啥用呢&#xff1f; static是静态的意思&#xff0c;是一个修饰符&#xff0c;就像是一个形容词&…

static关键字(java)

一、static的用途 1.static修饰的变量和方法是属于类的&#xff1b; 2.static修饰的变量和对象&#xff0c;方法存储在方法区的静态常量池中&#xff1b;是共享的&#xff1b; 3.可以在没有创建任何对象的前提下&#xff0c;仅仅通过类本身来调用static方法 4.static修饰的…

static关键字的用法

static关键字用法 目录 一.概述二.使用动机三.使用方法 static关键字修饰类static关键字修饰方法static关键字修饰变量static关键字修饰代码块 一. 概述 > static是一个静态修饰符关键字&#xff0c;表示静态的意思&#xff0c; ①方便在没有创建对象的情况下进行调用。可…

static 关键字用法总结

一、static 关键字的含义 static是Java50个关键字之一。static关键字可以用来修饰代码块表示静态代码块&#xff0c;修饰成员变量表示全局静态成员变量&#xff0c;修饰方法表示静态方法。(注意&#xff1a;不能修饰普通类&#xff0c;除了内部类&#xff0c;这是为什么&#…

java static关键字的作用是什么_static关键字有什么作用

今天主要学习下Java语言中的static关键字。 static关键字的含义及使用场景 static是Java50个关键字之一。static关键字可以用来修饰代码块表示静态代码块,修饰成员变量表示全局静态成员变量,修饰方法表示静态方法。(注意:不能修饰普通类,除了内部类,这是为什么?)class A …

static关键字的作用

目录 C语言中static关键字的作用 1.static关键字修饰局部变量 2.static关键字修饰全局变量 3.static关键字修饰函数 在C中static关键的作用 1.静态成员变量 2.静态成员函数 C语言中static关键字的作用 1.static关键字修饰局部变量 概念&#xff1a; static修饰局部变量就…

静态关键词:static

static关键字的作用 static是静态的意思&#xff0c;可以修饰成员变量&#xff0c;表示给成员变量只在内存中存储一份&#xff0c;可以被共享访问、修改 成员变量可以分为2类1、静态成员变量&#xff08;有static修饰&#xff0c;属于类&#xff0c;内存中加载一次&#xff…

C# -- static 关键字

一、static关键字 static 关键字&#xff0c;用于修饰类&#xff0c;字段&#xff0c;属性&#xff0c;方法&#xff0c;构造方法等。被 static 修饰的类称之为“静态类”&#xff1b; 被 static 修饰的成员称之为“静态成员”&#xff0c;被修饰过的成员分别称为&#xff1a;…

static关键字详解

1.概述&#xff1a; static&#xff1a;就是多个对象共享同一份数据 一个类的不同对象有些共享的数据&#xff0c;这样我们就可以使用static来修饰 一旦使用了static关键字&#xff0c;那么这样的内容不再属于对象&#xff0c;而是属于类的&#xff0c;所以凡是本类的对象&…

在 C/C++中 static 关键字详解

static 关键字详解 C/C 中的 static1. 静态局部变量2. 静态全局变量全局变量 与 extren 3. static 修饰函数 C的 static 成员静态成员变量const修饰的成员除外 静态成员函数 总结&#xff1a; static是 C/C中的关键字之一&#xff0c;是常见的函数与变量&#xff08;C中还包括类…

Windows添加路由的方法

假设本来的局域网网关是192.100.10.1&#xff0c;现在要访问网关是192.100.20.0的服务器&#xff0c;可以手动添加路由。 方法&#xff1a; 1.以管理员的身份打开cmd命令窗口 2.输入 route add 192.100.20.0 mask 255.255.255.0 192.100.10.1 -p&#xff08;最后加上-p就是…

如何在 Linux 上添加路由?

在 Linux 系统中&#xff0c;路由是网络通信的关键组件之一。通过添加路由&#xff0c;您可以指定数据包在网络中的传输路径&#xff0c;从而实现网络连接和数据转发。本文将详细介绍如何在 Linux 上添加路由&#xff0c;以便您可以根据需要配置网络路由并实现灵活的网络连接。…

Linux上添加路由,删除路由,修改路由配置(route add, route del, 路由表项基本知识)

路由基础知识&#xff1a; 是由一项或者多项路由表组成的&#xff0c;每个IP报文被发送前&#xff0c;系统都会查找主机路由表&#xff0c;决定将这个报文从 哪个网卡&#xff0c;发送到哪个下一跳。路由表项可以分成主机路由&#xff0c;网络路由和默认路由3种。每条路由表项…