【疯狂Java讲义】Java学习记录(IO流)

news2024/11/16 22:57:15

IO流

IO:Input / Output

完成输入 / 输出

应用程序运行时——数据在内存中                        ←→                把数据写入硬盘(磁带)

                                内存中的数据不可持久保存

输入:从外部存储器(硬盘、磁带、U盘)把数据读入内存中。

输出:从内存中把数据写入外部存储器(硬盘、磁带、U盘)中,这样就可以保证,即使程序退出了,数据依然不会丢失。

File —— 代表磁盘上的文件或目录

listRoot:列出磁盘上所有的根目录

exists:判断是否存在

mkdir:创建目录

listFiles():列出当前目录下所有的文件和子目录

listFiles(FileFilter filter):列出当前目录下符合指定条件的文件和子目录

listFiles(FilenameFilter filter)

列出某个磁盘所有的文件——递归

import java.io.File;

public class ListE {

	public static void main(String[] args) {
		// 创建一个File,它代表了E盘
		File e = new File("e:/Program Files");
		
		List(e);
	}
	
	public static void List(File dir) {
		System.out.println(dir + "目录下包含的文件和子目录有:");
		// 该方法返回当前目录所包含的所有文件和子目录
		File[] files = dir.listFiles();
		
		for (File file : files) {
			System.out.println("	" + file);
			// 如果file是目录,继续列出该目录下所有文件
			if (file.isDirectory()) {
				List(file);
			}
		}
	}
}

 列出某个磁盘所有的.txt文件——递归

import java.io.*;

public class FileFilterTest {

	public static void main(String[] args) {
		File e = new File("e:/");
		
		// 返回当前目录所包含的所有*.txt文件,此时就需要对文件进行过滤
		File[] files = e.listFiles(new FileFilter() {
			// pathname就代表正在处理的文件,如果该方法返回true,意味着该文件就被保留,否则该方法将会被过滤掉
			@Override
			// 没有比IOExcepiton更小的,所以只能用try catch
			public boolean accept(File pathname) {
				// 说明文件名以.txt结尾
				try {
					if (pathname.getCanonicalPath().endsWith("txt")) {
						return true;
					}
				} catch (IOException e) {
					e.printStackTrace();
				}
				return false;
			}
		});
		
		for (File file : files) {
			System.out.println(file);
		}
	}
}

File的特征:只能访问磁盘上的文件和目录,它无法访问文件内容。

如果要访问文件的内容,必须使用IO流

流的分类

1、按流的方向来分(从程序所在内存的角度来看)

(1)输入流

把外部输入读入当前程序所在内存

(2)输出流

把当前程序所在内存的数据输出到外部

2、按流处理的数据来分

(1)字节流

处理数据单位是字节(8bit),适应性广、功能强大

(2)字符流

处理的数据单元是字符。通常来说它主要用于处理文本文件

在处理文本文件时,比字节流方便

3、按流的角色来分

(1)节点流

直接和一个IO的物理节点(磁盘上的文件、网络)关联

(2)包装流(处理流 / 过滤流)

以节点为基础,包装之后得到的流

都继承了FilterXxx等基类

流的概念模型

输入流中的数据单元放入应用程序;应用程序中的数据单元放入输出流。

缓冲流

外部存储器的速度比内存的速度慢,外部存储器的读写与内存的读写并不同步

——通过缓冲就可以解决这种不同步

反正你把流用完了,

- 别忘记调用flush方法(把缓冲中的内容刷入实际的节点)

             调用close()也可——系统会在关闭之前,自动刷缓冲

IO流一共涉及40多个类

字节流字符流
节点流InputStreamOutputStreamReaderWriter抽象
FileInputStreamFileOutputStreamFileReaderFileWriter访问文件
ByteArrayInputStreamByteArrayOutputStreamCharArrayReaderCharArrayWriter数组
PipedInputStreamPipedOutputStreamPipedReaderPipedWriter访问管道
StringReaderStringWriter访问字符串
缓冲流BufferedInputStreamBufferedOutputStreamBufferedReaderBufferedWriter缓冲
FilterInputStreamFilterOutputStreamFilterReaderFilterWriter抽象
PrintStreamPrintWriter打印
InputStreamReaderOutputStreamWriter转换
DataInputStreamDataOutputStream特殊

