Java IO流操作规律 与 转换流

1 转换流

把字节流转成字符流,再用字符流的方法,处理字节

1.1 InputStreamReader

InputStreamReader是字节流通向字符流的桥梁;它使用指定的 charset 读取字节并将其 解码为字符。
它使用的字符集可以由名称指定或显式给定,或接受平台默认的字符集。
每次调用 InputStreamReader中的一个 read()方法 都会导致从底层输入流读取一个或多个字节。

要启用从字节到字符的有效转换,可以提前从底层流读取更多的字节,使其超过满足当前读取操作所需的字节。
为了达到最高效率,可以考虑在 BufferedReader内 包装 InputStreamReader。如:
BufferedReader in = new BufferedReader( new InputStreamReader(System.in));

字符流的由来就是 字节流+编码表,字节流+编码表 组成的对象 就是 转换流

1.2 OutputStreamWriter

读和写正好是相反的,读—读的都是字符数据 — 字节变字符。写 — 写的都是字节数据 — 字符变字节
OutputStreamWriter 的 直接子类 — FileWriter
OutputStreamWriter 已经把字符转换为了字节, FileWriter就不用转换了, 直接拿过来用就可以了

代码实例:

将键盘录入的数据写入到一个文件中

BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("b.txt")));
		String line = null;
		while((line=bufr.readLine())!=null){
			if("over".equals(line))
				break;
			bufw.write(line.toUpperCase());
			bufw.newLine();
			bufw.flush();
		}	
	}

将一个文本文件内容显示在控制台上

BufferedReader bufr = new BufferedReader(new InputStreamReader(new FileInputStream("a.txt") ) );
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out);

将一个文件文件中的内容复制到的另一个文件中

 BufferedReader bufr = new BufferedReader(new InputStreamReader(new FileInputStream("a.txt") ) ); 
 BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("b.txt")));
1.3 转换流的使用场景

什么时候使用转换流

1 源或者目的对应的设备是字节流,但是操作的却是文本数据,可以使用转换作为桥梁,提高对文本操作的便捷
2 一旦操作文本涉及到具体的指定编码表时,必须使用转换流

码表是固定写死的,必须使用转换流来做

将一个中文字符串数据按照指定的编码表写入到一个文本文件中

分析:
FileWriter fw = new FileWriter("a.txt");
fw.write("你好");
注意:既然需求中已经明确了指定编码表的动作,那就不可以使用FileWriter,因为FileWriter内部是使用默认的本地码表,只能使用其父类。OutputStreamWriter
OutputStreamWriter接收一个字节输出流对象,既然是操作文件,那么该对象应该是FileOutputStream
OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("a.txt"),charsetName);
需要高效吗?
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(“a.txt”),charsetName));

转换流 OuputStreamWriter可以指定编码表

public static void writeText() throws IOException {
		InputStreamReader isr = new InputStreamReader(new FileInputStream("gbk_1.txt"),"utf-8");
		char[] buf = new char[10];
		int len = isr.read(buf);
		String str = new String(buf,0,len);
		System.out.println(str);
		isr.close();
	}

说明:

OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("gbk_3.txt"),"GBK");
OutputStreamWriter osw = new >OutputStreamWriter(new FileOutputStream("gbk_3.txt"));
FileWriter fw = new FileWriter("gbk_3.txt");

这三句代码的功能是等同的。 使用的都是默认的码表
FileWriter:其实就是转换流指定了本机默认码表的体现
只要看到一堆乱七八糟的中文,一定是用 GBK解码 解出来的,只有GBK能解码中文
InputStreamReader isr = new InputStreamReader(new FileInputStream("u8_1.txt"),"gbk"); // 乱码
只能是相同的编码,相同的解码

用GBK编码,用GBK解码
用 utf-8编码,用 utf-8 解码
用GBK编码的文件,用 utf-8来解码。出来的是 ??(你好)

2 IO流 操作规律

流对象太多,开发时不知道用哪个对象合适,弄清楚 IO流操作规律,可以很好的掌握 IO流的使用

四个明确
1 明确源和目的(汇)

源:InputStream Reader
汇:OutputStream Writer

2 明确数据是否是纯文本数据

源是纯文本数据 :Reader 不是 InputStream
目的是纯文本数据:Writer 不是 OutputStream

3 明确具体设备

源设备: 硬盘 File 键盘 System.in 内存数组 网络Socket流
目的设备:硬盘 File 键盘 System.out 内存数组 网络Socket流

4 是否需要其他额外功能

1 是否需要高效(缓冲区) — 是,就加上 Buffer
2 是否需要转换 — 是,转换流 InputStreamReader OutputStreamWriter

代码实例

2.1 演示键盘录入,并打印在控制台上

读取一个键盘录入的数据,并打印在控制台上

private static void readOneByte() throws IOException {
		
		InputStream in = System.in;
		int ch = in.read(); // 阻塞式方法,有数据就读,没有数据就等,所以是阻塞式方法
		System.out.println(ch);
		int ch1 = in.read();//阻塞式方法。		
		System.out.println(ch1);
		int ch2 = in.read();//阻塞式方法。		
		System.out.println(ch2);
		
		/*
		 *   其他对象,关了之后,接着 new一个,还可以读,但是标准类不行
		 *   System.in --- 从系统获取的流对象就一个,关了就没有了,
		 *   所以不用关,它会随着系统的消失而消失
		 */
//		in.close(); // 为什么不关流 因为关了之后,就没办法再读了
		
	}

