java基础---节点流、过滤流、桥接转换流

本文详细介绍了Java中的IO流,包括节点流如FileInputStream和FileOutputStream,以及字符流FileReader和FileWriter。强调了内存数组流如CharArrayReader和CharArrayWriter,内存字符串流StringReader和StringWriter的使用。此外,还讨论了过滤流的概念,如BufferedReader和BufferedWriter,以及转换流InputStreamReader和OutputStreamWriter在不同编码间的桥梁作用。最后,举例展示了自定义流实现加密和桥接转换流的应用。

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

节点流

类型字符流字节流
File文件FileReader、FileWriter
FileInputStreamFileOutputStream
内存数组

CharArrayReader、

CharArrayWriter

ByteArrayInputStream
ByteArrayOutputStream
内存字串StringReader、StringWriter
管道
PipedReader PipedWriter
PipedInputStream PipedOutputStream

文件节点流

FileInputStreamFileOutputStream是文件字节流,是一种节点流
文件字节输入流的构造方法:
  • FileInputStream("文件名称"),如果文件不存在则FileNotFoundException
  • FileInputStream(File)
文件字节输出流的构造方法:
  • FileOutputStream(“文件名称”) 如果文件不存在则新建文件,如果文件存在则覆盖文件内容
  • FileOutputStream(String name文件名称, boolean append是否采用追加方式)
FileReaderFileWriter类似
FileInputStreamFileOutputStream两个类属于结点流,第一个类的源端和第二个类的目的端都是磁盘文件,它们的构造方法允许通过文件的路径名来构造相应的流。
如:
FileInputStream infile = new FileInputStream("myfile.dat");
FileOutputStream outfile = new FileOutputStream("results.dat");
要注意的是,构造FileInputStream, 对应的文件必须存在并且是可读的,而构造FileOutputStream时,如输出文件已存在,则必须是可覆盖的。

需求: 将存储路径下的data/calcCharNum.txt拷贝到data/cal.txt

package com.yan2;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;

/*
 * 文件节点流
 * 	字节  FileInputStream和FileOutputStream
 * 
 * 	文件字节输入流的构造方法:
 * - FileInputStream("文件名称"),如果文件不存在则FileNotFoundException
 * - FileInputStream(File)
 * 		throws或者try/catch
 * 	文件字节输出流的构造方法:
 * 	- FileOutputStream(“文件名称”)  如果文件不存在则新建文件,如果文件存在则覆盖
 * 	文件内容
 * - FileOutputStream(String name文件名称, boolean append是否采用追加方式)
 * 
 * FileReader和FileWriter类似
 * 	字符  FileReader和FileWriter
 */

public class Test1 {
	public static void main(String[] args) {
		File file = new File("data/calcCharNum.txt");
		if (file.exists()) {
			try (Reader r = new FileReader(file); Writer w = new FileWriter("data/cal.txt", true)) {
				char[] arr = new char[8192];
				int len = 0;
				while ((len = r.read(arr)) > 0) {
					w.write(arr, 0, len);
				}
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			} catch (IOException e) {
				System.out.println("出问题了:" + e.getMessage());
			}
		}
	}
}


//构造输出文件流时可以使用两种不同的方式 
//OutputStream os=new FileOutputStream("e:\\dd.txt"); 如果文件不存在则自动创建;如果文件存在则进行覆盖 
//OutputStream os=new FileOutputStream("e:\\dd.txt",true),这里的boolean类型参数 表示是否采用追加的方式写入文件

内存数组节点

如果文本则使用char[],如果二进制则使用byte[]
构造器方法
  • CharArrayReader(char[] buf)其中char[]就是数据的来源,也就是说Reader就是从char[]中读取数据
  • CharArrayRead(char[] buf, int offset, int length)
CharArrayWriter用于实现向一个字符数组中写入数据,这个数组可以自动调整大小
ByteArrayInputStreamByteArrayOutputStreamCharArrayReader以及CharArrayWriter类似,支持操作的内容不同而已,操作byte[]char[]
package com.yan2;

import java.io.CharArrayReader;
import java.io.CharArrayWriter;
import java.io.Reader;
import java.io.Writer;
import java.util.Scanner;

/*
 * 内存数组节点 
 * 
 * 如果文本则使用char[],如果二进制则使用byte[]
 * 
 * 构造器方法
 * - CharArrayReader(char[] buf)其中char[]就是数据的来源,
 * 也就是说Reader就是从char[]中读取数据
 * - CharArrayRead(char[] buf, int offset, int length)
 * 
 * CharArrayWriter用于实现向一个字符数组中写入数据,这个数组可以自动调
 * 整大小
 * 
 * ByteArrayInputStream、ByteArrayOutputStream和CharArrayReader以及
 * CharArrayWriter类似,支持操作的内容不同而已,操作byte[]与char[]
 */
