黑马程序员——Java之IO流(2)

------Java培训、Android培训、iOS培训、Net培训、期待与您交流! -------

一、IO流简介

       Java的IO流是实现输入/输出的基础,它可以方便地实现数据的输入/输出操作,在Java中把不同的输入/输出源(键盘、文件、网络连接等)抽象称为“流”(Stream),通过流的方式允许Java程序使用相同的方式来访问不同的输入/输出源。

       Java  把所有的流类型(类和抽象类)都放在Java.io包中,用以实现输入/输出功能。

 

二、字节流和字符流

       字节流可以处理所有类型的数据,操作的数据单元是8位的字节,如MP3、图片、文字、视频等。在读取时,读到一个字节就返回一个字节。在Java中对应的类都以“Stream”或“Reader”结尾。

       字符流仅能够处理纯文本数据,操作的数据单元是16位的字符,如txt文本等。在读取时,读到一个或者多个字节,先查找指定的编码表,然后将查到的字符返回。在Java中对应的类都以“Reader” 或“Writer”结尾。

      Java的IO流的40多个类都是从以下4个抽象基类派生的:

      InputStream/Reader:所有输入流的基类,前者是字节输入流,后者是字符输入流;

      OutputStream/Writer:所有输出流的基类,前者是字节输出流,后者是字符输出流;

(1)InputStream/Reader

         InputStream和Reader是所有输入流的抽象基类,本身不能创建实例来执行输入,但它们将作为所有输入流的模板,所以它们的方法是所有输入流都可以使用的方法。InputStream和Reader分别有一个用于读取文件的输入流:FileInputStream和FileReader,它们都是节点流——会直接与指定文件关联。

        在InputStream里包含以下三个方法:

       ①int  read():从输入流中读取单个字节,返回所读取的字节数据(字节数据可直接转换为int类型);

       ②int  read(byte[]b):从输入流中最多读取b.length个字节的数据,并将其存储在字节数组b中,返回实际读取的字节数;

       ③int  read(byte[]b ,int  off, int  len):从输入流中最多读取len个字节的数据,并将其存储在数组b中,放入数组b中时,并不是从数组的起点开始,而是从off位置开始,返回实际读取的字节数。

示例:

import java.io.FileInputStream;
import java.io.IOException;
public class FileInputStreamTest {

	public static void main(String[] args) throws IOException {
		    //创建字节输入流
			FileInputStream fis = new FileInputStream("FileInputStreamTest.java");
		{  
			//创建 一个长度为1024的数组
		    byte[] bbuf = new byte[1024];
			int hasRead ;
			//循环从输入流中取出数据
			while ((hasRead = fis.read(bbuf)) >0 ) {
				//取出数组中的字节,将字节数组转换成字符串输入
				System.out.println(new String(bbuf , 0 , hasRead));
		}		 
     }
  }
}

运行结果:

将输出上面程序源代码。 

      

       在Reader里包含了以下三个方法:

       ①int  read():从输入流中读取单个字符,返回所读取的字符数据(字符数据可直接转换为int类型);

       ②int  read(char[]cbuf):从输入流中最多读取cbuf.length个字符的数据,并将其存储在字符数组cbuf中,返回实际读取的字符数;

       ③int  read(char[]cbuf ,int  off, int  len):从输入流中最多读取len个字符的数据,并将其存储在字符数组cbuf中,放入数组cbuf中时,并不是从数组的起点开始,而是从off位置开始,返回实际读取的字符数。

示例:

import java.io.FileReader;
import java.io.IOException;
public class FileReaderText {

	public static void main(String[] args) throws IOException {
		//创建FileReader对象
		FileReader fw = new FileReader("F:/eclipse/File/FileWriter.txt");
		//读取字符并输出
		while (fw.read() != -1){
			System.out.print((char)fw.read());
	}
		fw.close();
	}
}

运行结果:

One dream.

       上面程序最后使用了fw.close()来关闭该文件输入流,程序里打开的文件IO资源不属于内存里的资源,垃圾回收机制无法回收该资源,使用应该关闭文件IO资源。

 

(2)OutputStream/Writer

        OutputStream和Writer也非常相似,两个流都提供了

       ①void  write(int c):将指定的字节/字符输出到输出流中,其中c既可以代表字节,也可以代表字符;

       ②void  write(byte[]/char[] buf):将字节数组/字符数组中的数据输出到指定输出流中;

       ③void  write(byte[]/char[]buf ,int  off, int  len):将字节数组/字符数组中从off位置开始,长度为len的字节/字符输出到输出流中。

示例:下面程序使用FileInputStream来执行输入,并使用FileOutputStream来执行输出,用以实现复制FileOutputStreamTest.java文件的功能。

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
public class FileOutStreamTest {

	public static void main(String[] args) {
		try {
			//创建字节输入流
			FileInputStream fis = new FileInputStream("FileOutStreamTest.java");
		    //创建字节输出流
			FileOutputStream fos = new FileOutputStream("newFile.txt");
		    byte[] cbuf = new byte[1024];
			int hasRead =0;
			//循环从输入流中取出数据
			
				while ((hasRead = fis.read(cbuf)) >0 ) 
				{
					//取出数组中的字节,将字节数组转换成字符串输入
					fos.write(cbuf , 0 , hasRead);
				}
		}   catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}

运行结果:

在看到系统当前路径下多了一个文件:newFile.txt,该文件的内容和FileOutputStreamTest.java文件的内容完全相同。

 

        如果希望看到直接输出字符串内容,则使用Writer会有更好的效果,如下程序:

import java.io.FileWriter;
import java.io.IOException;
public class FileWriteText {

