重新开始学Java-8IO流

重新开始学Java-8IO流

  • 8-IO流
    • 概述
      • 输入输出概念
      • 字符流和字节流
      • 常用的16个流
      • 类结构图
    • FileInputStream
    • FileOutputStream
    • FileReader
    • FileWriter
    • BufferedReader
      • 前提介绍
      • BufferedReader重点
      • 装饰者模式
    • BufferedWriter
    • DataOutputStream和DataInputStream
      • 基本信息
      • DataOutputStream
      • DataInputStream
    • 标准输出流
      • PrintStream
      • PrintWriter
    • ObjectInputStream和ObjectOutputStream
      • 序列化
      • ObjectOutputStream
      • ObjectInputStream
    • File类
      • 常用方法

在Java里,读文件、输入输出是属于非常常用的部分,里面有很多类,之前一直就没搞清楚过。。。。。
终于有机会可以把输入输出这部分的内容捋捋了~

8-IO流

Tip:

这部分有很多相通的地方,从官方参考文档可以看的更具体,这里放一下参考文档的链接,可以时常参考

Java官方文档:https://docs.oracle.com/javase/8/docs/api/index.html

概述

输入输出概念

  1. 输入和输出都是程序相对于内存而言的
  2. 输入就是到内存中,通常用读取,InputStream,read表示
  3. 输出是从内存中出去,通常用写,OutputStream,write表示

字符流和字节流

  1. 根据数据的读取方式,将流分为字符流和字节流
  2. 字节流是按照字节进行读取的,适合读取视频、音频、图片等文件(相对比较万能)
  3. 字符流是按照字符进行读取的,一次读取两个字节,凑成一个字符,比较适合读取纯文本的文件
  4. 在Java包中,字符流通常用Reader和Writer结尾,字节流通常用Stream结尾

常用的16个流

注:
常用的16个流,可以分为InputStream、OutputStream、Reader、Writer四个类(同时也是父类)

FileInputStream FileOutputStream
FileReader FileWriter
BufferedInputSream BufferedOutputSream
BufferedReader BufferedWriter
DataInputStream DataOutputStream
ObjectInputStream ObjectOutputSream
OutputSreamReader InputStreamReader
PrintWriter PrintStream

类结构图

还是用类结构图表明一下IO流之间的关系

(四个类放在一张图有点放不下,分开了一下嗷)
重新开始学Java-8IO流_第1张图片
重新开始学Java-8IO流_第2张图片

FileInputStream

属于java.io包,文件字节流

应用的话,我们直接上例子比较容易理解一点

import java.io;

public class Test1{
     
	public static void main(String[] args){
     
		
		/*注意点:
		IO流函数调用可能会报错,所以在调用前需要处理错误
		代码里省略了处理错误的部分
		如果自学的话,可以try-catch简单处理一下
		如果是实际应用,报错信息可以参考官方文档,内容更详细
		*/
		
		String filePath="C:\\test.txt";
		//创建一个文件输入流
		FileInputStream fis=new FileInputStream(filePath);
		//构造函数也可以传递File类型的参数

		//开始读文件
		int temp=0;
		//read()是开始读文件,每次返回的是一个字节
		//int接受是因为ASCII码值,英文由一个字节可以读完
		//当返回值为-1时是文件读完了
		while((temp=fis.read())!=-1){
     
			System.out.print(temp);
		}

		//其他读文件的方式
		//提前准备字节数组,读取的效率会高些,1024表示读1kB大小的文件
		byte[] temp=new int[1024];
		while(fis.read(temp)!=-1){
     
			System.out.print(temp.toString());
		}

		//其他会用到的函数
		//判断流中剩余的预估字节数
		fis.available();
		//跳过多少字节不读取
		fis.skip(1024);//直接跳过了1kB字节不读

		//通常流完成任务要关闭,避免资源浪费
		fis.close();
	}
}

FileOutputStream

和FileInputStream可以类比着记忆,很多是一样的,只是一个是输入,一个是输出

具体的应用还是直接上例子

import java.io;

public class Test2{
     
