Java语言的IO流详解

简介: Java语言的IO流详解

一、IO概念

• I/O 即输入Input/ 输出Output的缩写,其实就是计算机调度把各个存储中(包括内存和外部存储)的数据写入写出的过程;

• java中用“流(stream)”来抽象表示这么一个写入写出的功能,封装成一个“类”,都放在http://java.io这个包里面。

二、来理解“流”是什么?通过“流”的形式允许java程序使用相同的方式来访问不同的输入/输出源。stream是从起源(source)到接收的(sink)的有序数据。我们这里把输入/输出源对比成“水桶”,那么流就是“管道”,这个“管道”的粗细、单向性等属性也就是区分了不同“流”的特性。

三、IO流的分类

可以从三个不同的维度进行分类:

• 1、按照流的方向(输出输入都是站在程序所在内存的角度划分的)

• 输入流:只能从中读取数据【主要由InputStream和Reader作为基类】

• 输出流:只能向其写入数据【主要由outputStream和Writer作为基类】

在下图中,从磁盘读取数据到内存是输入流,从client读取数据到server是输入流;同样,把内存数据写到磁盘是输出流,把server数据写到client是输出流

• 2、按照流的操作颗粒度划分

• 字节流:以字节为单元,可操作任何数据【主要由InputStream和outPutStream作为基类】

• 字符流:以字符为单元,只能操作纯字符数据,比较方便【主要由Reader和Writer作为基类】

• 3、按照流的角色划分

• 节点流:可以从/向一个特定的IO设备(如磁盘,网络)读/写数据的流,也叫【低级流,主要由】

• 处理流:用于对一个已存在的流进行连接和封装,通过封装后的流来实现数据的读/写功能,也叫【高级流】下图中可以看出来,处理流就是在基础的字节流上,进行了封装,增加了特定的功能,使得传输更适合特定的场景。

四、流的原理以及一共有多少IO流

•  1、流的原理解析流其实我们可以想象成一个“水管”,源端和目的端就是两个“水桶”,数据是通过这个“水管”进行流动传输的,以InputStream和Reader为例,水管的每个“水滴”就是具体的数据,如果是字节流,那么一个“水滴”就是一个字节,如果是字符流,那么一个“水滴”就是一个字符。

当创建一个流对象的时候,如fis=new  FileInputStream(“…\xx\xx.txt”),记录指针来表示当前正准备从哪个“水滴”开始读取,每当程序从InputStream或者Reader里面取出一个或者多个“水滴”后,记录指针自定向后移动;除此之外,InputStream和Reader里面都提供了一些方法来控制记录指针的移动。

如果是处理流的话,就相当于在这个水管上面装了一些“控制阀门”,最终用户只要关心“阀门”具备的能力就行

• 2、java中所有流汇总

http://java.io中子类有40个“流”类,我们用以下表格来综合划分,当然这些流你不用都去花时间一个一个看过来,我们只要熟悉掌握几类常用的“流”就足够了,后续项目中如果用到陌生的“流”,知道原理的话可以快速地去检索学习下就ok了。

上图中我们可以看到,InputStream/Reader,OutputStream/Writer 是整个I/O体系的基类,他们本身不能用来创建实例,下面开始逐一对常见的I/O类进行实战

五、常见IO流的实战

1、访问操作文件(FileInputStream/FileReader ,FileOutputStream/FileWriter)

FileInputStream中包含以使用FileInputStream为例,类中包含的属性及方法,我们可以在线查看jdk的api文档http://tool.oschina.net/apidocs/apidoc?api=jdk-zh),下面只是截图了FileInputStream的构造方法:

1)使用FileInputStream,从文件读取数据

import java.io.*;
public class TestFileImportStream {
public static void main(String[] args) {
int b=0;
FileInputStream in = null;
try {
in =new FileInputStream("C:\\Users\\41639\\Desktop\\java\\FileText\\src\\TestFileImportStream.java");
}catch(FileNotFoundException e){
System.out.println("file is not found");
System.exit(-1);
}
try {
long num=0;
while ((b=in.read())!=-1) {
System.out.println((char)b);
num++;
}
in.close();
System.out.println();
System.out.println("共读取了"+num+"个字节");
}catch(IOException e) {
System.out.println("IO异常,读取失败");
System.exit(-1);
}
}

2)使用FileOutputStream,往文件里写数据

import java.io.*;
public class TextFileOutputStream {
public static void main(String[] args) {
int b=0;
FileInputStream in = null;
FileOutputStream out = null;
try {
in =new FileInputStream("C:\\Users\\41639\\Desktop\\java\\FileText\\src\\TestFileImportStream.java");
out=new FileOutputStream("C:\\Users\\41639\\Desktop\\java\\temp\\out.java");
}catch(FileNotFoundException e){
System.out.println("file is not found");
System.exit(-1);
}
try {
while ((b=in.read())!=-1) {
out.write(b);
}
in.close();
out.close();
}catch(IOException e) {
System.out.println("IO异常,读取失败");
System.exit(-1);
}
System.out.println("文件复制完成");
}
}