输出结果:

a
97
13
10

分析:
上面的代码,只能读3个数据,因为就写了读3个字节的方法,为什么会出现 13 ,10?每读取一个字符,都会输出 13 10 — 回车符 \r\n的ASCII码 a 对应 97
想不断的读取键盘录入的数据,应该怎么做,— 循环

 int ch = 0;
		while ( (ch=in.read()) !=-1 ){
	   System.out.println(ch);
	}

改进:

要求

获取用户键盘录入的数据
并将数据变成大写显示在控制台上
如果用户输入的是over,结束键盘录入

结束标记,是用户自己定义的,而不是 按快捷键等强行结束

思路
键盘录入一次只读取一个字节 — 如果是中文,需要读两次

1,因为键盘录入只读取一个字节,要判断是否是over,需要将读取到的字节拼成字符串。
2 需要一个容器。StringBuilder
3 在用户回车之前将录入的数据变成字符串判断即可

private static void readBytesEndWithOver() throws IOException {
//	    InputStream in = System.in; // 键盘录入有一个弊端,一次只能读取一个字节
	  StringBuilder sb = new StringBuilder();  // 1 创建容器
	  InputStream in = System.in; // 2 获取键盘 读取流
	  int ch = 0; // 定义变量,记录读取到的字节,并循环获取
	  while((ch=in.read())!=-1){
		  // 在存储之前,需要判断是否是换行标记,因为换行标记不存储
		  if(ch=='\r'){
			  continue;
		  }
		  if(ch=='\n'){ // 如果是 \n,说明一行结束了
			  String temp = sb.toString();
			  if("over".equals(temp))
				  break;
			  System.out.println(temp.toUpperCase());
			//如果不加这一行,再次输入时,会把上次和以前所有的输入的内容,都显示出来
			  sb.delete(0,sb.length());
		  }
		  else 
			  sb.append((char)ch);//将读取到的字节存储到StringBuilder中
	  }
	}

输出结果:

asd
ASD
vbn
VBN
over
2.2 复制一个文本文件

分析
1 明确源和目的:源:InputStream Reader 目的:OutputStream Writer
2 是否是纯文本 :是— 源 ReaderWriter
3 明确具体设备:源:硬盘 File 目的:硬盘 File

FileReader fr = new FileReader("a.txt");
FileWriter fw = new FileWriter("b.txt");
流对象一旦确定,剩下的就是读写操作

4 需要额外功能吗:需要,需要高效

BufferedReader bufr = new BufferedReader(new FileReader("a.txt"));
BufferedWriter bufw = new BufferedWriter(new FileWriter("b.txt"));

2.3 读取键盘录入的信息,并写入到一个文件中

分析
1 明确源和目的:源:InputStream Reader 目的:OutputStream Writer
2 是否是纯文本 :是— 源 ReaderWriter
3 明确具体设备:源:键盘 System.in 目的:硬盘 File

InputStream in = System.in;
FileWriter fw = new FileWriter("b.txt");
这样做可以完成,但是麻烦。将读取的字节数据转成字符串。再由字符流操作

4 需要额外功能吗:需要,需要转换

将字节流转成字符流。因为明确的源是Reader,这样操作文本数据做便捷。
所以要将已有的字节流转成字符流。使用字节–>字符 —InputStreamReader
InputStreamReader isr = new InputStreamReader(System.in);
FileWriter fw = new FileWriter("b.txt");

还需要功能吗?需要 — 高效

BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufw = new BufferedWriter(new FileWriter("b.txt"));

2.4 将一个文本文件数据 显示在控制台上

分析
1 明确源和目的:源:InputStream Reader 目的:OutputStream Writer
2 是否是纯文本 :是— 源 ReaderWriter
3 明确具体设备:源:硬盘 File 目的:控制台 System.out

FileReader fr = new FileReader("a.txt");
OutputStream out = System.out;//PrintStream
流对象一旦确定,剩下的就是读写操作

4 需要额外功能吗:需要,转换

FileReader fr= new FileReader("a.txt");
OutputStreamWriter osw = new OutputStreamWriter(System.out);

需要,高效

BufferedReader bufr = new BufferedReader(new FileReader("a.txt"));
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));

2.5 读取键盘录入的数据,显示在控制台

分析
1 明确源和目的:源:InputStream Reader 目的:OutputStream Writer
2 是否是纯文本 :是— 源 ReaderWriter
3 明确具体设备:源:键盘 System.in 目的:控制台 System.out

InputStream in = System.in;
OutputStream out = System.out;//PrintStream
流对象一旦确定,剩下的就是读写操作

4 需要额外功能吗:需要,转换。因为都是字节流,但是操作的却是文本数据。所以使用字符流操作起来更为便捷。

InputStreamReader isr = new InputStreamReader(System.in);
OutputStreamWriter osw = new OutputStreamWriter(System.out);

需要,高效

BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值