黑马程序员_文件IO流部分疑点和JDK1.7版本后新try-catch处理学习笔记

时间:2023-02-19 15:54:49

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

前言

IO流,应该算是JAVA程序,与外部沟通的桥梁吧。

这边整理一下自己在IO流学习中,经常容易忘掉的知识点。

说明:

1)本文中的代码,为了体现主干流程思想,暂时上抛所有异常。

2)JDK1.7版本以后,可以参考新try-catch的处理方法,处理IO流的关闭。


1、在文件后添加内容
实现方法:在新建文件流的时候,第二个参数置为true。eg:
private static void appendFile() throws IOException {
		//打开文件流
		FileWriter fw1 = new FileWriter("D:\\1.txt");
		//写入文件
		fw1.write("HelloWorld1");
		//关闭文件流
		fw1.close();
		
		//再次打开文件流
		FileWriter fw2 = new FileWriter("D:\\1.txt",true);
		//写入文件
		fw2.write("HelloWorld2");
		//关闭文件流
		fw2.close();
	}

2、LineNumberReader类
通过LineNumberReader类读取行数、指定读取的起始行数,eg:
private static void lineNumber() throws FileNotFoundException, IOException {
		LineNumberReader lnr = new LineNumberReader(new FileReader("D:\\ClassLoaderTest.java"));
		//指定读取的起始行数
		lnr.setLineNumber(2);
		String line = null;
		while(null!=(line=lnr.readLine()))
			//获取行数,并打印行内容
			System.out.println(lnr.getLineNumber() + ":" + line);
		lnr.close();
	}

3、打印流PrintWriter和PrintStream(Writer/OutputStream)
该流提供了打印方法,可以将各中数据类型的数据都原样打印。eg:
private static void PrintWriterTest() {
		//新建打印流
		PrintWriter pr = new PrintWriter(System.out);
		//打印数据
		pr.println("hello");
		//打印基本数据
		pr.println(1.111);
		
		List<Integer> list = new ArrayList<Integer>();
		list.add(1);
		list.add(2);
		list.add(3);
		//打印对象
		pr.println(list);
		//关闭打印流
		pr.close();
	}

4、合并流
用于合并读取多个输入流,eg:
private static void sequenceInputStreamTest() throws FileNotFoundException,
			IOException {
		//用一个Vector存储多个输入流
		Vector<FileInputStream> vector = new Vector<FileInputStream>();
		vector.add(new FileInputStream("D:\\1.txt"));
		vector.add(new FileInputStream("D:\\2.txt"));
		vector.add(new FileInputStream("D:\\3.txt"));

		//定义一个序列流
		SequenceInputStream sis = new SequenceInputStream(vector.elements());
		
		//定义一个输出流
		FileOutputStream fos = new FileOutputStream("D:\\4.txt");
		
		//依此读取 三个输入流 到 一个输出流 中
		int len=0;
		byte[] buf = new byte[1024];
		while((len=sis.read(buf))>0) {
			fos.write(buf, 0, len);
		}
		
		//关闭输出流
		fos.close();
		
		//关闭输入流
		sis.close();
	}

5、对象序列化ObjectInputStream和ObjectOutputStream
被操作的对象,需要实现Serializable接口(标记接口),eg:
1)可序列化的类:
import java.io.Serializable;
public class Person implements Serializable{
	private String name;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}
2)序列化对象:
private static void objectOutputStreamTest() throws IOException,
			FileNotFoundException {
		//定义对象输出流
		ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("D:\\object.txt"));
		//定义待序列化的对象
		Person person = new Person();
		person.setName("cby");
		//序列化对象到文件中
		oos.writeObject(person);
		//关闭输出流
		oos.close();
	}
3)反序列化对象
private static void objectInputStreamTest() throws IOException,
			FileNotFoundException, ClassNotFoundException {
		//定义对象输入流
		ObjectInputStream oos = new ObjectInputStream(new FileInputStream("D:\\object.txt"));
		//从文件中反序列化对象
		Person person = (Person)oos.readObject();
		//获取对象中的属性值
		System.out.println(person.getName());
		//关闭输入流
		oos.close();
	}
4)序列化的文件
黑马程序员_文件IO流部分疑点和JDK1.7版本后新try-catch处理学习笔记

注意:
1)、静态属性是不能被序列化的
2)、如果有非静态成员不详序列化,应该用transient修饰。

6、管道流PipedInputStream和PipedOutputStream
输入输出可以直接进行连接。
应该用于多线程,单线程易导致死锁。
在写之前,读是阻塞式方法。
开发的时候,参考API文档就可以了。

7、RandomAccessFile
随机访问文件(灰常强大),有些书上说,这个类可以用作断点续传。
主要是因为,这个类读取文件时,是可以指定开始读取位置的。
开发的时候,参考API文档就可以了。

8、数据流:DataOutputStream和DataInputStream
专门用于操作数据的流。
开发的时候,参考API文档就可以了。

9、数组操作对象:ByteArrayInputStream和ByteArrayOutputStream
没有访问资源,不需要关闭。
即使关闭以后,对象依然可以正常访问。
开发的时候,参考API文档就可以了。

10、转换流操作编码表
	//定义文本转换输出流(向文件输出UTF-8编码的中文字符)
	OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("D:\\utf.txt"),"UTF-8");
	//写入信息
	osw.write("你好");
	//关闭流
	osw.close();

11、JDK1.7之后,新try-catch对IO流的关闭
当你同时访问多个文件资源时,多个IO流的释放往往是一件让人头疼的事。
我们可以看一下以下的代码:
public static void main(String[] args) {
        FileReader fr = null;
        FileWriter fw = null;
        try {
                fr  = new FileReader("D:\\ClassLoaderTest.java");
                fw = new FileWriter("D:\\ClassLoaderTest1.java");
                char[] cbuf = new char[1024];
                int len = 0;
                while((len=fr.read(cbuf)) > 0)
                        fw.write(cbuf, 0, len);
        } 
        catch (IOException e) {
                e.printStackTrace();
        }
        finally {
                try {
                        if(null!=fr) {
                                fr.close();
                        } 
                } catch (IOException e) {
                        e.printStackTrace();
                } finally {
                        try {
                                if(null!=fw) {
                                        fw.close();
                                } 
                        } catch (IOException e) {
                                e.printStackTrace();
                        }
                }
        }
}
代码的功能很简单,其实就是将一个文本文件拷贝到另外一个文本文件中。
但为了较为安全的释放IO流访问的资源。
我们花费了将近一半的篇幅,来写释放资源的代码。
看括号的层次,就挺让人觉得烦躁的。


所以,在JDK1.7中,我们可以用如下方法来实现:
public static void main(String[] args) {
                try 
                (
                        FileReader fr = new FileReader("D:\\ClassLoaderTest.java");
                        FileWriter fw = new FileWriter("D:\\ClassLoaderTest1.java");
                )
                {
                        char[] cbuf = new char[1024];
                        int len = 0;
                        while((len=fr.read(cbuf)) > 0)
                                fw.write(cbuf, 0, len);
                } 
                catch (IOException e) 
                {
                        e.printStackTrace();
                }
        }
显然,以上这段代码,相对于第一段代码而言,清晰很多。
两段代码的区别在于:
1、将资源的创建放到了try后面的小括号中。
2、省去了资源释放的代码。

在try中的代码运行结束后,不需要手动的close()资源。
JAVA会自动去释放这些资源。

这应该算是JDK1.7之后一个较好的改进吧。




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