马程序员 java_IO流笔记(二)

本文深入探讨了装饰设计模式的原理及应用实例,并详细解析了Java中的流技术,包括字符流、字节流及其缓冲机制,展示了如何利用这些技术进行文件操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

-------android培训 、java培训、期待与您交流! ----------

装饰设计模式 

一般有两种方式可以实现给一个类或者对象增加功能

        一个是继承机制 使用继承机制是给先有类天健功能的一种有效途径,通过继承一个先有类可以使得子类在拥有自身方法的同时还拥有父类的方法,再是这中方式是静态的,用户不能控制增加行为的方式和时机

一个是关联机制  即将一个类的对象潜入另一个对象中,由另一个对象来决定是不是调用嵌入对象的行为以便扩展自己的行为,我们称这个嵌入的对象为装饰类

与继承关系相比,

 关联关系的主要优势在于不会破坏类的封装性,而且继承是一种耦合度较大的静态关系,无法再程序运行时动态的扩展,在软件开发阶段关联关系,虽然不会比继承关系减少编码,但是到了软件维护阶段,由于关联关系使系统具有较好的松耦合性因此使得系统更加容易维护,当然关联关系的缺点是比继承关键要创建更多的对象。

装饰设计模式的典型事例

class Person
{
	public void chifan()
	{
		System.out.println("吃饭");
	}
}

class SuperPerson 
{
	private Person p ;
	SuperPerson(Person p)
	{
		this.p = p;
	}
	public void superChifan()
	{
		System.out.println("开胃酒");
		p.chifan();
		System.out.println("甜点");
		System.out.println("来一根");
	}
}



class  PersonDemo
{
	public static void main(String[] args) 
	{
		Person p = new Person();

		//p.chifan();

		SuperPerson sp = new SuperPerson(p);
		sp.superChifan();

	}
}

 了解BufferedReader的原理

对BufferedReader原理的理解这个类提供了一套缓冲机制,在要读取文件时,首先在内存中建立一段缓冲区,然后读取文件填充满缓冲,随后对文件的操作其实是直接作用在缓冲上,当缓冲区数据读完后再调用read方法继续填充缓冲区,以此类推。

 首先考虑到类的创建,应该传入一个Reader对象,然后通过传入的对象进行读取等操作,而缓冲技术应该是类的内部保存一个char类型的数组,将文件存入到数组中,之后的操作就是作用在这个数组之上,所以我们在类中应该建立一个char类型数组,将文件存入数组中,之后的操作就是作用在这个数组之上,所以我们在类中应该建立一个char数组的私有变量,因为涉及到对数组的操作,我们应该建立length变量,存储目前数组中保存的数据长度

字符读取流缓冲区:
该缓冲区提供了一个一次读一行的方法 readLine,方便于对文本数据的获取。
当返回null时,表示读到文件末尾。
readLine方法返回的时候只返回回车符之前的数据内容。并不返回回车符。

import java.io.*;

class  BufferedReaderDemo
{
	public static void main(String[] args) throws IOException
	{
		//创建一个读取流对象和文件相关联。
		FileReader fr = new FileReader("buf.txt");

		//为了提高效率。加入缓冲技术。将字符读取流对象作为参数传递给缓冲对象的构造函数。
		BufferedReader bufr = new BufferedReader(fr);
		

		String line = null;

		while((line=bufr.readLine())!=null)
		{
			System.out.print(line);
		}


		bufr.close();
	}

}

字节流

字节流继承体系简图


基本操作与字符流相同但是它不仅可以操作字符,还可以操作其他媒体文件

同样是提高了字节流的读写效率

小例子复制一个jpg文件

