流类总结

  • java内存中存的字符都是Unicode编码的,当读取磁盘中的文件的时候,默认通过GBK解码(记事本的ANSI编码,就是这种默认编码),但是磁盘/网络中有各种各样的的编码方式(比如:UTF-8,UTF-8是网页比较流行的一种格式,但是它无法通过默认的GBK解码,只能通过UTF-8进行解码),因此从java内存到磁盘/网络或者从磁盘/网络到java内存中会有一个转换过程,InputStreamReader和OutputStreamWriter可指定编码格式
  • https://blog.csdn.net/m0_37732829/article/details/80571166
  • 将数据存到电脑中,最根本的格式是二进制的格式,但是当存入比如文档中或者别的文件中的时候,会有自己的一个编码格式,将二进制转换成自己的编码格式,当读入到java程序中的时候,java又将他们自己的编码格式变成Unicode编码格式。当从java程序读到别的文件中的时候,又将Unicode编码格式转换成其余的编码格式。
  • 做题的时候不需要想太多,比如需要一个String类型的,就用Buffered流,需要读int类型的,就用Data流,需要读结构体类型的,就用结构体类型的流。
  • 字符流的时候,write(String类型)一般文件中不会错
  • 做题的时候,先想到底是读/写字节/字符进来,最终以什么形式,然后再想各种形式之间的转换问题。
  • 想要什么类型,中间需要经过多少转换要想清楚

一、输入流和输出流的四种抽象基本类是InputStream、OutputStream、Reader、Writer

输入流和输出流是相对于java内存而言的
输入流(读到java内存中):InputStream、Reader
输出流(从java内存中读出):OutputStream、Writer


(一)InputStream

直接子类有:FileInputStream, ObjectInputStream
间接子类有:BufferedInputStream(FileInputStream),DataInputStream(FileInputStream)

字节为单位,通过默认编码从磁盘/网络中读取文件到java内存中进行的操作

1、基本操作

read括号中没有或者是byte[]类型,返回值是int类型

在这里插入图片描述


(二)Reader

直接子类有:BufferedReader, InputStreamReader
间接子类有:FileReader(InputStreamReader)

字符为单位从磁盘/网络中读取文件到java内存中进行的操作

1、基本操作

read括号中没有或者是char[]类型,返回值是int类型

在这里插入图片描述


(三)OutputStream

直接子类有:ObjectOutputStream、BufferedOutputStream
间接子类有:DataOutputStream, FileOutputStream

字节为单位将java内存中的数据写到磁盘/网络中

1、基本操作

write括号中的是int或者byte[]类型,返回值是int类型,但是作用:将指定的字节写入该输出流中

在这里插入图片描述


(四)Writer

直接子类有:BufferedWriter, OutputStreamWriter
间接子类有:FileWriter, PrintWriter

字符为单位将java内存中的数据写到磁盘/网络中

1、基本操作

write括号中的是int或者char[]或者String类型,返回值是void类型

在这里插入图片描述


二、文件输入流和输出流的四种基本类是FileInputStream、FileOutputStream、FileReader、FileWriter

输入流和输出流是相对于java内存而言的
输入流(读到java内存中):FileInputStream、FileReader
输出流(从java内存中读出):FileOutputStream、FileWriter


(一)FileInputStream(以字节的形式读入char,输出也要为char)

FileInputStream in=null;//可能会抛出一个已检查异常//别忘记导入包
try
	{
		in=new FileInputStream("TestFileInputStream.java");
	}
	catch(FileNotFoundException e)
	{
		System.out.println("找不到指定文件");
		System.exit(-1);//直接退出程序
	}
	try
	{
		ong num=0;
		while((b=in.read())!=-1)//每次读一个字节给b,-1的意思是已经读到文件结尾了
		{
			System.out.print((char)b);//读入char,输出也要为char//read的返回值是int类型的
			num++;//统计多少个字节
		}
		System.out.println();
		System.out.println("共读取了"+num+"个字节");
	}
  • read()返回类型是int,结果为-1代表读到结尾了
  • 因为读的时候是按照字节来读的,所以输出的时候需要强制转换成char类型的

(二)FileReader(以字符的形式读入char,输出也要为char)

FileReader fr=null;//可能会抛出一个已检查异常//别忘记导入包
int c=0;
try
{
	fr=new FileReader("E:\\workplace\\KeJian\\src\\TestFileReader.java");
	int ln=0;
	while((c=fr.read())!=-1)//没有读到文件结尾
	{
		System.out.print((char)c);//读入char,输出也要为char
		ln++;
	}
	System.out.println("共读取了"+ln+"个字符");
}
  • read()返回类型是int,结果为-1代表读到结尾了
  • 因为读的时候是按照字节来读的,所以输出的时候需要强制转换成char类型的

(三)FileOutputStream(以字节的形式写到磁盘中)

  • 如果通过FileInputStream读入,那么就需要用FileOutputStream与其相匹配,如果用FileWriter,会导致中文输出不正常,因为按照字节读入,就要按照字节输出,不能按照字符输出,否则会导致乱码。
  • 如果通过FileInputStream读入,FileOutputStream与其相匹配输出到文件中的时候,不需要必须为char类型,因为读入和输出的方式(以字节为单位)相同
