Java中IO流的介紹

之前學習Java_SE時候對於Java中IO這一塊簡略看,之後看Java_Web時候總會用到一些流,所以今天查查資料瀏覽衆多高人博客,整理了一番,希望大家多給意見
package cn.iotest;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.io.RandomAccessFile;
import java.io.Reader;
import java.io.SequenceInputStream;
import java.io.Writer;
import cn.iotest.User;

import org.apache.commons.io.IOUtils;
import org.junit.Test;

public class Demo1 {
	// File類相關操作
	/**
	 * 創建一個新文件,boolean file.createNewFile() 運行結果爲true
	 * 
	 * @throws IOException
	 */
	@Test
	public void test1() throws IOException {
		String filename = "D:/newfile.txt";
		File file = new File(filename);
		System.out.println(file.createNewFile());
	}

	/**
	 * File中的兩個常量File.pathSeparator,File.separator 下例結果爲 ; \
	 */
	@Test
	public void test2() {
		System.out.println(File.pathSeparator);
		System.out.println(File.separator);
	}

	/**
	 * 保持代碼健壯,因爲在Windows下分隔符是\,但是在Linux中就不一定了,所以用靜態常量最安全 下例結果也爲true
	 * 再提一句,有可能有些朋友對'\'和'/'迷糊的,其實'\'和'/'是一個意思,電腦都能讀懂,
	 * 但是單個'\'是轉義字符的意思,所以用'\'時需要打兩個,也就是'\\' "D:/new.txt" 等同於 "D:\\new.txt"
	 * 
	 * @throws IOException
	 */
	@Test
	public void test3() throws IOException {
		String filename = "D:" + File.separator + "new.txt";
		File file = new File(filename);
		System.out.println(file.getName() + "\n" + file.toString() + "\n"
				+ file.getPath());

	}

	/**
	 * 刪除一個文件:file.exists(),file.delete() 先判斷存不存在,存在再刪除 下例結果爲true
	 */
	@Test
	public void test4() {
		String filename = "D:" + File.separator + "newfile.txt";
		File file = new File(filename);
		if (file.exists())
			System.out.println(file.delete());
	}

	/**
	 * 創建一個文件夾file.isDirectory(),file.mkdir() 下例結果爲true
	 */
	@Test
	public void test5() {
		String filename = "D:" + File.separator + "newfile";
		File file = new File(filename);
		if (!file.isDirectory()) {
			System.out.println(file.mkdir());
		}
	}

	/**
	 * 列出指定目錄的所有文件(文件名形式) 結果爲 JTattoo.jar libquaqua.jnilib libquaqua64.jnilib
	 * quaqua.jar
	 */
	@Test
	public void test6() {
		String filename = "D:" + File.separator + "lookandfeel";
		File file = new File(filename);
		if (file.isDirectory()) {
			String[] list = file.list();
			for (String i : list) {
				System.out.println(i);
			}
		}
	}

	/**
	 * 列出指定目錄的所有文件(包括隱藏文件,用路徑形式)file.listFiles() D:\lookandfeel\JTattoo.jar
	 * D:\lookandfeel\libquaqua.jnilib D:\lookandfeel\libquaqua64.jnilib
	 * D:\lookandfeel\quaqua.jar 這裏直接在控制檯輸出對象其實是默認調用了對象的toString方法,而且該方法也已經被 重寫了
	 */
	@Test
	public void test7() {
		String filename = "D:" + File.separator + "lookandfeel";
		File file = new File(filename);
		if (file.isDirectory()) {
			File[] list = file.listFiles();
			for (File i : list) {
				System.out.println(i);
			}
		}
	}

	/**
	 * 使用RandomAccessFile寫入文件 此時打開new.txt,結果是亂碼。用處再議
	 * 
	 * @throws IOException
	 */
	@Test
	public void test8() throws IOException {
		String filename = "D:" + File.separator + "new.txt";
		File file = new File(filename);
		RandomAccessFile raf = new RandomAccessFile(file, "rw");
		raf.write(12);
		raf.writeBoolean(true);
		raf.writeFloat(12.3f);
	}

	// 字節流
	/**
	 * 向文件寫入字符串out.write(bytes) 字符轉字節,再輸出到文件中
	 * 
	 * @throws IOException
	 * 
	 */
	@Test
	public void test9() throws IOException {
		String filename = "D:" + File.separator + "new.txt";
		File file = new File(filename);
		OutputStream out = new FileOutputStream(file);
		String word = "寫入的話";
		byte[] bytes = word.getBytes();
		out.write(bytes);
		out.close();
	}

