Java IO 总结

1. Java的IO运用了 装饰者模式,提供了一个称做链接(Chaining)的机制,可以将一个流处理器跟另一个流处理器首尾相接,以其中之一的输出为输入,形成一个流管道的链接,如:
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("lecturer.dat"));


2. Java的IO具有对称性:
a. 输入 - 输出对称:
    字节流的两个 抽象基类InputStreamOutputStream
// 输入流实现Closeable接口(close()方法)
public abstract class InputStream implements Closeable {
}

// 输出流实现Closable接口和Flushable接口(flush()方法)
public abstract class OutputStream implements Closeable, Flushable {
}


    字符流的两个 抽象基类ReaderWriter

// Reader实现Readable(read()方法)和Closeable接口
public abstract class Reader implements Readable, Closeable {
}

// Writer实现Appendable接口(append系列方法)、Closable接口和Flushable接口
public abstract class Writer implements Appendable, Closeable, Flushable {
}


b. 字节流 - 字符流对称:
    输入流: InputStreamReader分别负责字节流和字符流的输入,
    输出流: OutputStreamWriter分别负责字节流和字符流的输出。

3. 使用完资源后,必须要手动调用 close()方法关闭,否则会导致缓冲区的部分没有写入到流而产生错误。最好是放在 finally块中,保证执行。
如果要把异常抛给调用者,省略catch从句;如果在catch中重新抛出异常会损失性能:

    public InputStream decrypt(File fileIn) throws Exception {
		FileInputStream fis = null;
		
		try {
			fis = new FileInputStream(fileIn);
		} finally {
			if (fis != null)
				fis.close();
		}
	}

   已经关闭的资源 再次调用close()不会抛异常,也不会产生任何动作。

4. 输入流和输出流之间的转换一般通过 字节数组来中转:
	FileInputStream fis = null;
	FileOutputStream fos = null;
	
	try {
		fis = new FileInputStream(new File("eligible.txt"));
		fos = new FileOutputStream(new File("eligibility.txt"));
		byte[] buffer = new byte[8192];
		int count = 0;
		while ((count = fis.read(buffer)) > 0) {
			fos.write(buffer, 0, count);
		}
	} catch (IOException e) {
		e.printStackTrace();
	} finally {
		if (fos != null)
			fos.close();
		if (fis != null)
			fis.close();
	}


5. 字节流和字符流之间的转换: InputStreamReader, OutputStreamWriter
	FileInputStream fis = null;
	InputStreamReader isr = null;
	FileOutputStream fos = null;
	OutputStreamWriter osw = null;
	
	try {
		fis = new FileInputStream(new File("eligible.txt"));
		fos = new FileOutputStream(new File("eligibility.txt"));
		// Char reader wraps the byte input stream. It's preferable to specify the char set.
		// Otherwise messy code may occur.
		// Available char set: ASCII, UNICODE, GB2312, GBK, UTF-8, UTF-16, UTF-32
		isr = new InputStreamReader(fis, "UTF-8");
		// Char writer wraps the byte output stream. It's preferable to specify the char set.
		// Otherwise messy code may occur.
		osw = new OutputStreamWriter(fos, "UTF-8");
		char[] buffer = new char[1024];
		int count = 0;
		while ((count = isr.read(buffer)) > 0) {
			osw.write(buffer, 0, count);
		}
	} catch (IOException e) {
		e.printStackTrace();
	} finally {
		if (isr != null)
			isr.close();
		if (osw != null)
			osw.close();
	}


6. 底层的流一定是字节流,字符流不过是在其基础上按照编码进行了处理。

7. 使用缓冲类 BufferedInputStream, BufferedOutputStream, BufferedReaderBufferedWriter来提升性能:
		BufferedInputStream bis = new BufferedInputStream(new FileInputStream("neglect.dat"));
		BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("negligible.dat"));
		BufferedReader br = new BufferedReader(new FileReader("elect.dat"));
		BufferedWriter bw = new BufferedWriter(new FileWriter("election.dat"));


8. 扩展 FilterInputStream, FilterOutputStream, FilterReaderFilterWriter来实现自定义的输入输出流处理类。

9. 如果文件路径包含特殊字符(如空格)经过编码后(%20)传给FileInputStream,会抛出java.io.FileNotFoundException:
		// String path = SpecialCaseInPath.class.getProtectionDomain().getCodeSource().getLocation().getPath() + "/..\\screw chew.xml"; // This long expression would bring the encoded path
		String path = "C:\\programs%20data\\screw chew.xml";
		FileInputStream fis = new FileInputStream(path);

解决办法:
		// Solution 1:
		// path = path.replaceAll("%20", " ");
		// Solution 2:
		path = URLDecoder.decode(path, "utf-8");
		FileInputStream fis = new FileInputStream(path);

你可能感兴趣的:(java,IO)