黑马程序员--字节流、转换流、流操作规律

本文详细介绍了Java中的字节流与字符流的概念、特点及其应用实践,包括使用字节流复制文件、利用缓冲技术提高文件复制效率,以及通过转换流实现纯文本数据的高效操作。

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

第一节--字节流

字节流和字符流的操作基本相同,不同的是字节流既可以操作文本文件也可以操作媒体文件等其他文件。

字节写入流:OutputStream

使用write方法写入时不需要flush,它不像字符写入流,需要先将字符写入流对象中,查看编码表,转换成字节后再flush写入目的地。但需要关闭。

字节读取流:InputStream

特有的方法available(),可以获取读取流关联的文件的字节个数,这样在定义字节数组时可以设置合适的长度,不需要进行循环读取,可以一次将文件读取到数组中。但要注意,文件较大时有内存溢出的风险,慎用!

练习:使用字节流复制文件

/*
 * 需求:使用字节读写流对象,将E盘下demo.txt文件复制到E盘下demo_copy.txt
 * 思路:1.创建字节读取流对象,关联要读取的文件
 * 		 2.创建字节写入流对象,指定写入数据的目的地
 *       3.分别调用read()和write()方法,循环读写
 */
package io;

import java.io.*;

public class FileInputStreamDemo {

	public static void main(String[] args) throws IOException {
		copy_2();

	}
	//方式一:使用一次读一个字节的方法
	public static void copy_1() throws IOException{
		//声明字节读写流对象的引用
		FileInputStream fis = null;
		FileOutputStream fos = null;
		int byt = 0;
		try {
			//创建读写流对象,关联读取的文件,指定写入的目的地
			fis = new FileInputStream("E:\\demo.txt");
			fos = new FileOutputStream("E:\\demo_copy.txt");
			//调用read方法读取数据,当读到文件末尾,返回-1
			while((byt = fis.read())!=-1)
				fos.write(byt);
		}
		catch (IOException e) {
			throw new IOException("文件复制失败");
		}
		finally{
			try {
				if(fis != null)
					fis.close();
			}
			catch (Exception e2) {
				throw new IOException("文件读取失败");
			}
			try {
				if(fos != null)
					fos.close();
			}
			catch (Exception e2) {
				throw new IOException("文件写入失败");
			}
		}
	}
	//方式二:使用读取数组的方法
	public static void copy_2() throws IOException{
		//声明字节读写流对象的引用
		FileInputStream fis = null;
		FileOutputStream fos = null;
		int len = 0;
		try {
			byte[] bt = new byte[1024];
			//创建读写流对象,关联读取的文件,指定写入的目的地
			fis = new FileInputStream("E:\\demo.txt");
			fos = new FileOutputStream("E:\\demo_copy.txt");
			//调用read方法,将数据读取到数组中,返回的是读取的字节个数,读到文件末尾返回-1
			while((len = fis.read(bt))!=-1)
				fos.write(bt,0,len);
		}
		catch (IOException e) {
			throw new IOException("文件复制失败");
		}
		finally{
			try {
				if(fis != null)
					fis.close();
			}
			catch (Exception e2) {
				throw new IOException("文件读取失败");
			}
			try {
				if(fos != null)
					fos.close();
			}
			catch (Exception e2) {
				throw new IOException("文件写入失败");
			}
		}
	}
}

练习:使用字节流缓冲区技术复制文件

/*
 * 需求:使用字节流缓冲区技术,将E盘下的1.mp3文件复制到E盘下的2.mp3文件中
 * 思路:
 * 1.创建字节流缓冲区对象
 * 2.调用读取数组的方法读取数据
 * 3.调用写入数组的方法写入数据
 * 4.关闭资源
 */
package io;
import java.io.*;
public class BufferedByteCopy {