public class Test2 {
	public static void main(String[] args) throws Exception {
		String str = "abc中国人民解放军123";
		char[] arr = str.toCharArray();
		Reader r = new CharArrayReader(arr);
		while (true) {
			int kk = r.read();
			if (kk == -1)
				break;
			System.out.println((char) kk);
		}
		System.out.println("键盘录入数据");
		Scanner sc = new Scanner(System.in);
		Writer w = new CharArrayWriter();
		while (true) {
			String ss = sc.nextLine();
			if ("quit".equals(ss))
				break;
			w.write(ss);
		}
		sc.close();
		// 需要使用CharArrayWriter中定义的特殊方法,获取输出的目标数组
		if (w instanceof CharArrayWriter) {
			CharArrayWriter caw = (CharArrayWriter) w;
			caw.append("dsuhsad");// 向输出的数组末尾添加内容 StringBuilder
			// 获取输出的目标数组
			char[] target = caw.toCharArray();
			System.out.println(new String(target));
		}
	}
}
//ByteArrayInputStream、ByteArrayOutputStream和CharArrayReader以及
//CharArrayWriter类似,支持操作的内容不同而已,操作byte[]与char[]

内存字串流

StringReader用于从一个字串String中读取数据

StringWriter用于给一个StringBuffer中写入数据,实现一个可变长的字串

package com.yan2;

import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;

/*
 *内存字串流
 * StringReader用于从一个字串String中读取数据
 * 
 * StringWriter用于给一个StringBuffer中写入数据,实现一个可边长的字串 
 */
public class Test4 {
	public static void main(String[] args) throws IOException {
		String str = "中abc国人民解放军";
		Reader r = new StringReader(str);
		while (true) {
			int kk = r.read();
			if (kk == -1) {
				break;
			}
			System.out.print((char) kk);
		}

		Writer w = new StringWriter();
		for (int i = 0; i < 26; i++) {
			w.write(('a' + i));
		}
		// 测试它左边的对象是否是它右边的类的实例,返回 boolean 的数据类型
		if (w instanceof StringWriter) {
			// 创建StringWriter实例对象
			StringWriter sw = (StringWriter) w;
			// getBuffer()方法,返回流的字符缓冲对象StringBuffer
			StringBuffer ss = sw.getBuffer();
			System.out.println(ss);
		}
	}
}

总结

  • 读写文件使用节点流FileInputStream/FileOutputStreamFileReader/FileWriter,如果操作文本文件,建议使用FileReader/FileWriter,如果操作二进制文件建议使用FileInputStream/FileOutputStream
  • 需要建立缓冲区(建立临时文件的方式效率低),可以考虑使用内存节点,例如 CharArrayReader/CharArrayWriterStringReader/StringWriterByteArrayInputStream/ByteArrayOutputStream
  • 如果需要一个二进制缓冲区可以使用ByteArrayInputStream/ByteArrayOutputStream,如果需要一个字符缓存可以使用CharArrayReader/CharArrayWriterStringReader/StringWriter
  • 如果数据量不是特别大使用CharArrayReader/CharArrayWriter更为方便,如果数据量大而且可能需要直接操作缓冲区则使用StringReader/StringWriter
  • StringWriter中提供了方法getBuffer():StringBuffer

过滤流类型

过滤流就是在节点流的基础上附加功能

处理类型字符流字节流
缓存BufferedReader、BufferedWriterBufferedInputStream、BufferedOutputStream
过滤处理FilterReader、FilterWriterFileInputStream、FileOutputStream
桥接处理

InputStreamReader、

OutputStreamWriter

对象序列化处理ObjectInputStream、ObjectOutputStream
数据转换DataInputStream、DataOutputStream
行数统计LineNumberReaderLineNumberInputStream
回滚处理PushbackReaderPushbackInputStream
打印功能PrintWriterPrintStream

过滤流

就是decorate模式中的抽象装饰角色

FilterInputStream/FilterOutputStream和FilterReader/FilterWriter

public class FilterInputStream extends InputStream { //典型的装饰模式
        protected volatile InputStream in; //被装饰目标
        
        protected FilterInputStream(InputStream in) { //通过构造器组装被装饰对象
                this.in = in;
        }
        public int read() throws IOException {//调用Filter中的read方法时实际操作是由
被装饰对象实现的
                return in.read();
        }
}

所谓的过滤流实际上就是类似上面的加密处理,在输入之后(后置处理,被装饰对象先执行)或者输出之前(前置处理,先处理然后被装饰对象执行)进行一下额外的处理,最终实际操作是调用被装饰对象的方法完成工作,依靠这种装饰模式实现在节点流的基础上附加额外功能。当然也允许多个过滤流嵌套从而达到功能累加的目的

FilterInputStream实际上就是一个装饰抽象角色

