黑马程序员-----java基础(IO下)

本文详细介绍了Java中的IO流概念及应用,包括字节流与字符流的区别和使用方法,探讨了标准输入输出流、缓冲流及转换流的操作技巧。

-----------android培训java培训、java学习型技术博客、期待与您交流!------------ 

一、IO流

IO流:

  字节流       

字节输入流 读取数据 InputStream

字节输出流 写入数据 OutputStream

字符流

字符输入流 读取数据 Reader

字符输出流 写入数据 Writer


IO流的概述:

Java程序通过流来完成输入和输出,流是输入或输出信息的抽象。流通过Java的输入/输出系统与外设连接进行数据通信。流是抽象的对象,具体实现代码在java.io包中。

IO流的常用基类:

       1、 字节流的抽象基流:InputStreamOutputStream

        2、 字符流的抽象基流:ReaderWriter

二、字符流

通过字符流写入输出数据,通过查看API,我们发现,Writer是一个抽象类。所以,使用他的子类FileWriter

FileWriter构造方法:

FileWriter(File file) 

FileWriter(String fileName)

字符输出流操作步骤:

A:创建字符输出流对象

B:调用对象的写入数据方法,并刷新缓冲区

  C:释放资源

 问题1:为什么FileWriter没有无参构造方法?
   因为写数据的时候,一定要明确写道哪里去。
  
  问题2:flush()和close()的区别?
   flush():只刷新缓冲区,流对象还可以继续使用。
   close():先刷新缓冲区,在关闭流对象。流对象不可以继续被使用。

问题3:难道每次调用方法的时候,都需要刷新吗?或者说,不用刷,直接等到close()来解决,行不行?
   这两种方式都不可取。

写入数据的方式,有5种。

write(int ch)
   write(char[] chs,int index,int len)
   write(char[] chs)
   write(String str,int index,int len)
   write(String str)

数据没次都把以前的给覆盖了,如果我想追加写入,怎么办?
   构造的时候,用带两个参数的。
   public FileWriter(String fileName,boolean append)

字符输入流读取数据步骤:
A:创建字符输入流对象
  B:调用读取数据功能,并显示
  C:释放资源

一次读取一个字符数组
   public int read(char[] cbuf)每次读取数据,把数据存储到字符数组中,返回值是实际读取长度。

通过字节流往文件中写数据。

字节输出流操作步骤:
  A:创建字节输出流对象
  B:调用写数据的方法
 C:释放资源

字节输入流操作步骤:
  A:创建字节输入流对象
  B:调用读取数据的方式,并显示
  C:释放资源

字符缓冲流:提高了流的读写效率,所以在缓冲区创建前,要先创建流对象。即先将流对象初始化到构造函数中。 

字符缓冲流读取数据

构造方法:BufferedWriter(Writer out)

普通方法:

BufferedWriter:
   public void newLine():根据系统平台写入行分隔符
  
  BufferedReader:
   public String readLine():一次读取一行的数据。但是不包含换行符。


练习:把D盘下所有.java文件改名.jad并复制到D盘.jad文件下

public class CopyCopyCopy {
	public static void main(String[] args) throws IOException {
		File srcFile=new File("d:\\java");
		File[]fileArray=srcFile.listFiles(new FilenameFilter() {
			
			@Override
			public boolean accept(File dir, String name) {
				// TODO Auto-generated method stub
				return new File(dir,name).isFile()&&name.endsWith(".java");
			}
		});
		File deskFile=new File("d:\\jad");
		if(!deskFile.exists()){
			deskFile.mkdirs();
		}
		
		for(File file:fileArray){
			String name=file.getName();
			String newName=name.replace(".java", ".jad");
			File newFile=new File(deskFile,newName);
			
			BufferedReader br=new BufferedReader(new FileReader(file));
			BufferedWriter bw=new BufferedWriter(new FileWriter(newFile));
			String line=null;
			while((line=br.readLine())!=null){
				bw.write(line);
				bw.newLine();
				bw.flush();
			}
			bw.close();
			br.close();
		}
	}
}

二、字节流

1、字节流和字符流的基本操作是相同的,但字节流还可以操作其他媒体文件。

2、因为字节流操作的是图片,视频,音频等媒体文件这些数据都是以字节存储的,所以字节流对象可以直接对文件写入数据,不用再刷新动作

3、读写字节流  输入流(读InputStream ) 输出流(写OutputStream)

字节流缓冲区

和字符流缓冲区一样,提高了效率。

自定义读取字节流缓冲区

        需求:根据字节流缓冲区的原理,自定义一个字节流缓冲区。