PS:大家也可以尝试使用FileReader、FileWriter,看看和FileInputStream、FileOutputStream有什么区别

2、缓存流的使用(BufferedInputStream/BufferedOutputStream,BufferedReader/BufferedWriter)

import java.io.*;
public class TestBufferStream {
public static void main (String[] args) throws IOException{
BufferedInputStream bis=null;
BufferedOutputStream bos=null;
try {
FileInputStream fis = new FileInputStream("C:\\Users\\41639\\Desktop\\java\\FileText\\src\\TestFileImportStream.java");
FileOutputStream fos = new FileOutputStream("C:\\Users\\41639\\Desktop\\java\\temp\\out2.java");
bis = new BufferedInputStream(fis);
bos = new BufferedOutputStream(fos);
byte[] b = new byte[1024];
int off=0;
while ((off=bis.read(b))>0) {
bos.write(b,0,off);
}
bis.close();
bos.close();
}catch (IOException e) {
e.printStackTrace();
}finally {
bis.close();
bos.close();
}
}
}

从代码中可以看到,他们最基本的其实也是FileInputStream和FileOutputStream,在这个“流”的基础上,又加了缓存的功能流BufferedInputStream和BufferedOutputStream。相对比较好理解。

3、转换流的使用(InputStreamReader/OutputStreamWriter)

字面意思理解,转化流就是用来转化的,那么到底是什么转什么呢?我们可以通过以下的例子来熟悉。读取键盘输入的每一行内容,并写入到文本中,直到遇到over行结束输入

import java.io.*;
public class TransStreamTest {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new FileWriter("C:\\Users\\41639\\Desktop\\java\\temp\\test1031.txt"));
String line =null;
while ((line=br.readLine())!=null) {
if ("over".contentEquals(line)) {
break;
}
bw.write(line);
bw.newLine();
bw.flush();
}
bw.close();
br.close();
}
}

PS:readLine()方法在进行读取一行时,只有遇到回车(\r)或者换行符(\n)才会返回读取结果,这就是“读取一行的意思”,有兴趣的同学查看readLine()源码

4、对象流的使用(FileInputStream/ObjectOutputStream)

前面讲了字节和字符流,包括封装在他们上面的处理流,那么我们想,在程序设计的过程中,我们都是用类和对象来描述定义,能不能直接把对象进行传输。答案当然是肯定的,对象流其实就是一种特殊的处理流水,也是在基础的字节流上去作封装。【可以应用于游戏存盘】

下面程序使用一个对象流,把对象直接写到文件中

import java.io.*;
public class ObjectStreamTest {
public static void main(String[] args) throws Exception{
try {
Person P=new Person("Jeccica",26);
FileOutputStream fos=new FileOutputStream("C:\\Users\\admin\\Desktop\\Java\\temp\\22.txt");
ObjectOutputStream oos=new ObjectOutputStream(fos);
oos.writeObject(P);
oos.flush();
oos.close();
}catch(FileNotFoundException e) {
e.printStackTrace();
}catch(IOException e) {
e.printStackTrace();
}
FileInputStream fis=new FileInputStream("C:\\Users\\admin\\Desktop\\Java\\temp\\22.txt");
ObjectInputStream ois=new ObjectInputStream(fis);
Person P2=(Person)ois.readObject();
System.out.println(P2.name+"的年龄为"+P2.age);
}
}
class Person implements Serializable{
String name=null;
int age=0;
Person(String _name,int _age){
name=_name;
age=_age;
}
}

5、字节数组流的使用(ByteArrayInputStream/ByteArrayOutputStream)【通常结合数据流DataInputStream/DataOutputStream】

我们分析了常见的节点流和常见的处理流等,经常而言我们都是针对文件的操作,然后带上缓冲的节点流进行处理,但有时候为了提升效率,我们发现频繁的读写文件并不是太好,那么于是出现了字节数组流,即存放在内存中,因此有称之为内存流;其中字节数组流也一种节点流;除了节点流外,我们也将学习另外一种处理流,即数据流。数据处理流是用于针对数据类型传输处理的,是一种处理流,即是在节点流之上的增强处理,一般用于序列化和反序列化的时候用到。

import java.io.*;
public class DataStream {
public static void main(String[] args) {
ByteArrayOutputStream baos=new ByteArrayOutputStream();//创建字节数组流,同时会在内存里面创建数组
DataOutputStream dos=new DataOutputStream(baos);//对字节数组流外封装成数据处理流
try {
dos.writeDouble(Math.random());//利用数据流里面的写入方法,写一个Double类型的随机数据
dos.writeBoolean(true);
ByteArrayInputStream bias=new ByteArrayInputStream(baos.toByteArray());//toByteArray()方法是创建一个新分配的字节数组。数组的大小和当前输出流的大小。这里指的是baos这个字节数组
System.out.println(bias.available());
DataInputStream dis=new DataInputStream(bias);
System.out.println(dis.readDouble());
System.out.println(dis.readBoolean());
dos.close();
dis.close();
}catch (IOException e) {
e.printStackTrace();
}
}
}