	/**
	 * 添加新內容 new FileOutputStream(file,true)表示爲追加,而不是重寫
	 */
	@Test
	public void test10() throws IOException {
		String filename = "D:" + File.separator + "new.txt";
		File file = new File(filename);
		OutputStream out = new FileOutputStream(file, true);
		String word = "寫入";
		byte[] bytes = word.getBytes();
		for (int i = 0; i < bytes.length; i++) {
			out.write(bytes[i]);
		}
		out.close();
	}

	/**
	 * 讀取文件內容 IOUtils爲commons-io的一個jar包,其中IOUtils.toByteArray(in)直接返回讀取數據的
	 * byte數組 輸出結果爲“寫入的話寫入”
	 * 
	 * @throws IOException
	 */
	@Test
	public void test11() throws IOException {
		String filename = "D:" + File.separator + "new.txt";
		File file = new File(filename);
		InputStream in = new FileInputStream(file);
		byte[] bytes = IOUtils.toByteArray(in);
		in.close();
		System.out.println(new String(bytes));

	}

	// 字符流
	/**
	 * 字符流和字節流在讀寫上面唯一的區別是一個是讀寫char,一個是讀寫byte
	 * 
	 * 還有一點,字節流不通過緩衝區操作文件,字符流通過緩衝區操作文件 可以試一下二者在寫入信息時都不執行close()操作,結果是字節流有效,字符流無效
	 * 但刷新一下緩衝區一樣有效
	 * 
	 * @throws IOException
	 */
	@Test
	public void test12() throws IOException {
		String fileName = "D:" + File.separator + "new.txt";
		File f = new File(fileName);
		char[] ch = new char[100];
		Reader read = new FileReader(f);
		int count = read.read(ch);
		read.close();
		System.out.println("讀入的長度爲:" + count);
		System.out.println("內容爲" + new String(ch, 0, count));
	}

	// 字符流轉化爲字節流
	// 主要介紹OutputStreamWriter和InputStreamReader
	/**
	 * 字符輸出流轉化爲字節輸出流 可能不好理解,簡單來說就是你存的是字符,但是最後轉化爲了字節存儲
	 * 字節送給writer,然後writer再通過轉換將數據轉爲字節傳給指定outputStream
	 * 
	 * 最後結果爲hello,看清楚,我們輸入的是String也就是char[]
	 * 
	 * @throws IOException
	 */
	@Test
	public void test13() throws IOException {
		Writer writer = new OutputStreamWriter(new FileOutputStream("D:"
				+ File.separator + "test13.txt"));
		writer.write("hello");
		writer.close();
	}

	/**
	 * InputStreamReader無非是用將數據以字節流讀入,最後用char[]接收,不浪費篇幅了
	 */
	/**
	 * 博主最近學習時接觸到outputStreamWriter類,給大家說一下,覺得有啓發的看官就收着 沒啥用就跳過
	 * 將該類用於SAX解析器解析XML文檔進行XML回寫的相關操作
	 * XML回寫用的是XMLWriter類,需求的是一個Writer子類,但是相關類是不提供編碼設置的,
	 * 也就是說必須使用指定默認編碼,這不扯淡麼!這時就要用outputStreamWriter類來設置
	 * 編碼了,就是帶編碼格式的outputStreamWriter構造器
	 */
	// @Test
	// public void test14(Object user){
	// //省去部分代碼,此處沒導dom4j的jar包,沒找到相關類而已
	// XMLWriter writer;
	// try {
	// /**
	// * 將輸入的信息以utf-8的編碼方式轉化爲字節輸出流保存起來,format是一個格式規範器
	// */
	// writer = new XMLWriter(new OutputStreamWriter(
	// new FileOutputStream(path),"UTF-8"), format);
	// writer.write(doc );//doc爲Document文檔對象
	//
	//
	// }
	/**
	 * PrintStream(裝飾流)
	 * 打印流最主要的是區別,打印流可以選擇控制檯也可以選擇文件作爲目的地。 例如:System.out.println就是把目的地選擇爲了控制檯。
	 * 當然如果輸出到文件,如果使用打印流則是將打印流指定到輸出流管道, 實現輸出的還是輸出流。因此,如果目的地是文件,選擇輸出流較好。
	 * 
	 * 結果爲: append13 c
	 * 
	 * @throws IOException
	 */
	@Test
	public void test14() throws IOException {
		PrintStream ps = new PrintStream(new FileOutputStream("D:"
				+ File.separator + "test14.txt"));
		ps.append("append");
		byte[] bytes = "write".getBytes();
		ps.println(13);
		ps.print('c');
	}