	public static void main(String[] args){
     
		
		/*
		IO流函数调用可能会报错,解释如上
		*/
		
		String filePath="C:\\TestOutput.txt";
		//创建一个文件输出流
		FileOutputStream fos=new FileOutputStream(filePath);
		//构造函数也可以传递File类型的参数
		//这里需要注意的是:
		//1.如果输出的文件不存在的话,会创建文件
		//2.构造函数里还有一个boolean类型的参数,判断是否以追加的方式写入

		//开始写文件
		int x=89;
		fos.write(x)
		
		//其他写文件的方式
		//可以用字节数组写文件
		//byte[] filecontent={};
		//用数组写文件的时候,可以选择全部写,也可以设定写中间一段
		//函数是:fos.write(filecontent,起始int值,结束int值)
		//fos.write(filecontent);

		//强制刷新
		//一般建议加上,保证文件全部写入
		fos.flush();

		//通常流完成任务要关闭,避免资源浪费
		fos.close();
	}
}

FileReader

属于java.io包,文件字节流

父类InputStreamReader,是一种转换流,将字节流转换为字符流

和InputStreamReader有很多相似的地方

官方文档可以看见,FileReader的方法基本都是继承自父类的
重新开始学Java-8IO流_第3张图片
这里只说一个区别点,和FileInputStream不同,FileReader的read函数,可以接受char类型数组

这个区别的优势:文件流可以直接读一个中文字符了,一定程度能避免出现乱码

FileWriter

和FileReader是类似的

方法里特殊的点也在于write函数,传递的参数可以是char[]和String了

BufferedReader

Tip:BufferedReader的介绍中有涉及InputStreamReader的使用内容

前提介绍

为了后面理解比较方便,一些内容先提前一点说明吧~

1. 关于System.in

从文档里可以看到,System.in是一个属性,是标准的输入流,是InputStream类,所以用System.in接收控制台输入的时候,得到的是InputStream
重新开始学Java-8IO流_第4张图片

2. 关于InputStreamReader

前面有简单说明,InputStreamReader是字符流和字节流之间的一个转换类,将字节流转化为字符流

InputStreamReader的构造方法需要InputStream类型参数(暗示前面提到的System.in),同时,在构造参数中,可以指定字符编码,缺省表示默认编码

InputStreamReader本身也有read()方法,可以读取文件,但通常情况下,采用效率更高的方式

什么方式呢???

将InputStreamReader包装在BufferedReader中:

BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

BufferedReader重点

重点一:读取

除了Reader和InputStream都会用到的read(),BufferedReader的特别之处在于有一个效率更高的函数

String readLine()

这个函数的厉害之处就在于,每次直接读一行的内容,这个效率就很高了

当然,这个函数的缺点在于,每次读一行,读出来之后没有换行符。。。。。。

这时候再判断文件是否读完,直接判断函数的返回值是否为null

重点二:关闭流

虽然我们用了InputStreaReader创建BufferedReader,但最后用完关闭流的时候,直接关闭BufferedReader对象就可以了

装饰者模式

(1)作用

可以对类进行扩展,降低程序的耦合度

(2)思路

  1. 装饰者中有被装饰者的引用
  2. 实际调用的时候是创建装饰者对象,将被装饰者对象作为参数传递
  3. 装饰者和被装饰者实现同一个类/接口

(3)举个栗子

注意点:

  1. 栗子中用的类名和Java中的类名只是一样而已,注意区分
  2. 栗子解释了为什么BufferedReader创建的对象只需要关闭BufferedReader的对象,而不用管InputStreamReader对象
public abstract class Reader{
     
	public abstract void close();
}

public class FileReader extends Reader{
     
	public void close(){
     
		System.out.println("FileReader closed!");
	}
}

public class BufferedReader extends Reader{
     
	Reader reader;

	public BufferedReader(Reader reader){
     
		//采用的是多态的方式,FileReader对象也可以传进来
		this.reader=reader;
	}

	public void close(){
     
		System.out.println("FileReader类的扩展内容");
		reader.close();
	}
}

BufferedWriter