FileInputStream in=null;//可能会抛出一个已检查异常//别忘记导入包
FileOutputStream out=null;
FileWriter f=null;
try
{
	in=new FileInputStream("HelloWorld.java");
	out=new FileOutputStream("newHello.java");
	while((b=in.read())!=-1)
	{
		out.write(b);//中文正常//读完之后,写到newHello.java这个文件中去
	}
}

(四)FileWriter(以字符的形式写到磁盘)

FileWriter fw=null;//可能会抛出一个已检查异常//别忘记导入包
FileOutputStream fs=null;
try
	{
		fw=new FileWriter("E:\\workplace\\KeJian\\unicode.txt");//双斜杠是转移符的问题,\\代表\
		fs=new FileOutputStream("E:\\workplace\\KeJian\\unicode1.txt");
		for(int c=0;c<=50;c++)
		{
			fw.write(c);//乱码
			fs.write(c);//乱码
		}
	}
  • 都是乱码的原因是:需要的是字符/字节,但是传进来的是int不是一个字节/字符,所以会导致乱码
  • 可能会想,为什么前面从文件中读取完之后是int类型直接写到文件中却不是乱码呢?因为即使是int类型,也是从文件中按照字节/字符的形式读取,按照字节/字符的形式拷贝的,因此不是乱码,这里是直接把一个int类型的数字放进去,不是字节/字符形式,必然会出现乱码的问题

三、字符处理流


(一)BufferedInputStream(字节流)
括号中需要是InputStream的子类
直接子类有:FileInputStream, ObjectInputStream
间接子类有:BufferedInputStream(FileInputStream),DataInputStream(FileInputStream)

BufferedInputStream bis=null;
try
	{
		/*FileInputStream fis=new FileInputStream("HelloWorld.java");
		bis=new BufferedInputStream(fis);*/
		bis=new BufferedInputStream(new FileInputStream("HelloWorld.java"));
		int c=0;
		for(int i=0;(c=bis.read())!=-1;i++)
		{
			System.out.print((char)c);
		}
	}
  • 与 FileInputStream相比,没有太大的区别,仅仅是加快了速度
  • BufferedInputStream括号中只能new FileInputStream,别的不行
    在这里插入图片描述

(二)BufferedReader(字符流)
括号中需要是Reader的子类
直接子类有:BufferedReader, InputStreamReader
间接子类有:FileReader(InputStreamReader)

  • 作用:缓冲字符,以便提供字符、数组和行的有效读取
  • BufferedReader中能new FileReader,new InputStreamReader
  • 增加了readLine方法,返回值是String类型,比较好用,一次读取一行,因此,如果想要读取String类型的数据,就用BufferedReader

在这里插入图片描述

br=new BufferedReader(new FileReader("test.txt"));//读test.txt中的内容
String s=null;
while((s=br.readLine())!=null)
{
	System.out.println(s);
}

(三)BufferedOutputStream(字节流)
括号中需要是OutputStream的子类
直接子类有:ObjectOutputStream
间接子类有: DataOutputStream,FileOutputStream

在这里插入图片描述


(四)BufferedWriter(字符流)
括号中只能是Writer的子类
直接子类有:BufferedWriter, OutputStreamWriter
间接子类有: FileWriter, PrintWriter

  • 作用:缓冲字符,以便提供字符、数组和行的有效读取
  • BufferedWriter中 能new FileWriter 能new OutputStreamWriter
  • 增加了newLine方法,比较好用,每次写完一行之后,自动换行,因此,如果想要读完一行之后回车,就用BufferedWriter
    在这里插入图片描述

四、转换流

(一)InputStreamReader(字符流)
括号中只能是InputStream的子类,可以指定用何种形式编码

  • InputStreamReader是 InputStream中的字节转换成字符
  • 为什么要指定编码集合呢?
    因为java程序在内存中的字符都是Unicode编码的,但是从文件中读取的内容有自己的编码格式,可能是jbk编码,可能是ISO8859_1编码,还有可能是ASCILL编码,编码不同,所以要根据已有编码转换成Unicode编码,因此,要告诉java原来是什么样的编码格式(但是如果指定编码格式错误的话,会出现乱码问题)。
  • 只能new InputStream的子类,如:FileInputStream

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

FileWriter和FileOutputStream都可以实现在文章结尾继续写东西而不是覆盖掉以前的东西,至于true加到哪里上面的两张图片已经说的很清楚了。

InputStreamReader isr=null;
try
{
	isr=new InputStreamReader(new FileInputStream("TestTileInputStream.java"));//通过InputStreamReader读取FileInputStream中读取的TestTileInputStream.java中的字符
	long num=0;
	while((b=isr.read())!=-1)
	{
		System.out.print((char)b);
		num++;
	}
	System.out.println("共读取了"+num+"个字符");
}