注意:

        1、字节流的读一个字节的read方法为什么返回值类型不是byte,而是int

       因为有可能会读到连续8个二进制1的情况,8个二进制1对应的十进制是-1.那么就会数据还没有读完,就结束的情况。因为我们判断读取结束是通过结尾标记-1来确定的。

       所以,为了避免这种情况将读到的字节进行int类型的提升。并在保留原字节数据的情况前面了补了240,变成了int类型的数值。而在写入数据时,只写该int类型数据的最低8位。

        2byte类型的-1提升为int类型时还是-1。原因:因为在bit81前面补的全是1导致的。如果在bit81前面补0,即可以保留原字节数据不变,又可以避免-1的出现。这时将byte型数据&0xff255即可。

代码:


、标准输入输出流

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

        Ssytem.out:对应的是标准的输出设备,控制台。

        System.in的类型是InputStream.

        System.out的类型是PrintStreamOutputStream的子类FilterOutputStream的子类。

   整行录入

       当使用输入流进行键盘录入时,只能一个字节一个字节进行录入。为了提高效率,可以自定义一个数组将一行字节进行存储。当一行录入完毕,再将一行数据进行显示。这种正行录入的方式,和字符流读一行数据的原理是一样的。也就是readLine方法。

      那么能不能直接使用readLine方法来完成键盘录入的一行数据的读取呢?readLine方法是字符流BufferedReader类中方法。而键盘录入的read方法是字节流InputStream的方法。

      那么能不能将字节流转成字符流再使用字符流缓冲区的readLine方法呢?这就需要用到转换流了。


、转换流

1转换流的由来:

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

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

转换流的应用:

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

   InputStreamReader将字节流通向字符流

       a、获取键盘录入对象。

              InputStream in=System.in;

       b、将字节流对象转成字符流对象,使用转换流。

              InputStreamReaderisr=new InputStreamReader(in);

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

              BufferedReaderbr=new BufferedReader(isr);

       //键盘录入最常见写法

              BufferedReaderin=new BufferedReader(new InputStreamReader(System.in));

   OutputStreamWriter字符流通向字节流

       字符通向字节:录入的是字符,存到硬盘上的是字节。步骤和InputStreamReader转换流一样。

public class SystemInDemo {
	public static void main(String[] args) throws IOException {
		// 封装数据源
		InputStream is = System.in;
		/*
		 * 这个时候,我们拥有的是标准键盘录入。
		 * 而字节的输入流有两种读取方式:
		 * 方式1:一次读取一个字节,但是,这样的话,我们每次都需要对读取到的数据进行保存,将来判断是否一行结束,麻烦。
		 * 方式2:一次读取一个字节数组,但是,这个时候,最大的问题是,数组的长度定义为多大不好确定。
		 * 所以,我们觉得这两种方式都不够好。
		 * 我们就想有没有这样的一种方案,直接一次读取一行数据。
		 * 我们就想到了字符缓冲输入流的:readLine()方法。
		 * 我们就按照默认的写法去做了这件事情,但是,发现报错了。
		 * 因为BufferedReader需要的是一个字符流,而你现在有的确实一个字节流。
		 * 假如能有一个流对象能够实现字节流转成字符流,我们就可以用了。
		 * 转换流:InputStreamReader
		 */
		//InputStreamReader(InputStream in) 
		InputStreamReader isr = new InputStreamReader(is);
		BufferedReader br = new BufferedReader(isr);

		// 封装目的地
		BufferedWriter bw = new BufferedWriter(new FileWriter("bw.txt"));
		
		String line = null;
		while((line=br.readLine())!=null){
			//只要是键盘录入,就的自己定义结束条件
			if("over".equals(line)){
				break;
			}
			bw.write(line);
			bw.newLine();
			bw.flush();
		}
		
		bw.close();
		br.close();
	}
}

public class SystemOutDemo {
	public static void main(String[] args) throws IOException {
		// 封装数据源
		BufferedReader br = new BufferedReader(new FileReader("bw.txt"));
		// 封装目的地
		OutputStream os = System.out;
		/*
		 * 这个时候,往控制台写数据的时候,我们又的方式一次写一个字节,或者一次写一个字节数组。
		 * 但是,我们获取到的确实一个字符串数据。
		 * 所以,我们就想能不能直接写一个字符串在控制台呢?
		 * A:把字符串转换字节数组输出,但是,不满足我的要求。
		 * B:使用字符缓冲流写出一个字符串。
		 */
		//能实现,但是不满足我的要求
//		String line = null;
//		while((line=br.readLine())!=null){
//			os.write(line.concat("\r\n").getBytes());
//		}
		
		OutputStreamWriter osw = new OutputStreamWriter(os);
		BufferedWriter bw  = new BufferedWriter(osw);
		
		String line = null;
		while((line=br.readLine())!=null){
			bw.write(line);
			bw.newLine();
			bw.flush();
		}
		System.out.println();
		bw.close();
		br.close();
	}
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值