黑马程序员_IO流_3

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

1、字节流是由字节组成的,字节流是由字符组成的

2、输入流就是能连续从其中读取数据的对象,输出流刚刚相反,就是能连续写入数据到其中的对象。

由上面2点可以知道JAVA的IO流中有4大基类,分别为InputStream,OutputStream,Reader,Writer。他们都是抽象类。由这4个类派生出来的子类名称都是以父类名作为类名的后缀,以类的功能来作为类的前缀。

 

Writer子类必须实现的方法有 write(char[], int, int)、flush() 和 close()这3个方法也是最常用的方法。write()方法是将char[]数组中从第二个参数一直写到第三个参数。因为写入的参数会保存在流中,所以要调用flush()方法讲数据刷新到目的中。(一个字节构成不了要的数据)。因为Writer类要调用系统资源,所以要调用close()方法来关闭资源。FileWriter是个操作文件的Writer类。可以用来演示.

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

	FileWriter fw = new FileWriter("FileWriterDemo.txt");

	fw.write("lailongwei");

	fw.flush();

	fw.close();

	Runtime.getRuntime().exec("notepad.exe FileWriterDemo.txt");

}

FileWriter的构造函数中可以传入是否续写的参数。True表示续写。

 

Reader子类必须实现的方法只有 read(char[], int, int) 和 close()。read()方法读取一个字符。返回int类型,读到末尾返回-1。read(char[]),字符数组,用于存储读到的字符。返回读到的字符个数。FileReader是个操作文件的Reader类,和FileWriter对应。可以用来演示.

public static void main(String[] args) throws IOException {
	FileReader fr = new FileReader("FileWriterDemo.txt");
	char[] temp = new char[16];
	int len;
	while ((len = fr.read(temp)) > 0) {
		System.out.print(new String(temp, 0, len));
	}
	fr.close();
}

 

因为write()方法和read()方法每个细小的操作都要去调用系统底层的方法所以效率低。这个时候就出现了缓存区。缓存区的出现是为了提高数据的读写效率,分别为BufferReaderBufferWriter。他们是修饰类。修饰类要被修饰对象作为构造函数的参数。BufferReader中有readLine()特有方法。BufferWriternewLine()这个特有方法。分别修改上面的两端代码如下:

public static void main(String[] args) throws IOException {
	FileWriter fw = new FileWriter("FileWriterDemo.txt");
	//fw.write("lailongwei");
	BufferedWriter bw = new BufferedWriter(fw);
	bw.write("lailongwei");
	bw.newLine();
	bw.flush();
	fw.close();
	bw.close();
	Runtime.getRuntime().exec("notepad.exe FileWriterDemo.txt");
}

 

public static void main(String[] args) throws IOException {
	FileReader fr = new FileReader("FileWriterDemo.txt");
	BufferedReader br = new BufferedReader(fr);
//		char[] temp = new char[16];
	String line;
	while ((line = br.readLine()) != null) {
		System.out.print(line);
	}
	fr.close();
	br.close();

}

 

缓存类的close()就会调用被修饰对象的close()方法。newLine()方法的好处是,不同系统换行的表示方式可能不同。readLine()方法原理:无论是读一行还是读多个字符,其实最终都是在硬盘上一个一个的读取,所以最终都是使用的还是read()方法一次一个的读取。

 

上面的演示都没有对异常进行处理。IO流中的IO异常处理方式:在try外部建立应用,然后在try中赋值,finally里面进行close()。close要用try语句块,因为也会跑出异常。在关闭之前要判断流是否为空,为空就不必关闭,不然会抛出异常。示例如下:

public static void main(String[] args) {
	BufferedReader br = null;
	try {
		br = new BufferedReader(new FileReader("FileWriterDemo.txt"));
		String line;
		while ((line = br.readLine()) != null) {
			System.out.print(line);
		}
	} catch (FileNotFoundException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
//		char[] temp = new char[16];
	catch (IOException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	finally{
		try {
			br.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

 

}

 

 

InputStream字节输入流,需要定义 InputStream 子类的应用程序必须总是提供返回下一个输入字节的方法read()这个方法返回一个int类型。低八位表示读取到的byte类型,返回-1表示已经读到了末尾)。InputStream的available()方法返回可以读取的字节数。FileInputStream是它的操作文件的子类。

OutputStream字节输出流,需要定义 OutputStream 子类的应用程序必须始终提供至少一种可写入一个输出字节的方法write()方法,就是read()方法的反操作FileOutputStream是它的操作文件的子类。OutputStream的flush并不会进行任何操作。因为他就是写入字节。

因为FileInputStream和FileOutputStream的效率都不高,所以要提高效率,BufferFileInputStream和BufferOutputStream来修饰,提高效率。下面通过键盘录入来演示

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class BufferInDemo {

public static void main(String[] args) {
	BufferedInputStream bis = null;
	BufferedOutputStream bos = null;
	try {
		bis = new BufferedInputStream(new FileInputStream("QQ.jpg"));
		bos = new BufferedOutputStream(new FileOutputStream("Q_Q.jpg"));
		byte[] bytes = new byte[1024];
		int len;
		while ((len = bis.read(bytes)) != -1){
			bos.write(bytes, 0, len);
		}
	} catch (FileNotFoundException e1) {
		// TODO Auto-generated catch block
		e1.printStackTrace();
	} catch (IOException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	finally{
		try {
			bis.close();
			bos.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	System.out.println("复制成功");
}

}

 

InputStreamReader是字节流通向字符流的桥梁。而OutputStreamWriter是字符流通向字节流的桥梁。这两个桥梁的构造函数中可以选择需要解码或者编码的编码表。在存储时,如果需要加入指定的编码表。而指定的编码表只有转换流可以指定。所以要在转换流中填入指定的编码。下面通过键盘录入来演示:

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

public class InputStreamReaderDemo {

public static void main(String[] args) {
	BufferedReader br = null;
	BufferedWriter bw = null;
	try {
		br = new BufferedReader(new InputStreamReader(System.in));
		bw = new BufferedWriter(new OutputStreamWriter(System.out));
		String line;
		while (true) {
			line = br.readLine();
			if (line.equals("over")) {
				break;
			}
			else {
				bw.write(line.toUpperCase());
				bw.flush();
			}
		}
	} catch (Exception e) {
		// TODO: handle exception
	}
	finally{
		try {
			br.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try {
			bw.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
}


RandomAccessFile这个类的实例支持对随机访问文件的读取和写入。它不是IO体系中的之类,不过在IO包中。内部封装了一个数组,而且通过指针对数组元素进行操作。可以通过getFilePointer获取指针位置。同时可以通过seek方法来改变指针的位置,其实,完成读写的原理就是内封装了字节输入流和输出流,通过构造函数可以看出该类是否能进行写入(如果模式为只读r,就不会创建文件,如果为rw就会在需要的时候创建)。seek()调整指针的位置。skipBytes()是跳过多少个字节,不能往回跳。通过文件切割来演示:
 

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
public class SplitFiltDemo {

	public static void main(String[] args) {
		File file = new File("D:\\网络图片\\mypicture.jpg");
		for (int i = 0; i < 4; i++) {
			new Thread(new Split(file, i)).start();
		}
		System.out.println("没问题");
	}

}

class Split implements Runnable{
	private File file;
	private int num;
	public Split(File file,int num){
		this.file = file;
		this.num = num;
	}
	@Override
	public void run() {
		RandomAccessFile raf = null;
		RandomAccessFile raFile = null;
		try {
			raf = new RandomAccessFile("切个" + num + ".split", "rw");
			raFile = new RandomAccessFile(file, "r");
			byte[] temp = new byte[1024];
			int len = 0;
			raFile.seek(file.length() / 4 * num);
			while ((len = raFile.read(temp)) != -1 && raFile.getFilePointer() <= (file.length() / 4 * (num + 1))) {
				raf.write(temp, 0, len);
			}
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		finally{
			try {
				raf.close();
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
			try {
				raFile.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
	}
	
}


              ObjectOutputStream是讲对象输出,不过这个对象必须要实现Serializable接口,这个借口中并没有具体的方法,是个标记接口.接口中有个序列号.对象的系列话指的是将堆内存中的对象保存在可以持续保存的地方。可以通过ObjectInputStream方法来重构对象。注意,静态成员不会被系列化,如果想让非静态成员也不参与系列化,这个成员就要用transient来修饰。




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

详情请查看:http://edu.csdn.net/heima

 

                                   


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值