相关文章
|
4天前
|
安全 Java
|
3天前
|
存储 Java
杭州 java IO流详解(借鉴-侵-删)
杭州 java IO流详解(借鉴-侵-删)
7 0
|
4天前
|
Java 数据处理 开发者
Java IO流专家级教程:深入理解InputStream/OutputStream和Reader/Writer的内部机制
【6月更文挑战第26天】Java IO流涉及字节流(InputStream/OutputStream)和字符流(Reader/Writer),用于高效处理数据输入输出。InputStream/OutputStream处理二进制数据,常使用缓冲提升性能;Reader/Writer处理文本,关注字符编码转换。两者都有阻塞IO操作,但Java NIO支持非阻塞。示例代码展示了如何使用FileInputStream/FileOutputStream和FileReader/FileWriter读写文件。理解这些流的内部机制有助于优化代码性能。
|
4天前
|
存储 自然语言处理 Java
Java IO流完全手册:字节流和字符流的常见应用场景分析!
【6月更文挑战第26天】Java IO流涵盖字节流和字符流,字节流用于二进制文件读写及网络通信,如图片和音频处理;字符流适用于文本文件操作,支持多语言编码,确保文本正确性。在处理数据时,根据内容类型选择合适的流至关重要。
|
4天前
|
Java 开发者
Java IO流实战技巧:如何优化InputStream/OutputStream和Reader/Writer的使用?
【6月更文挑战第26天】Java IO流优化涉及缓冲、资源管理、字符编码和流式处理。使用Buffered流提高读写效率,如`BufferedInputStream`和`BufferedReader`。确保资源关闭使用try-with-resources,如`try (InputStream is = ...) {...}`。处理文本时指定编码,如`InputStreamReader(is, StandardCharsets.UTF_8)`防止乱码。流式处理大文件,分块读写避免内存溢出,以减少内存占用。这些技巧能提升程序性能和健壮性。
|
4天前
|
自然语言处理 Java
Java IO流进阶教程:掌握字节流和字符流的高级用法!
【6月更文挑战第26天】Java IO流助你高效交换数据,包括字节流(InputStream/OutputStream)和字符流(Reader/Writer)的高级技巧。缓冲流(Buffered*)提升读写性能,对象流(Object*Stream)支持对象序列化。字符流的BufferedReader/BufferedWriter优化文本处理,注意字符集如UTF-8用于编码转换。掌握这些,优化IO操作,提升代码质量。
|
4天前
|
Java
Java IO流终极指南:从InputStream/OutputStream到Reader/Writer的全面解读
【6月更文挑战第26天】Java IO流涵盖字节流(InputStream/OutputStream)和字符流(Reader/Writer),前者处理二进制数据,后者专司文本。例如,FileInputStream/FileOutputStream用于文件的字节级读写,而FileReader/FileWriter处理字符级文本。Buffered流提供缓冲功能,提升效率。选择合适的流类取决于数据类型和性能需求。
|
4天前
|
Java 测试技术
Java IO流深度剖析:字节流和字符流的性能对比!
【6月更文挑战第26天】Java IO流分字节流和字符流,字节流处理所有类型数据(如图片),字符流处理文本(基于Unicode)。字节流直接处理,性能高,适合非文本文件;字符流处理文本时考虑编码,适合文本文件。性能测试显示,字节流在读写非文本文件时更快,而字符流在处理文本时更方便。选择流类型应依据数据类型和需求。
|
4天前
|
存储 设计模式 Java
Java IO流大揭秘:如何高效使用InputStream/OutputStream和Reader/Writer?
【6月更文挑战第26天】Java IO流核心基础,涉及InputStream/OutputStream(字节流)和Reader/Writer(字符流)。高效使用的关键包括:使用Buffered流提升性能,如BufferedInputStream和BufferedOutputStream;处理编码,通过InputStreamReader和OutputStreamWriter指定如UTF-8编码;应用装饰器模式,如DataOutputStream增强功能。理解并巧妙运用这些技巧能优化数据读写操作。
|
4天前
|
自然语言处理 Java 数据处理
Java IO流全解析:字节流和字符流的区别与联系!
【6月更文挑战第26天】Java IO流涵盖字节流与字符流。字节流(InputStream/OutputStream)处理数据单位为字节,适用于二进制和文本,而字符流(Reader/Writer)专注于文本,处理单位为字符,处理编码转换。字符流在字节流基础上添加编码处理,以装饰器模式实现。文件复制示例展示了两者区别:字节流直接复制所有数据,字符流处理字符编码。理解并选择适当流类型对优化程序至关重要。

热门文章

最新文章