	public static void main(String[] args) throws IOException {
		//创建FileReader对象
		FileWriter fw = new FileWriter("poem.txt");
		//写入字符串
		fw.write("One \r\n");
		fw.write("dream \r\n");
		fw.write(". \r\n");
	
	}
}

运行结果:

将会在当前目录下输出一个poem.txt文件,文件内容就是程序中输出的内容。

 

三、带缓存的输入/输出流

       缓存可以说是I/O流的一种性能优化。缓存流为I/O流增加了内存缓存区。

(1)BufferedInputStream类与BufferedOutputStream类

         BufferedInputStream类可以对任意的InputStream类进行带缓冲区的包装以达到性能的优化。

         BufferedInputStream类有两个构造函数:

         ①BufferedInputStream(InputStream in):构造函数创建了一个带有32个字节的缓存流;

         ②BufferedInputStream(InputStream in , int size):构造函数按指定的大小创建缓存区。

         从构造函数可以看出,BufferedInputStream对象位于InputStream类对象之前,下图描述字节数据读取文件的过程:

 示例:

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
public class MyBufferedInputStream {

	public static void main(String[] args) throws IOException {
		File f = new File("F:/eclipse/File/FileWriter.txt");
		//创建FileInputStream对象
		FileInputStream in = new FileInputStream(f);
		//创建BufferedInputStream对象
		BufferedInputStream bis = new BufferedInputStream(in);
		byte[] bytes = new byte[10];
		//将字节流数据读取到byte数组中,再将其转换我字符串形式
         do{
            bis.read(bytes);
			System.out.print(new String(bytes));
		}while (bis.read() != -1) ;
		//关闭BufferedInputStream
		bis.close();
	}
}


运行结果:

One dream.

        使用BufferedOutputStream输出信息和向OutputStream输入信息完全一样,不过BufferedOutputStream有一个flush()方法用来讲缓冲区的数据强制输出完。

        BufferedOutputStream类也有两个构造方法:

        ①BufferedOutputStream(OutputStream in):构造函数创建了一个带有32个字节的缓存区;

        ②BufferedOutputStream(outputStream in , int size):构造函数按指定的大小创建缓存区。

示例:

import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;


public class MyBufferedOutputStream {

	public static void main(String[] args) throws IOException {
		//创建FileOutStream对象,并指定目录路径
		FileOutputStream out = new FileOutputStream("F:/eclipse/File/FileWriter.txt");
		//创建BufferedOutputStream对象
		BufferedOutputStream bos = new BufferedOutputStream(out);
		//定义s类型的字符串
		String s = "I have one dream.";
		//将字符串传递到bos对象李
		bos.write(s.getBytes());
		//刷新缓存
		bos.flush();
		//关闭BufferedOutputStream
		bos.close();
	}
}

运行结果:

将在FileWriter.txt文件显示程序中的内容。

(2)BufferedReader类与BufferedWriter类

         BufferedReader类与BuffferedWriter类分别继承Reader类与Writer类。这两个类同样具有内部缓存机制,并可以行为单位进行输入/输出。

         根据BufferedReader类的特点,总结出下图所示的字符数据读取文件的过程:

       BufferedReader类常用的方法如下:

      ①read()方法:读取单个字符;

      ②readLine()方法:读取一个文本行,并将其返回为字符串;若无数据可读,则返回null;

      ③write(String  s , int off ,int len)方法:写入字符串的某一部分;

      ④flush()方法:刷新该流的缓存;

      ⑤newLine()方法:写入一个行分隔符。

      在使用BufferedWriter类的Write()方法时,数据并没有立刻被写入至输出流中,而是首先进入缓冲区中。如果想立刻将缓冲区中的数据写入输出流中,要调用flush()方法。

示例:向指定的磁盘文件中写入数据,并通过BufferedReader类将文件中的信息分行显示。

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
public class MyBuffer {

	public static void main(String[] args) {
		//定义字符串数组
		String  str[] = {"I","have","a","dream","."};
		//创建文件对象
		File file = new File("D://work.txt");
		try {
			//创建FileWriter类对象
			FileWriter fw = new FileWriter(file);
			//创建BufferedWriter类对象
			BufferedWriter bufw = new BufferedWriter(fw);
			//遍历循环数组
			for (int i = 0; i < str.length; i++) {
				//将字符串数组中元素写入到磁盘文件中
				bufw.write(str[i]);
				//将数组中的单个元素以单行的形式写入文件
				bufw.newLine();
			}
			//将BufferedWriter关闭
			bufw.close();
			//将FileWriter关闭
			fw.close();
		} catch (IOException e) {
			
			e.printStackTrace();
		}
       try {
    	//创建FileReader类对象
		FileReader fr = new FileReader(file);
		//创建BufferedReader类对象
		BufferedReader bufr = new BufferedReader(fr);
		//创建字符串对象
		String s= null;
		//声明int型变量
		int i = 0;
		//如果文件的文本行数不为null,则进入循环
		while ((s=bufr.readLine()) != null) {
			//将变量做自增运算
			i++;
			//输出文件数据
			System.out.println("第"+i+"行:"+s);
		}
		//将BufferedReader关闭
		bufr.close();
		//将FileReader关闭
		fr.close();
	} catch (FileNotFoundException e) {
		
		e.printStackTrace();
	} catch (IOException e) {
		e.printStackTrace();
	}
       
	}
}

运行结果:

第1行:I
第2行:have
第3行:a
第4行:dream
第5行:.

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值