1. 程式人生 > >IO流(四)

IO流(四)

read and 內存操作流 取數據 obj 返回值 object類 system類 args

登錄註冊IO版本案例(掌握)

	
	要求,對著寫一遍。
	
	cn.itcast.pojo User
	cn.itcast.dao UserDao
	cn.itcast.dao.impl UserDaoImpl(實現我不管)
	cn.itcast.game GuessNumber
	cn.itcast.test	UserTest

數據操作流(操作基本類型數據的流)(理解)

	
	1、可以操作基本類型的數據
	2、流對象名稱	
		DataInputStream
			A:創建數據輸出流對象
				DataOutputStream dos = new DataOutputStream(new FileOutputStream(
				"dos.txt"));
			B:寫數據
				dos.writeByte(10);
				dos.writeShort(100);
				dos.writeInt(1000);
				dos.writeLong(10000);
				dos.writeFloat(12.34F);
				dos.writeDouble(12.56);
				dos.writeChar(‘a‘);
				dos.writeBoolean(true);
			C:釋放資源
				dos.close();
		DataOutputStream
			A:創建數據輸入流對象
				DataInputStream dis = new DataInputStream(
				new FileInputStream("dos.txt"));
			B:讀數據
				byte b = dis.readByte();
				short s = dis.readShort();
				int i = dis.readInt();
				long l = dis.readLong();
				float f = dis.readFloat();
				double d = dis.readDouble();
				char c = dis.readChar();
				boolean bb = dis.readBoolean();
			C:釋放資源
				dis.close();

內存操作流(理解)

	
	1、有些時候我們操作完畢後,未必需要產生一個文件,就可以使用內存操作流。
	2、三種
		A:操作字節數組
			ByteArrayInputStream
					//將寫入的流轉化為字符數組
					byte[] bys = baos.toByteArray();
					//創建對象
					ByteArrayInputStream bais = new ByteArrayInputStream(bys);
					//讀數據
					int by = 0;
					while ((by = bais.read()) != -1) {
						System.out.print((char) by);
					}
			ByteArrayOutputStream
					// 創建對象
					ByteArrayOutputStream baos = new ByteArrayOutputStream();
					// 寫數據
					for (int x = 0; x < 10; x++) {
						baos.write(("hello" + x).getBytes());
					}
					// 釋放資源
					// 通過查看源碼我們知道這裏什麽都沒做,所以根本需要close()
					// baos.close();
		B:操作字符數組
			CharArrayReader
			CharArrayWriter
		C:操作字符串
			StringReader
			StringWriter

打印流(掌握)

	
	1、字節打印流 PrintStream,字符打印流 PrintWriter
	2、特點:
		A:只操作目的地,不操作數據源(只能寫不能讀)
		B:可以操作任意類型的數據
		C:如果啟用了自動刷新,在調用println()方法的時候,能夠換行並刷新
		D:可以直接操作文件
			問題:哪些流可以直接操作文件呢?
						FileInputStream
						FileOutputStream
						FileReader
						FileWriter
						PrintStream
						PrintWriter
			流分為基本流(能直接讀寫文件)和高級流(在基本流基礎上提供一些其它功能)
			看API,如果其構造方法能夠同時接收File和String類型的參數,一般都是可以直接操作文件的
	3、復制文本文件
		BufferedReader br = new BufferedReader(new FileReader("a.txt"));
		PrintWriter pw = new PrintWriter(new FileWriter("b.txt"),true);	//第二參數啟動刷新
		
		String line = null;
		while((line=br.readLine())!=null) {
			pw.println(line);	//println自動刷新功能
		}
		
		pw.close();
		br.close();

標準輸入輸出流(理解)

	
	1、System類下面有這樣的兩個字段
		in 標準輸入流
		out 標準輸出流
	2、三種鍵盤錄入方式
		A:main方法的args接收參數
		B:System.in通過BufferedReader進行包裝
			BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		C:Scanner
			Scanner sc = new Scanner(System.in);
	3、輸出語句的原理和如何使用字符流輸出數據
		A:原理
			System.out.println("helloworld");
			
			PrintStream ps = System.out;
			ps.println("helloworld");
		B:把System.out用字符緩沖流包裝一下使用
			BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

隨機訪問流(理解)

	
	RandomAccessFile類不屬於流,是Object類的子類。
	但它融合了InputStream和OutputStream的功能。
	支持對文件的隨機訪問讀取和寫入。
	1、可以按照文件指針的位置寫數據和讀數據。
	2、案例:
		
		A:創建隨機訪問流對象
				RandomAccessFile raf = new RandomAccessFile("raf.txt", "rw");	//第一個參數是文件路徑,第二個參數是操作文件的模式。
				//模式有四種,我們最常用的一種叫"rw",這種方式表示我既可以寫數據,也可以讀取數據 
		B:寫數據
				raf.writeChar(‘a‘);
		C:讀數據
				char ch = raf.readChar();
		D:獲取和改變文件指針的位置
				raf.getFilePointer();
		E:設置指針位置
				raf.seek(4);