所有以InputStream结尾的都是字节输入流

所有以OutputStream结尾的都是字节输出流

所有以Reader结尾的都是字符输入流

所有以Writer结尾的都是字符输出流

1、FileInputStream 

import java.io.*;
public class FileInputStreamTest {
	public static void main(String[] args) throws IOException {
		// 创建输入流,相当于得到一根有水的水管
		FileInputStream fis = new FileInputStream("D:\\Program Files\\eclipse-java-2023-06-R-win32-x86_64\\workplace\\day\\src\\day13\\FileInputStreamTest.java");
		
		// System.out.print((char)fis.read());// 该方法每次只读一个字节
		
		/*
		 * 为了把fis中水滴全部“取出”内存,有两个做法:
		 * 1、用大桶
		 * 2、用循环
		 */
		byte[] buff = new byte[64]; // 我的水桶可以装64个“水滴”
		int hasRead = -1;
		//hasRead = fis.read(buff);// 用“桶”从fis(水管)中取水
		while((hasRead = fis.read(buff)) > 0) {
			// 上一次读取了几个字节,此处就输出几个字节
			System.out.println(new String(buff, 0 ,hasRead));
		}
	}
}

运行结果: 

 2、FileOutputStream

import java.io.FileOutputStream;
import java.io.IOException;