import java.io.*;
class CopyPic 
{
	public static void main(String[] args) 
	{
		/*
		new FileInputStream 读硬盘了 存放到 fis里面了 然后fis调用read一个一个往外取

		
		*/
		FileOutputStream fos = null;
		FileInputStream fis = null;
		try
		{
			fos = new FileOutputStream("2.bmp");//复制到当前目录下命名为2.bmp
			fis = new FileInputStream("1.bmp");//要复制的图片为当前文件夹下的1.bmp

			byte[] buf = new byte[1024];//设置字节数组来存储字节流

			int len = 0 ;//字节数组长度初始化

			while ((len=fis.read(buf))!=-1)
			{
				fos.write(buf,0,len);//输出字节流
			}

		}
		catch (IOException e)
		{
			throw new RuntimeException("复制文件失败");
		}
		finally
		{
			//分别关闭资源
			try
			{
				if(fis!=null)//非空表示用了流,用了才要关闭,要是空则表示没用流就是读取失败了
					fis.close();
			}
			catch (IOException e)
			{
				throw new RuntimeException("读取关闭失败");
			}
			try
			{
				if(fos!=null)
					fos.close();
			}
			catch (IOException e)
			{
				throw new RuntimeException("写入关闭失败");
			}

		}
		//System.out.println("Hello World!");
	}

}

转换流

InputStreamReader,OutputStreamWriter

 转换流的由来

         字符流与字节流之间的桥梁        

         方便了字符流与字节流之间的操作

转换流的应用

         字节流中的数据都是字符时,转成字符流操作更高效。

转换流应用
import java.io.*;

class  TransStreamDemo
{
	public static void main(String[] args) throws IOException
	{
	/*	//获取键盘录入
		InputStream in = System.in;

		//将字节流对象转换成字符流对象,使用转换流 InputStreamReader
		InputStreamReader buf = new InputStreamReader(in);

		//为了提高效率将字符串进行缓冲区技术高效操作使用BufferedReader
		BufferedReader bufer = new BufferedReader(buf);
	*/
		//键盘录入最常见写法
		BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
	/*	//建立输出流
		OutputStream out = System.out;
        //输出流转换
		OutputStreamWriter osw = new OutputStreamWriter(out);
		//缓冲区技术
		BufferedWriter bufw = new BufferedWriter(osw);
	*/
		//最常见的输出写法
		BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));
		String line = null;
		while ((line=bufr.readLine())!=null)
		{
			if("over".equals(line))
				break;
			bufw.write(line.toUpperCase());	//写入缓冲区
			bufw.newLine();					//换行
			bufw.flush();					//从缓冲区中刷出来
		}
		bufr.close();
	}
}

标准输入输出流

System类中的字段 in out

他们个代表了系统标准的输入和输出

默认输入设备是键盘,输出设备是显示器

System.in的类型是InputStream

System.out的类型是PrintStream 是OutputStream的子类FileOutputStream的子类

标准输入输出流示例

例获取键盘录入数据,然后将数据流向显示器,那么显示器就是目的地

通过system类的setln,setOut方法对默认设备进行改变

       System.setIn(newFileInputStream(“a.txt”));//将源改成文件a.txt

       System.setOut(newFileOutputStream(“2.txt”));//将目的改成文件2.txt

因为字节流处理的是文本数据,可以转换成字符流,操作更方便

BufferedReader bufr =

new BudderedReader(new InputStreamReader(System.in));

BufferedWriter bufw =

                   newBufferedWriter(new OutStreamWriter(System.out)); 

读取键盘录入。
System.out:对应的是标准输出设备,控制台。

System.in:对应的标准输入设备:键盘。

需求:
通过键盘录入数据。
当录入一行数据后,就将该行数据进行打印。

如果录入的数据是over,那么停止录入。

import java.io.*;
class  ReadIn
{
	public static void main(String[] args) throws IOException
	{
		InputStream in = System.in; //获取键盘录入对象
		StringBuilder sb = new StringBuilder();//建立一个可变的缓冲区

		while(true)
		{
			int ch = in.read();//调用流的read方法做判断
			if(ch=='\r')//判断回车符
				continue;
			if(ch=='\n')//回车了判断里面存的是不是over
			{
				String s = sb.toString();
				if("over".equals(s))//如果是就跳出
					break;
				System.out.println(s.toUpperCase());//变大写打印
				sb.delete(0,sb.length());//清空缓冲区,每次打印完了都要清空一下防止缓冲区累计边长
			}
			else
				sb.append((char)ch);//如果不是回车符那就加到缓冲区结尾

		}
	}
}