	public static void main(String[] args) throws IOException {
		copyMp3();

	}
	public static void copyMp3() throws IOException{
		BufferedInputStream bis = null;
		BufferedOutputStream bos = null;
		try {
			int len = 0;
			byte[]byt = new byte[1024];
			bis = new BufferedInputStream(new FileInputStream("e:\\1.mp3"));
			bos = new BufferedOutputStream(new FileOutputStream("e:\\2.mp3"));
			while((len = bis.read(byt))!=-1)
				bos.write(byt,0,len);
		}
		catch (Exception e) {
			throw new IOException("文件复制失败");
		}
		finally{
			try {
				if(bis != null)
					bis.close();
			}
			catch (Exception e2) {
				throw new IOException("文件读取失败");
			}
			try {
				if(bos != null)
					bos.close();
			}
			catch (Exception e2) {
				throw new IOException("文件写入失败");
			}
		}
	}

}

注意:字节流中read方法和write方法的特点

read方法读取一个字节,为啥返回的是int类型而不是byte类型呢?是为了避免-1的出现。数据以字节码形式存储,一个字节占一个8位,如果这个8位是81,那么表示的值是-1,字节读取会中断。为了避免这种情况,read方法将字节提升为int类型,即占48位,前面3三个8位补了0,此时表示的值是255write方法写入时会将int类型进行强转为byte类型,保证了和原有数据一致性。

第二节--转换流及流操作规律

/*
读取键盘录入。
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();
			if(ch=='\r')
				continue;
			if(ch=='\n')
			{
				String s = sb.toString();
				if("over".equals(s))
					break;
				System.out.println(s.toUpperCase());
				sb.delete(0,sb.length());
			}
			else
				sb.append((char)ch);

		}
	}
}

</pre></div><p></p><p>读取键盘录入的流对象是字节读取流对象,读取键盘录入时一次只能读取一个字节。从上面例子可以看出,读取键盘录入结束时类似于一次读取一行数据。怎样让字节流对象可以实现一次读一行呢?<span style="font-family:Consolas;">java</span><span style="font-family:宋体;">提供了读取转换流对象,可以将字节转换成字符,读取转换流是字符流的子类,可以使用字符读取流缓冲区进行增强,从而实现一次读一行。</span></p><p>类似的,写入转换流可以将字符转换成字节。</p><p> </p><blockquote style="margin: 0 0 0 40px; border: none; padding: 0px;"><p></p><p>练习:使用转换流<span style="font-family:Consolas;">InputStreamReader</span><span style="font-family:宋体;">和</span><span style="font-family:Consolas;">OutputStreamWriter</span></p><p><span style="font-family:Consolas;"></span><pre name="code" class="java">class  TransStreamDemo
{
	public static void main(String[] args) throws IOException
	{
		//获取键盘录入对象。
		//InputStream in = System.in;

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

		//为了提高效率,将字符串进行缓冲区技术高效操作。使用BufferedReader

		//BufferedReader bufr = new BufferedReader(isr);


		//键盘的最常见写法。
		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();
	}
}

注意:转换流是属于字符流体系

 

转换流:为了方便操作纯文本数据,可以将字节流转换成字符流,将字节按照编码表转换成字符进行操作,转换流就实现了这个功能。转换流可以接收一个字节流对象,并指定编码表。转换流有两个可以直接操作文本文件的子类,但编码表示默认的。需要指定编码表时,必须使用转换流。

 

流对象其实很简单,就是读取和写入。但是因为具体的功能不一样,流体系提供了很多流对象,那么如何选择合适的流对象呢?这就需要掌握流的操作规律。

流的操作规律:

1.明确要操作的数据的源和目的

源:就是需要用到读取,考虑两个读取流体系:InpuStreamReader

目的:就是需要用到写入,考虑两个写入流体系:OutputStreamWriter

2.明确操作的数据是否是纯文本

是纯文本:考虑使用字符流体系:ReaderWriter

不是纯文本:考虑使用字节流体系:InpuStreamOutputStream

3.虽然明确了体系,但具体使用那些对象呢?需要通过具体的设备来确定。

源设备:硬盘、内存、键盘

目的设备:硬盘、内存、控制台

4.最后考虑是否需要对流的功能进行增强,比如缓冲。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值