合並流(理解)

	
	1、把多個輸入流的數據寫到一個輸出流中。
	2、構造方法:
		A:SequenceInputStream(InputStream s1, InputStream s2) 
		B:SequenceInputStream(Enumeration<? extends InputStream> e) 
	3、例子:
		public class SequenceInputStreamDemo2 {
			public static void main(String[] args) throws IOException {
				// 需求:把下面的三個文件的內容復制到Copy.java中
				// ByteArrayStreamDemo.java,CopyFileDemo.java,DataStreamDemo.java

				// SequenceInputStream(Enumeration e)
				// 通過簡單的回顧我們知道了Enumeration是Vector中的一個方法的返回值類型。
				// Enumeration elements()
				Vector v = new Vector();
				InputStream s1 = new FileInputStream("ByteArrayStreamDemo.java");
				InputStream s2 = new FileInputStream("CopyFileDemo.java");
				InputStream s3 = new FileInputStream("DataStreamDemo.java");
				v.add(s1);
				v.add(s2);
				v.add(s3);
				Enumeration en = v.elements();
				SequenceInputStream sis = new SequenceInputStream(en);
				BufferedOutputStream bos = new BufferedOutputStream(
						new FileOutputStream("Copy.java"));

				// 如何寫讀寫呢,其實很簡單,你就按照以前怎麽讀寫,現在還是怎麽讀寫
				byte[] bys = new byte[1024];
				int len = 0;
				while ((len = sis.read(bys)) != -1) {
					bos.write(bys, 0, len);
				}

				bos.close();
				sis.close();
			}
		}

序列化流(理解)

	
	1、可以把對象寫入文本文件或者在網絡中傳輸。對象 -- 流數據(ObjectOutputStream)
	2、如何實現序列化呢(NotSerializableException:未序列化異常)?
		implements Serializable	讓被序列化的對象所屬類實現序列化接口。
		該接口是一個標記接口。沒有功能需要實現。
	3、註意問題(InvalidClassException):
		把數據寫到文件後,在去修改類,不寫再讀,會產生一個問題。
		如何解決該問題呢?
			實際開發中,需要修改類但還需要使用以前寫過的數據,不能重新寫入。怎麽辦呢?
			在類文件中,給出一個固定的序列化id值。
			點擊黃色警告線 Add generated serial version ID, 這樣也可以解決黃色警告線問題
		我一個類中可能有很多的成員變量,有些我不想進行序列化。請問該怎麽辦呢?
			使用transient關鍵字聲明不需要序列化的成員變量(private transient int age;)
	4、面試題:
		什麽時候序列化?
		如何實現序列化?
		什麽是反序列化?
			反序列化流:把文本文件中的流對象數據或者網絡中的流對象數據還原成對象。流數據 -- 對象(ObjectInputStream)

Properties(理解)

	
        1、 屬性集合類。是一個可以和IO流相結合使用的集合類。
		可保存在流中或從流中加載。屬性列表中每個鍵及其對應值都是一個字符串。
		是Hashtable的子類,說明是一個Map集合。
			Properties prop = new Properties();

			// 添加元素
			prop.put("it002", "hello");
			prop.put("it001", "world");
			prop.put("it003", "java");

			// System.out.println("prop:" + prop);

			// 遍歷集合
	2、特有功能
		A:public Object setProperty(String key,String value);	//添加元素
		B:public String getProperty(String key);	//獲取元素
		C:public Set stringPropertyNames();	//獲取所有鍵的集合
		D:例子
			public class PropertiesDemo2 {
			public static void main(String[] args) {
				// 創建集合對象
				Properties prop = new Properties();

				// 添加元素
				prop.setProperty("張三", "30");
				prop.setProperty("李四", "40");
				prop.setProperty("王五", "50");

				// public Set stringPropertyNames():獲取所有的鍵的集合
				Set set = prop.stringPropertyNames();
				for (String key : set) {
					String value = prop.getProperty(key);
					System.out.println(key + "---" + value);
				}
			}
			}
	3、和IO流結合的方法
		把鍵值對形式的文本文件內容加載到集合中
		public void load(Reader reader)
		public void load(InputStream inStream)

		把集合中的數據存儲到文本文件中
		public void store(Writer writer,String comments)
		public void store(OutputStream out,String comments)
		註意:這裏的集合指的是properties集合
		例子:
			public class PropertiesDemo3 {
			public static void main(String[] args) throws IOException {
				// myLoad();

				myStore();
			}

			private static void myStore() throws IOException {
				// 創建集合對象
				Properties prop = new Properties();

				prop.setProperty("林青霞", "27");
				prop.setProperty("武鑫", "30");
				prop.setProperty("劉曉曲", "18");
				
				//public void store(Writer writer,String comments):把集合中的數據存儲到文件
				Writer w = new FileWriter("name.txt");
				prop.store(w, "helloworld");
				w.close();
			}

			private static void myLoad() throws IOException {
				Properties prop = new Properties();

				// public void load(Reader reader):把文件中的數據讀取到集合中
				// 註意:這個文件的數據必須是鍵值對形式
				Reader r = new FileReader("prop.txt");
				prop.load(r);
				r.close();

				System.out.println("prop:" + prop);
			}
			}
	4、案例:
		A:根據給定的文件判斷是否有鍵為"lisi"的,如果有就修改其值為100
		B:寫一個程序實現控制猜數字小遊戲程序不能玩超過5次

NIO(了解)

	
	1、JDK4出現的NIO,對以前的IO操作進行了優化,提高了效率。但是大部分我們看到的還是以前的IO。
	2、JDK7的NIO的使用	
		Path:路徑
		Paths:通過靜態方法返回一個路徑
			public static Path get(URI uri)
		Files:提供了常見的功能
			復制文件:
				public static long copy(Path source,OutputStream out)
			把集合中的數據寫到文本文件:
				public static Path write(Path path,Iterable<? extends CharSequence> lines,Charset cs,OpenOption... options)
	3、例子:
		public class NIODemo {
			public static void main(String[] args) throws IOException {
				// public static long copy(Path source,OutputStream out)
				// Files.copy(Paths.get("ByteArrayStreamDemo.java"), new
				// FileOutputStream(
				// "Copy.java"));

				ArrayList array = new ArrayList();
				array.add("hello");
				array.add("world");
				array.add("java");
				Files.write(Paths.get("array.txt"), array, Charset.forName("GBK"));
			}
		}

IO流(四)