和BufferedReader也是类似的

划重点:

  1. 创建对象,构造函数保证参数传的是Writer就可以了

Writer out
= new BufferedWriter(new FileWriter(filepath));

或者

Writer out
= new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filepath,boolean)));

  1. 写文件的时候也有一个新函数newLine(),会直接写一个换行符

  2. 同样建议在写完后,用flush刷新一下,保证所有内容输出

DataOutputStream和DataInputStream

基本信息

(1)归属

java.io下

(2)优势

针对数据的IO流,可以直接根据数据类型读、写数据,不需要再进行数据类型转换

DataOutputStream

(1)实例化对象

new DataOutputStream(OutputStream)

(2)DataOutputStream输出

可以直接用write(byte[]/int)输出

也可以选择对应的数据类型进行数据,类里有的函数如下表

注意点:输出的信息是有固定格式的,所以直接打开写的文件可能会乱码

返回值 函数
void writeBoolean(boolean v)
void writeByte(int v)
void writeBytes(String s)
void writeChar(int v)
void writeChars(String s)
void writeDouble(double v)
void writeFloat(float v)
void writeInt(int v)
void writeLong(long v)
void writeShort(int v)
void writeUTF(String str)

DataInputStream

和DataOutputStream是对应的,也是类似的,就类比着来吧

这趴过~

标准输出流

PrintStream

标准输出流,字节流形式,通常用来打印信息到控制台

PrintStream=System.out

可以改变输出流的输出位置,使之输出到固定文件夹下

需要应用到System包中的static void setOut(PrintStream out)函数

举个栗子

System.setOut(new PrintStream(new FileOutputStream("log.txt")));
//此时输出信息就会写在log.txt文件中
System.out.println("test");

PrintWriter

也是标准输出流,字符流形式

用的相对PrintStream会少些

ObjectInputStream和ObjectOutputStream

序列化

后面会用到,先介绍一下吧

(1)含义

将Java对象的状态保存到硬盘中

(2)要求

Java对象实现序列化接口Serializable

(3)Serializable接口

java.io包下,没有具体的方法,属于一种标志化的接口

(4)Serializable本质

给Java类添加了一个序列化版本号的属性

建议手动提供序列化版本号(因为当序列化版本号不一致时,序列化会出错)

举个栗子

static final long seralVersionUID=123456L;

(5)其他

需要排除Java类中某个属性不需要参加序列化的时候,用transient关键词修饰

ObjectOutputStream

通常会用ObjectOutputStream来序列化Java对象到硬盘中(序列化写)

具体写的流程,写个栗子吧

//创建Java对象
Student stu=new Student("Li Ming",20);
//创建输出流
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("data"));
//写对象
oos.writeObject(stu);
//刷新、关闭
oos.flush();
oos.close();

ObjectInputStream

与序列化相对应,反序列化

和ObjectOutputStream相似,类比着用吧~~

File类

前面好像说了很多File对象,也是比较常用的一个类,这里补一下

File类在java.io下,不是流,不能进行读写操作

File类是计算机中文件夹和文件的抽象表现,一般用来操作文件的

常用方法

  1. 构造方法

形参一般是String或者URL,文件的相对路径或者绝对路径都可以

  1. boolean createNewFile()

当且仅当具有此名称的文件还不存在时,创建新的空文件

  1. boolean exists()

判断文件是否存在

  1. String getAbsolutePath()

获取文件的绝对路径

  1. String getName()

获取文件名

  1. String getParent()

获取文件父文件路径

  1. boolean isFile()

判断是否为文件

  1. boolean isDirectory()

判断是否为目录

  1. long lastModified()

返回文件最后一次修改的时间

  1. long length()

返回文件绝对路径的长度

  1. boolean mkdir()

在文件不存在的时候,创建路径名指定的文件目录

  1. boolean mkdirs()

和mkdir类似,不同的是创建路径名指定的多重文件目录

以上。
IO流的内容就是这样了,基本总结的都是比较常用的,不常用的就慢慢积累吧,其中很多相通的内容

你可能感兴趣的:(Java,java)