自定义流实现循环13加密

  • 读取数据不变:FileReader---BufferedReader
  • 写出数据自定义过滤流Round13Reader(FilterReader)
package com.yan3;

import java.io.FileReader;
import java.io.FilterReader;
import java.io.IOException;
import java.io.Reader;

/*
 * 抽象装饰FilterInputStream和FilterOutputStream   FilterReader和FilterWriter
 */
public class Test2 {
	public static void main(String[] args) throws Exception {
//		Reader r = new Round13Reader(new FileReader("data/calcCharNum.txt"));
		Reader r = new Round13Reader(new FileReader("data/round13.txt"));

//		Writer w = new FileWriter("data/round13.txt");
//		char[] cc = new char[1024];
		int kk = -1;
		while ((kk = r.read()) != -1) {
//			w.write(kk);
			System.out.print((char) kk);
		}
		r.close();
//		w.close();
	}
}

class Round13Reader extends FilterReader {
	protected Round13Reader(Reader in) {
		super(in);
	}

	@Override
	public int read() throws IOException {
		int kk = super.read();
		// 判断是否是英文字符
		if (kk >= 'A' && kk <= 'Z') {
			return (kk - 'A' + 13) % 26 + 'A';
		} else if (kk >= 'a' && kk <= 'z') {
			return (kk - 'a' + 13) % 26 + 'a';
		}
		return kk;
	}
}

 

 桥接转换流

InputStreamReaderOutputStreamWriterjava.io包中用于处理字符流的最基本的类,用来在字节流和字符流之间作为中介:从字节输入流读入字节,并按编码规范转换为字符;往字节输出流写字符时
先将字符按编码规范转换为字节。使用这两者进行字符处理时,在构造方法中应指定一定的平台规范,以便把以字节方式表示的流转换为特定平台上的字符表示。
转换流可以在构造时指定其编码字符集
  • InputStreamReader用于将一个InputStream类型的输入流自动转换为Reader字符流
  • OutputStreamWriter用于将一个Writer字符输出流转换为OutputStream字节输出流

InputStreamReader构造器

  • InputStreamReader(InputStream)
  • InputStreamReader(InputStream, String)
  • InputStreamReader(InputStream, Charset)
  • InputStreamReader(InputStream, CharsetDecorder)
package com.yan3;

import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.Charset;

/*
 * InputStreamReader构造器
 * - InputStreamReader(InputStream)
 * - InputStreamReader(InputStream, String)
 * - InputStreamReader(InputStream, Charset)
 * - InputStreamReader(InputStream, CharsetDecorder)
 */
public class Test4 {
	public static void main(String[] args) throws Exception {
//		Reader r = new InputStreamReader(new FileInputStream("data/pavkage-info.java"), "UTF-8");
		Reader r = new InputStreamReader(new FileInputStream("data/package-info.java"), Charset.forName("UTF-8"));// Charset.defaultCharset()默认的字符集
		int kk = -1;
		while (true) {
			kk = r.read();
			if (kk == -1)
				break;
			System.out.print((char) kk);
		}
	}
}

 

Reader r=new InputStreamReader(System.in);
int kk=r.read(); //例如输入的是中国,这里实际读取的是""
//因为这里读取的是一个字节,所以输入"中国",实际读取的是""的一个字节,输出显示为?
kk=System.in.read();
System.out.println("输入的是:"+(char)kk);
InputSteram is=new InputStreamReader(System.in,”iso8859-1”);
注意:一般不建议自行设置编码字符集,除非是必须的
Reader r=new InputStreamReader(System.in, "gbk");
int kk=r.read(); //例如输入的是"中国",实际读取的是""
System.out.println("输入的是:"+(char)kk);
package com.yan3;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
/*
 * ### 桥接转换流
 * InputStreamReader和OutputStreamWriter是java.io包中用于处理字符流的最基本的类,
 * 用来在字节流和字符流之间作为中介:从字节输入流读入字节,并按编码规范转换为字符;往字节输出流写字符时
 * 先将字符按编码规范转换为字节。使用这两者进行字符处理时,在构造方法中应指定一定的平台规范,以便把以字
 * 节方式表示的流转换为特定平台上的字符表示。
 * 转换流可以在构造时指定其编码字符集
 * InputStreamReader用于将一个InputStream类型的输入流自动转换为Reader字符流
 * OutputStreamWriter用于将一个Writer字符输出流转换为OutputStream字节输出流
 */

public class Test3 {
	public static void main(String[] args) throws Exception {
		InputStream is = new FileInputStream("data/package-info.java");
		Reader r = new InputStreamReader(is);
		while (true) {
//			int kk = is.read();
			int kk = r.read();
			if (kk == -1) {
				break;
			}
			System.out.print((char) kk);
		}

		OutputStream os = new FileOutputStream("data/out.txt");
		Writer w = new OutputStreamWriter(os);
		w.write("中国人民解放军");
		w.close();
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值