将键盘输入的内容直接输入到文档中

String s;
InputStreamReader isr=new InputStreamReader(System.in);
/*
 * 本来应该套一个InputStream,但是套了System.in
 * 所以System.in也是InputStream类型的
 * 所以可以传给InputStreamReader
 * InputStreamReader套接了控制台键盘输入
 * System.in读入的是字节,InputStreamReader转换成了字符
 * InputStreamReader只能一个字符一个字符地读,比较麻烦,所以又套接了一个BufferedReader
* */
BufferedReader br=new BufferedReader(isr);//BufferedReader的特点,能一次读取一行
System.out.println("Unix:Type ctrl-d or cril-c to exit."+"\nWindows:Type ctrl-z to exit");
try
{
	//用Ctrl+z来结束
	while((s=br.readLine())!=null)
	{
		System.out.println("Read: "+s);//输入一行,打印一行
	}
}

(二)OutputStreamWriter(字符流)
括号中只能是OutputStream的子类,可以指定编码格式

  • OutputStreamWriter是 OutputStream中的字节转换成字符
  • 为什么要指定编码集合呢?
    因为java程序在内存中的字符都是Unicode编码的,到文件中的时候,会有自己的编码格式,可能是jbk编码,可能是ISO8859_1编码,还有可能是ASCILL编码,编码不同,所以要将Unicode编码转换成自己想要的编码格式,因此,要告诉java自己需要什么样的编码格式。
  • 只能new OutputStream的子类,如:FileOutputStream

在这里插入图片描述

try
{
	OutputStreamWriter osw=new OutputStreamWriter(new FileOutputStream("transform1.txt"));//通过FileOutputStream文件输出流,往transform1.txt中写数据
	osw.write("计算机学院");
	osw.write("SUN Java");
	System.out.println(osw.getEncoding());//写入的时候没有指定编码格式,那么就采用中文Window默认编码GBK
	osw.close();//FileOutputStream构造方法第二个参数的含义,是否追加
	osw=new OutputStreamWriter(new FileOutputStream("transform1.txt",true),"ISO8859_1");
	/*这里用FileOutputStream的重载方法,形参加了个true
	 * 这里本来默认是false,每次写的时候,会覆盖原来文件的内容
	 * 但是加了true,意思是保留原有文件内容,并且在原有文件的尾部追加新的内容
	* 编码格式改成IS08859_1,指的是英文字符,没有中文字符串
	 * lantin-1
	 * */
	osw.write("山东科技大学");//上面指定的编码格式中,没有文字字符串
	osw.write("C#");
	System.out.println(osw.getEncoding());
	sw.close();
}

在这里插入图片描述

  • ISO8859_1编码格式中没有文字字符串,所以是错误的。
  • osw=new OutputStreamWriter(new FileOutputStream(“transform1.txt”,true),“ISO8859_1”);
    /*这里用FileOutputStream的重载方法,形参加了个true
    * 这里本来默认是false,每次写的时候,会覆盖原来文件的内容
    * 但是加了true,意思是保留原有文件内容,并且在原有文件的尾部追加新的内容
    * 编码格式改成IS08859_1,指的是英文字符,没有中文字符串
    * lantin-1
    * */
    在这里插入图片描述

五、数据流

(一)DataInputStream(字节流)
括号内只能是InputStream的子类

  • 可以直接将字节类型的转换为基本类型数据
    在这里插入图片描述

(二)DataOutputStream(字节流)
括号内只能是OutputStream的子类

  • 可以直接将字节类型的转换为基本类型数据
  • 将基本类型转换为字节存起来

在这里插入图片描述


六、Print流

(一)PrintStream(字节流)

在这里插入图片描述

在这里插入图片描述

PrintStream ps=null;
try
{
	FileOutputStream fos=new FileOutputStream("redirect.txt");
	ps=new PrintStream(fos,true,"utf-8");
	/*
	 * PrintStream中有构造方法,可以有三个参数的构造方法
	 * 第一个创建一个OutputStream
	* 第二个是是不是自动的刷新、缓冲、清空
	* 第三个指定输出的字符是什么编码格式
	 * */
	if(ps!=null)
	{
		System.setOut(ps);//实现输出的重定向,不再向控制台输出,而是向指定文件中输出
	}
			
			int line=0;
			for(char c=100;c<=200;c++)
			{
				System.out.println();//此时通过FileOutputStream这个流往redirect.txt这个文件中输出
				line=0;
			}
		}
  • System.setOut(ps);可以实现重定向

(二)PrintWriter(字符流)

在这里插入图片描述
在这里插入图片描述


对象序列化

为什么要进行对象序列化呢?
目的是为了转化成字节序列,便于存盘或者是进行网络传输。存盘和网络传输的是以字节为单位,对象序列化之后,就不会考虑到编码差异等问题了。

1、想要被对象序列化,就必须要实现Serializable或者Externalizable两个接口中的某一个

2、Serializable这个接口中没有任何接口,无需实现任何方法,仅仅继承这个接口就好。

3、使对象序列化的流
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值