流的基本应用小结

流是用来处理数据的,处理数据时一定要先明确数据源与数据目的地; 数据源可以使文件也可以使键盘。数据目的地可以使文件,显示器或者其他设备。而流只是在帮助数据进行传输,并对传输的数据进行处理,比如过滤处理转换处理等。

如何判断什么时候使用什么流小结 

1源 键盘录入 
目的 控制台
2 需求  想把键盘录入的数据存储的到文件中
源 键盘
目的 文件 
操作流对象的基本规律
最痛苦的是流对象有很多 不知道该用哪一个
通过三个明确来完成
1 明确源和目的。
源 输入流 InputStream Reader
目的 输出流 OutputStream Writer
2 明确操作的数据是否是纯文本
是 字符流 
不是 字节流 
3 当体系明确后,在明确要使用哪个具体的对象。
通过设备来进行区分 
源设备 内存,硬盘,键盘
目的设备 内存,硬盘 控制台
需求 1 将一个文本文件中的数据存储到另一个文件中 复制文件
源 文件 因为是源所以使用读取流 InputStream Reader 
是不是操作文件本文件 是 这时就可以选择 Reader
这样体系就明确了
接下来明确要使用该体系中该使用哪个对象
明确设备:  硬盘上一个文件
Reader体系中可以操作文件的对象是 FileReader
FileReader fr = new FileReader("a.txt");
s是否需要提高效率呢? 是 加入 Reader体系中的缓冲区 BufferedReader
BufferedReader bufr = new BufferedReader(fr);
目的 OutputStream Writer
是否是纯文本呢 是 Writer
设备 硬盘 一个文件 
Writer体系中可以操作文件的对象是 FileReader
是否需要提高效率呢? 是 加入 Writer体系中的缓冲区 BufferedWriter
FileWriter fw = new FileWriter("b.txt");
BufferedWriter bufw = new BufferedWriter(fw);

2 需求 将键盘录入的数据保存到一个文件中,
这个需求中有源和目的都存在
那么分别分析
源 InputStream Reader 
是不是纯文本  是  用Reader 
设备 键盘 对应的对象是System.in
不是选择Reader么 System.in对应的不是字节流么 
为了操作键盘的文本数据方便,转成字符流按照字符串操作是最方便的
所以 既然明确了reader就将System.in转成字符流Reader用到了Reader
体系中的转换流 InputStreamReader 
InputStreamReader isr = new InputStreamReader(System.in);
需要提高效率吗 需要 BufferedReader
BufferedReader bufr = new BufferedReader(isr);
目的 OutputStream Writer 
是否是纯文本 是 Writer字符流
设备 硬盘 一个文件 使用FilerWriter 
FileWriter fw = new FileWriter("c.txt");
是否需要提高效率 需要
BufferWriter bufw = new BufferedWriter(fw);
扩展一下, 想要把录入的数据按照指定的编码表(比如 utf-8),将数组存到文件中
目的 OutputStream Writer 
是否是纯文本 是 Writer字符流
设备 硬盘 一个文件 使用FilerWriter 
但是 FileWriter是使用的默认编码表GBK
但是存储时需要加入指定的编码表UTF-8,而指定的编码表只有 转换流 可以指定。
所以要使用对象是OutputStreamWriter 而该转换流对象要接受一个字节输出流,而且还可以操作的
文件是字节输出流,
转换流什么时候使用 

字符流和字节流简练的桥梁,通常涉及到 字符编码 转换时需要用到转换流。

import java.io.*;
class  TransStreamDemo2
{
	public static void main(String[] args) throws IOException
	{
		BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
		//输出到out。txt文件里面
		BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("out.txt")));
		
		String line = null;
		while ((line = bufr.readLine())!=null)
		{
			if("over".equals(line))
				break;
			bufw.write(line);
			bufw.newLine();
			bufw.flush();
		}
		bufr.close();
		
		//System.out.println("Hello World!");
	}
}

-------android培训 、java培训、期待与您交流! ----------


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值