	/**
	 * 使用OutputStream向屏幕輸出數據 只需要構造OutputStream output = System.out; 其他操作相同即可
	 * 
	 * @throws IOException
	 */

	/**
	 * BufferedReader,只能接受字符流的緩衝區,將System.in轉換爲字符流(裝飾流)
	 * 
	 * BufferedReader buf = new BufferedReader( new
	 * InputStreamReader(System.in));
	 */
	@Test
	public void test15() throws IOException {
		BufferedReader buf = new BufferedReader(
				new InputStreamReader(System.in));
		System.out.println("請輸入你要輸出的信息");
		String words = buf.readLine();
		System.out.println("您輸出的信息是" + words);
		buf.close();
	}

	/**
	 * 合併流 SequenceInputStream(沒有SequenceOutputStream)
	 * 將兩個字節輸入流按前後順序合併爲一個字節輸入流,其他操作可以對合並流進行(裝飾流)
	 * @throws IOException 
	 */
	@Test
	public void test16() throws IOException{
		InputStream in1 = new FileInputStream("D:"+ File.separator + "test16_1.txt");
		InputStream in2 = new FileInputStream("D:"+ File.separator + "test16_2.txt");
		OutputStream out = new FileOutputStream("D:"+ File.separator + "test16_out.txt");
		SequenceInputStream seq = new SequenceInputStream(in1, in2);
		byte[] temp = null;
		int count;
		//讀,IOUtils.toByteArray()是封裝好的將輸入流的數據轉化爲byte數組
		temp = IOUtils.toByteArray(seq);
		//寫
		out.write(temp);
	}
	/**
	 * 最後說一下序列化與反序列化,一個類想要能被序列化,首先要實現Serializable接口
	 * 這個接口裏面沒有任何方法,只要聲明,就說明這個類能夠被序列化,具體什麼是序列化
	 * 先來看看ObjectInputStream和ObjectOutputStream兩個類(裝飾流)
	 * ObjectOutputStream用來將對象轉化爲二進制數據進行存儲
	 * ObjectInputStream用來將數據進行轉化爲對象
	 * 
	 * 下例輸出結果爲
	 * User [username=張三, age=21]
	 * 
	 * 
	 * @throws IOException 
	 * @throws FileNotFoundException 
	 * @throws ClassNotFoundException 
	 */
	@Test
	public void test17() throws FileNotFoundException, IOException, ClassNotFoundException{
		File file = new File("D:"+ File.separator + "test17.txt");
		ObjectOutputStream objout = new ObjectOutputStream(new FileOutputStream(file));
		objout.writeObject(new User("張三",21));//這時寫進的是二進制數據
		ObjectInputStream objin = new ObjectInputStream(new FileInputStream(file));
		Object user = objin.readObject();//寫到這裏時記得導入相應對象的包,由於返回Object類型,他是不會提醒你的
		//至於這一塊JVM是怎麼認出讀出的數據是User對象的,可能序列化時候有唯一標識吧,這裏我也不清楚它怎麼實現的
		System.out.println(user.toString());
	}
	/**
	 * 再來簡略談談Externalizable接口,Serializable接口默認實現全部屬性序列化
	 * 注意!序列化時只有屬性被序列化
	 * 而繼承Externalizable接口則可以由我們自己定實現哪些屬性被序列化
	 * 並且這個類中必須要有一個無參的構造函數,如果沒有的話,在構造的時候會產生異常,
	 * 這是因爲在反序列話的時候會默認調用無參的構造函數。
	 * 
	 * 該接口有兩個方法需要實現,一個就是序列化,一個就是反序列化
	 * 
	 */
	/**
	 * 對於Externalizable接口,實現太過麻煩,對於不想被序列化的屬性
	 * 我們只需要加上關鍵字transient即可
	 * transient關鍵字的意義簡單說就是被修飾的成員不會被本地化
	 * 例如賬號的密碼可以用這個修飾
	 */
	/**
	 * IO流簡單說道這裏,有一些較偏的我也沒有整理(博主也起步學習不久)。越努力,越幸運
<span style="white-space:pre">	</span>	 
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章