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

这篇具有很好参考价值的文章主要介绍了【疯狂Java讲义】Java学习记录(IO流)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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);
			}
		}
	}
}

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

 列出某个磁盘所有的.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等基类

流的概念模型

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

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

缓冲流

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

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

反正你把流用完了,

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

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

IO流一共涉及40多个类

字节流 字符流
节点流 InputStream OutputStream Reader Writer 抽象
FileInputStream FileOutputStream FileReader FileWriter 访问文件
ByteArrayInputStream ByteArrayOutputStream CharArrayReader CharArrayWriter 数组
PipedInputStream PipedOutputStream PipedReader PipedWriter 访问管道
StringReader StringWriter 访问字符串
缓冲流 BufferedInputStream BufferedOutputStream BufferedReader BufferedWriter 缓冲
FilterInputStream FilterOutputStream FilterReader FilterWriter 抽象
PrintStream PrintWriter 打印
InputStreamReader OutputStreamWriter 转换
DataInputStream DataOutputStream 特殊

所有以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));
		}
	}
}

运行结果: 

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

 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();
			}
		}
	

运行结果: 

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

复制文本文件

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();
		}
	}
}

运行结果: 

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

节点流直接与IO节点关联

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

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

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

        过滤流的好处:

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

        ——使用过滤流的方法执行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();
		} 
	}
}

运行结果: 

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

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();
		}	
	}
}

运行结果:

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

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();
		}
	}
}

运行结果:

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

重定向标准输入输出

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文本文件中 

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

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学习记录(IO流),疯狂Java,学习

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("成功完成----");
		}
	}
}

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

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

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

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

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();
		}
	}
}

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

创建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
		}
	}
}

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

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的基本体系

字节输入流 字节输出流 字符输入流 字符输出流
访问文件 InputStream OutputStream Reader Writer
访问数组 FileXxx
访问管道 ByteArrayXxx CharArrayXxx
访问字符串 StringXxx
过滤流 FilterInputStream FilterOutputStream FilterReader FilterWriter
打印流 PrintStream PrintWriter
转换流 InputStreamReader OutputStreamWriter
特殊流 DataInputStream DataOutputStream
ObjectInputStream ObjectOutputStream

RandomAccessFile

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

2、任意,由seek(int pos)。文章来源地址https://www.toymoban.com/news/detail-722419.html

到了这里,关于【疯狂Java讲义】Java学习记录(IO流)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32外设芯片驱动学习记录 —— (二) PCA9555 IO扩展芯片驱动开发

    一、芯片介绍 二、Datasheet解读 1.硬件说明 2.寄存器说明 3.通信过程 三、驱动代码编写 1.软件I2C驱动 2. PCA9555芯片驱动函数 总结         PCA9555可设置16路输入或输出口,I2C接口,用于IO扩展,3个硬件地址引脚寻址,工作电压:VCC(2.3V 至 5.5V)。 1)框图   INT:中断输出 A0,

    2024年02月11日
    浏览(52)
  • Linux学习记录——사십사 高级IO(5)--- Epoll型服务器(2)(Reactor)

    本篇基于上篇代码继续改进,很长。关于Reactor的说明在后一篇 上面的代码在处理读事件时,用的request数组是临时的,如果有数据没读完,那么下次再来到这里,就没有这些数据了。所以得让每一个fd都有自己的缓冲区。建立一个Connection类,然后有一个map结构,让这个类和每

    2024年01月20日
    浏览(60)
  • Linux学习记录——사십사 高级IO(6)--- Epoll型服务器(3)(Reactor)

    看完前两篇再看这篇,本篇将会写Reactor EpollServer.hpp中创建一个函数HandlerRequest,用它来做Recver函数的数据处理,也就是数据分析。 改一下回调函数,不向外暴露Connection类。 Main.cc中就不需要两个函数,一个计算函数就可以 处理数据那里再加上最后的步骤 回到Recver函数,调用

    2024年01月20日
    浏览(46)
  • Linux学习记录——사십오 高级IO(6)--- Epoll型服务器(3)(Reactor)

    看完前两篇再看这篇,本篇将会写Reactor EpollServer.hpp中创建一个函数HandlerRequest,用它来做Recver函数的数据处理,也就是数据分析。 改一下回调函数,不向外暴露Connection类。 Main.cc中就不需要两个函数,一个计算函数就可以 处理数据那里再加上最后的步骤 回到Recver函数,调用

    2024年01月23日
    浏览(59)
  • 揉捻Map-疯狂Java

    邻接矩阵(Adjacency Matrix): 优点: 缺点: 邻接表(Adjacency List): 优点: 缺点: 关联矩阵(Incidence Matrix): 优点: 缺点: 其他表示方法: 1、社交网络分析: 2、路由和通信网络: 3、推荐系统: 4、地图和导航系统: 5、数据库和知识图谱: 6、组织结构和关系分析:

    2024年02月16日
    浏览(29)
  • 疯狂数据结构-栈-Java

    需要注意的是,在使用栈时要避免两个常见的问题:栈上溢(stack overflow)和栈下溢(stack underflow)。栈上溢发生在尝试向已满的栈中插入元素时,而栈下溢发生在尝试从空栈中弹出元素时。 这个代码演示了使用数组实现的栈的基本操作。你可以根据需要进行进一步扩展和优

    2024年02月16日
    浏览(33)
  • java io流 学习笔记

    通过IO我们能对硬盘文件进行读和写。(网络数据的传输也涉及到io)。 按照 流的方向 进行分类:分为输入、输出流。 往内存中去:叫做 输入(Input) 。或者叫做 读(Read) 。 从内存中出来:叫做 输出(Output) 。或者叫做 写(Write) 。 按照 读取数据方式 不同进行分类: 按照 字节 的

    2024年02月14日
    浏览(37)
  • Android问题记录 - Unable to make field private final java.lang.String java.io.File.path accessible

    最近一个Flutter项目有新需求,开发时一直是在iOS设备上运行,花了几天做完后运行到Android设备测试,结果项目构建失败了。 Flutter: 3.7.11 Android Studio: 2022.2.1 Java: 17.0.6 Gradle: 7.4 Android Gradle Plugin (AGP): 4.1.3 项目构建报错日志: 报错有点眼熟,根据以往开发经验,应该是Gradle版本

    2024年02月04日
    浏览(60)
  • JAVA学习:IO流篇(输入输出流)

    输入:将文件以数据流的形式读取到java程序中 输出:通过java程序将数据流写入文件中 按照方向分,可以分为输入流和输出流。 按照单位分,可以分为字节流和字符流,字节流是指每次处理的数据以字节为单位,字符流是指每次处理的数据以字符为单位。 按照功能分,可以

    2023年04月16日
    浏览(41)
  • Java学习16(IO设计模式)

    1、装饰器模式? 装饰器(Decorator)模式 可以在不改变原有对象的情况下拓展其功能。 装饰器模式通过 组合替代继承 来 扩展原始类的功能 ,在一些继承关系比较复杂的场景(IO 这一场景各种类的继承关系就比较复杂)更加实用。 对于字节流来说, FilterInputStream (对应输入

    2024年02月01日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包