public class FileOutputStreamTest {
	public static void main(String[] args) {
		FileOutputStream fos = null;
		try {
			// 得到输出流,相当于得到一个没有水滴的水管
			fos = new FileOutputStream("abc.txt");
			fos.write(97); // 每次输出"一个字节“
			fos.write(98);
			fos.write(99);
			fos.write(100);
			fos.write(101);
			
			fos.write("自由、民主的普世价值观~".getBytes());
		} catch (IOException ex) {
			ex.printStackTrace();
		} finally {
			try {
				fos.close();
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}
	

运行结果: 

复制文本文件

import java.io.*;
public class CopyTest {
	public static void main(String[] args) {
		// JDK 7提供了自动关闭资源的try语句
		try (
			// 创建输入流,得到一个有水滴的水管
			FileInputStream fis = new FileInputStream("D:\\Program Files\\eclipse-java-2023-06-R-win32-x86_64\\workplace\\day\\src\\day13\\CopyTest.java");
			// 创建输出流,得到一个空水管
			FileOutputStream fos = new FileOutputStream("D:\\Program Files\\eclipse-java-2023-06-R-win32-x86_64\\workplace\\day\\src\\day13\\test.txt"); 
		)
		{
			int hasRead = -1;
			byte[] buff = new byte[128];
			
			// 从fis里读取水滴,放入buff中
			while((hasRead = fis.read(buff)) > 0) {
				// 将buff中水滴写入fos,hasRead用于控制:读了多少,就写多少
				fos.write(buff, 0, hasRead);
			}
			
		} catch (IOException ex) {
			ex.printStackTrace();
		}
	}
}

运行结果: 

节点流直接与IO节点关联

——IO节点有很多:键盘、网络、文件、磁带……

过滤流:建立在节点流的基础之上

        过滤流的好处:

        ——消除底层节点之间的差异

        ——使用过滤流的方法执行IO更加便捷

                FileOutputStream →PrintStream

                              FileWriter→PrintWriter

                         如果已经知道要读的内容是字符内容,就可按如下方式转换:

                         InputStream→InputStreamReader→BufferedReader

1、 FileOutputStream →PrintStream

import java.io.*;

public class PrintStreamTest {
	public static void main(String[] args) {
		try (
			// 创建节点流,节点流使用不方便
			FileOutputStream fos = new FileOutputStream("D:\\Program Files\\eclipse-java-2023-06-R-win32-x86_64\\workplace\\day\\src\\day13\\my.txt"); 
			// 把节点流包装成过滤流:消除节点流的差异,而且PrintStream的方法更加方便
			PrintStream ps = new PrintStream(fos);		
		)
		{
			ps.println("我想");
			ps.println("我想早");
			ps.println("我想早点");
		} catch (Exception ex) {
			ex.printStackTrace();
		} 
	}
}

运行结果: 

3、DataInputStream与DataOutputStream

它们是两个特殊的流——它们是过滤流(建立在已有IO的基础之上)

——它们只要增加一些特定的方法来读取特定的数据。

import java.io.*;
public class DataOutputStreamTest {
	public static void main(String[] args) {
		try (
			// 创建节点流——与磁盘上的文件关联
			FileOutputStream fos = new FileOutputStream("price.txt");
			
			// 创建过滤流,过滤流建立在节点流的基础上
			DataOutputStream dos = new DataOutputStream(fos);
		)
		{
			dos.writeDouble(3.4);
			dos.writeDouble(5.23);
			dos.writeDouble(4.34);
			dos.writeDouble(5.12);
		} catch (Exception ex) {
			ex.printStackTrace();
		}	
	}
}

运行结果:

import java.io.*;
public class DataInputStreamTest {
	public static void main(String[] args) {
		try (
			// 先创建节点流,与指定物理节点(文件)建立读写
			FileInputStream fis = new FileInputStream("price.txt");
			
			// 以节点流来创建过滤流
			DataInputStream dis = new DataInputStream(fis);
		)
		{
			System.out.println(dis.readDouble());
			System.out.println(dis.readDouble());
			System.out.println(dis.readDouble());
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}
}

运行结果:

重定向标准输入输出

System.in——标准输入。通常代表键盘。

System.out——标准输出。通常代表屏幕。

System.setOut() ——可以将标准输出重定向另一个输出流。

import java.io.*;
public class SetOutTest {
	public static void main(String[] args) throws Exception{
		// 可以将标准输出重定向到指定的输出流
		System.setOut(new PrintStream("out.txt"));
		
		System.out.println("ABC");
		System.out.println("ABC");
		System.out.println("ABC");
		System.out.println("ABC");
	}
}

运行结果:输出的内容重定向到out.txt文本文件中 

System.setIn() ——可以将标准输出重定向另一个输入流。

import java.io.*;
public class RedirectKeyIn {
	public static void main(String[] args) throws Exception {
		// 将标准输入重定向到RedirectKeyIn.java
		System.setIn(new FileInputStream("RedirectKeyIn.java"));
		
		//System.in,它是一个节点流,一般关联着物理键盘
		//直接用System.In(InputStream——节点、字节、输入流)可以读取键盘输入
		//缺点是:太繁琐、而且效率相当低下
		//System.out.println(System.in.read());
		
		InputStreamReader reader = new InputStreamReader(System.in);
		
		BufferedReader br = new BufferedReader(reader);
		
		String line = null;
		// 控制BufferedReader每次读取一行
		while ((line = br.readLine()) != null) {
			System.out.println(line);
		}
	}
}

运行结果:

Java虚拟机读取其他进程的数据 

Java如何启动其他进程:Runtime实例.exec()

该方法的返回值是一个Process对象

Process——代表一个进程。

                    进程就是运行中的应用程序。

import java.io.*;
public class ReadFromProcess {
	public static void main(String[] args) throws Exception{
		
		Runtime runtime = Runtime.getRuntime();
		
		// 启动javac应用程序,返回该应用程序对应的进程
//		Process proc = runtime.exec("javac.exe -encoding UTF8 -d . ReadFromProcess.java");
		Process proc = runtime.exec("javac.exe -encoding UTF8 -d . ReadFromProcess");
		
		// 要得到javac应用程序输出的内容,此处应该用输入流?还是输出流?
		// 对于javac来说,是输出;但对于我们应用程序来说,用输入流
		InputStreamReader reader = new InputStreamReader(proc.getErrorStream());
		BufferedReader br = new BufferedReader(reader);
		
		String line = null;
		
		StringBuilder sb = new StringBuilder();
		
		// 控制BufferedReader每次读取一行
		while ((line = br.readLine()) != null) {
			//System.out.println(line);
			sb.append(line);
		}
		
		// 如果有错误输出
		if (sb.toString().length() > 0) {
			System.out.println("编译出错,错误信息如下----");
			// 输出错误提示
			System.out.println(sb);
		} else {
			System.out.println("成功完成----");
		}
	}
}

上面为“编译出错”的代码,下面为“成功完成”的代码 

RandomAccessFile——随意(任意)访问文件

Random——想访问文件的哪个点,就访问文件的哪个点(任意)

RandomAccessFile实现了Closeable接口,所以可以使用自动关闭资源的try语句

特征

1、既可读、又可写、还可追加。相当于InputStream与OutputStream合体。

      RandomAccessFile它不会覆盖原有的文件内容。

2、只能访问文件!这就是它的局限性。

import java.io.*;
public class RandomAccessFileTest {
	public static void main(String[] args) {
		try (
			// 使用RadomAccessFile创建一个只读的输入流
			RandomAccessFile raf = new RandomAccessFile("RandomAccessFileTest.java", "r");
		)
		{
			byte[] buff = new byte[1024];
			int hasRead = -1;
			while ((hasRead = raf.read(buff)) > 0) {
				System.out.println(new String(buff, 0, hasRead));
			}
			
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}
}

创建RandomAccessFile,需要指定读(r)、写(rw)模式

体现它的“random【任意】”性的方法

seek(long pos)——用于把记录指针移动到任意位置,想访问哪个点就访问哪个点。

一开始,它的记录指针位于文件的开始位置。

使用RandomAccessFile来追加文件内容

1、把记录指针移动到最后

2、执行输出即可

import java.io.RandomAccessFile;

public class AppendTest {
	public static void main(String[] args) {
		try (
				// 使用RadomAccessFile创建一个只读的输入流
				RandomAccessFile raf = new RandomAccessFile("AppendTest.java", "rw");
			)
			{
				// 把记录指针移动到文件的最后
				raf.seek(raf.length());
				raf.write("//做人好累".getBytes());	
			} catch (Exception ex) {
				ex.printStackTrace();
			}
	}
}

使用RandomAccessFile来插入文件内容

1、把记录指针移动到指定位置

2、从当前位置到文件结尾的内容,先读取,并保存

3、输出要插入的内容

序列化

Java对象(内存)->二进制流

目的

1、在有些时候,需要把对象存储到外部存储器中持久化保存。

2、在有些时候,需要把对象通过网络传输。

可序列化的对象

Java要求序列化的类实现下面任意两个接口

1、Serializable:接口只是一个标记性的接口,实现该接口无需实现任何方法

2、Externalizable:实现该接口要实现方法。

序列化的IO流

  ObjectInputStream——负责从二进制流“恢复”对象。readObject

ObjectOutputStream——负责把对象保存到二进制流中。writeObject

import java.io.*;
class Apple implements Serializable{
	private String name;
	private String color;
	private double weight;
	
	public Apple() {
		super();
	}

	public Apple(String name, String color, double weight) {
		super();
		this.name = name;
		this.color = color;
		this.weight = weight;
	}
	
	public String getName() {
		return name;
	}
	
	public void setName(String name) {
		this.name = name;
	}
	
	public String getColor() {
		return color;
	}
	
	public void setColor(String color) {
		this.color = color;
	}
	
	public double getWeight() {
		return weight;
	}
	
	public void setWeight(double weight) {
		this.weight = weight;
	}
	
	public String toString() {
		return "Apple[name=" 
				+ name +",color=" + color
				+ ",weight=" + weight + "]";
	}
}

public class WriteObject {
	public static void main(String[] args) {
		Apple ap = new Apple("红富士", "红色", 3.4);
		System.out.println(ap);
		
		// 当程序结束时,虚拟机退出,内存中的Apple对象就被销毁了
		try (
			ObjectOutputStream oos = new ObjectOutputStream(
					new FileOutputStream("app.bin"));
		) 
		{
			oos.writeObject(ap); //把ap对象写入app.bin文件中
		}
		catch (Exception ex) {
			// TODO: handle exception
		}
	}
}

import java.io.*;
public class ReadObject {
	public static void main(String[] args) {
		try (
			ObjectInputStream ois = new ObjectInputStream(
					new FileInputStream("app.bin"));
		)
		{
			Apple ap = (Apple)ois.readObject();
			System.out.println(ap);
		}
		catch (Exception ex) {
			ex.printStackTrace();
		}
	}
}

序列化机制

总结

Java传统IO的基本体系

字节输入流字节输出流字符输入流字符输出流
访问文件InputStreamOutputStreamReaderWriter
访问数组FileXxx
访问管道ByteArrayXxxCharArrayXxx
访问字符串StringXxx
过滤流FilterInputStreamFilterOutputStreamFilterReaderFilterWriter
打印流PrintStreamPrintWriter
转换流InputStreamReaderOutputStreamWriter
特殊流DataInputStreamDataOutputStream
ObjectInputStreamObjectOutputStream

RandomAccessFile

1、它只能访问文件。相当于DataInputStream和DataOutputStream组合

2、任意,由seek(int pos)。

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

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

相关文章

在unity中利用公开变量引用物体和组件(有手就会)

在任意的脚本组件中(必须先绑定物体),添加一个公开的 GameObject 类型的变量 using System.Collections; using System.Collections.Generic; using UnityEngine;public class test1 : MonoBehaviour {public GameObject other;// Start is …

蛋白质折叠

文章目录 4. GNNs for Protein foldingChemical Structures as GraphsProtein Structure PredictionMethods for Protein Structure PredictionOld method: fragment assemblyNew StrategyCo-evolution Analysis Towards An End-to-End Workflow AlphaFold2 architecture补充&a…

物联网AI MicroPython传感器学习 之 DRV8833电机驱动模块

学物联网,来万物简单IoT物联网!! 一、产品简介 DRV8833电机驱动模块是一种单H桥电机驱动芯片,可驱动2个直流电机和4线步进电机。内置过流保护,短路保护,欠压闭锁和过热保护,带低功耗睡眠模式。…

一篇文章讲懂mysql中的锁

事务的隔离性是由锁来实现的。 为什么需要锁 锁是计算机协调多个进程或线程并发访问某一资源的机制。在程序开发中会存在多线程同步的问题,当多个线程并发访问某个数据的时候,尤其是针对一些敏感的数据(比如订单、金额等)&#x…

高校教务系统登录页面JS分析——巢湖学院

高校教务系统密码加密逻辑及JS逆向 本文将介绍高校教务系统的密码加密逻辑以及使用JavaScript进行逆向分析的过程。通过本文,你将了解到密码加密的基本概念、常用加密算法以及如何通过逆向分析来破解密码。 本文仅供交流学习,勿用于非法用途。 一、密码加…

UDP和TCP:奇妙的网络协议

之前,我们介绍了基本的网络原理和网络编程的相关知识,接下来会根据TCP/IP协议栈,具体的介绍这里的关键协议和知识。这部分知识虽然是理论为主,但是这是我们作为程序员的基本内功,非常重要。 本文我们重点介绍TCP和UDP…

TCP协议的报文结构及其特性

文章目录 一、TCP报头二、TCP的特性2.1确认应答2.2超时重传2.3连接管理2.3.1三次握手2.3.2四次挥手 2.4滑动窗口2.5流量控制2.6拥塞控制2.7延时应答2.8捎带应答2.9面向字节流2.10TCP异常情况的处理 一、TCP报头 TCP报头(header)分为11个部分,TCP报头大小为(20~60个…

springboot实现文件上传和读取

一.本地存储(将图片存放在本地的nginx服务器上) 在nginx上创建images目录,用来存储上传的文件 (使用nginx的好处是暴露端口,便于外界访问,同时nginx作为静态资源服务器在处理静态资源方面更快) 不然你访问文件就需要通…

android 13/14高版本SurfaceFlinger出现VSYNC-app/VSYNC-appSf/VSYNC-sf剖析

问题背景: 了解surfaceflinger的vsync同学都可能知道vsync属于一个节拍器,主要用来控制有节奏的渲染,不至于会产生什么画面撕裂等现象。 一般vsync都有会有2部分: app部分vsync,控制各个app可以有节奏的上帧 surfacef…

FPGA project : sdram

sdram读写控制器 实验目标: 设计并实现一个 SDRAM 数据读写控制器,使用 PC 机通过串口向 SDRAM 写入 10 字 节数据,并将写入的 10 字节数据读出,通过串口回传至 PC 机,在串口助手上位机上打印 显示回传数据。 框图设…

towxml的使用,在微信小程序中快速将markdown格式渲染为wxml文本

towxml的使用,在微信小程序中快速将markdown格式渲染为wxml文本 Towxml概述安装下载 Towxml在小程序中使用 towxml Towxml概述 towxml3.0 支持以下功能: ● echarts图表,默认禁用,需自行构建以开启此功能 ● LaTeX数学公式&#…

3D视觉硬件技术

目前市面上主流的3D光学视觉方案有三种: 双目立体视觉法(Stereo Vision,在下文称双目法),结构光法(Structured Light,在下文称结构光)以及飞行时间法(Time of Flight, ToF在下文称T…

Java日志系统之Logback

目录 Logback Logback的简单使用 Logback配置文件 log4j.peoperties转化为logback.xml Logback Logback的性能要比log4j要好。 Logback分为三个模块: logback-core:其他两个模块的基础模块logback-classic:它是log4j的一个改良版本&am…

【网络协议】聊聊ICMP与ping是如何测试网络联通性

ICMP协议格式 ping是基于iCMP协议工作的,ICMP全称Internet Control Message Protocol,就是互联网控制报文协议。其实就是有点类似于古代行军打仗,哨探进行前方探明具体情况。 IMCP本身处于网络层,将报文封装在IP包里,…

AYIT嵌入式实验室2023级C语言训练1-4章训练题

文章目录 前言1. 判断闰年2.(ab-c)*d的计算问题3.计算三角形的周长和面积4.牛牛的等差数列5.判断字母6.网购7. 牛牛的通勤8.获得月份天数9.大小写转换10.KiKi说祝福语11.小乐乐求和12.奇偶统计13.KiKi求质数个数14.乘法表15.牛牛学数列16.牛牛学数列217.数位之和18.魔法数字变换…

Android---OkHttp详解

OkHttp 是一套处理 HTTP 网络请求的依赖库,由 Square 公司设计研发并开源,目前可以在 Java 和 Kotlin 中使用。对于 Android App,OkHttp 现在几乎已经占据了所有的网络请求操作。RetroFit OkHttp 实现网络请求似乎成了一种标配。 因此&…

【每日一题】—— 最大素因子

🌏博客主页:PH_modest的博客主页 🚩当前专栏:每日一题 💌其他专栏: 🔴 每日反刍 🟡 C跬步积累 🟢 C语言跬步积累 🌈座右铭:广积粮,缓称…

基于springboot实现4S店车辆管理系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现4S店车辆管理系统演示 摘要 随着信息技术和网络技术的飞速发展,人类已进入全新信息化时代,传统管理技术已无法高效,便捷地管理信息。为了迎合时代需求,优化管理效率,各种各样的管理系统应运而生&am…

PC性能监测工具,您不可或缺的好帮手

前言 在计算机使用过程中,常有人会问:为什么我的CPU利用率接近100%?为什么可用内存不断减少? 幸运的是,Windows性能工具包为我们提供了帮助。是什么应用程序的锅,我们使用该性能工具一探究竟。 一、 Win…

国内在线协作工具有哪些?

随着信息技术的快速发展和互联网的普及,在线协作工具成为了现代团队和企业不可或缺的一部分。国内市场上涌现出许多优秀的在线协作工具,为团队协作提供了高效、便捷的解决方案。 在本文中,我们将向大家推荐3款国内备受赞誉的在线协作工具&…