主要內容
1.編碼問題
2.File類的使用
3.RandomAccessFile的使用
4.I/O 輸入輸出流
編碼問題:

1 import java.io.UnsupportedEncodingException; 2 3 public class 編碼問題 { 4 public static void main(String[] args) { 5 // 我們項目的默認編碼是GBK 6 String s = "測試 ABC"; 7 byte[] byte1 = s.getBytes();// 轉換成的字節序列用的是項目默認的編碼gbk 8 for (byte b : byte1) { 9 // 1 byte = 8 位 //toHexString這個函數是把字節(轉換成了Int)以16進制的方式顯示 10 System.out.print(Integer.toHexString(b & 0xff) + " ");// & 11 // 0xff是為了把前面的24個0去掉只留下后八位 12 } 13 14 try { 15 // 也可以轉換成指定的編碼 16 byte[] bytes1 = s.getBytes("gbk"); 17 System.out.println(new String(bytes1)); 18 } catch (UnsupportedEncodingException e) { 19 // TODO Auto-generated catch block 20 e.printStackTrace(); 21 } 22 /** 23 * gbk編碼: 中文占用兩個字節,英文占用一個字節 utf-8編碼:中文占用三個字節,英文占用一個字節 24 * java是雙字節編碼,是utf-16be編碼 utf-16be編碼:中文占用兩個字節,英文占用兩個字節 25 * 當你的字節序列是某種編碼時,這個時候想把字節序列變成字符串,也需要用這種編碼方式,否則會出現亂碼 26 */ 27 try { 28 byte[] byte2 = s.getBytes("utf-16be"); 29 String s2 = new String(byte2, "utf-16be"); 30 System.out.println(s2); 31 } catch (UnsupportedEncodingException e) { 32 // TODO Auto-generated catch block 33 e.printStackTrace(); 34 } 35 /** 36 * 文本文件就是字節序列,可以是任意編碼的字節序列 37 * 如果我們在中文機器上直接創建文本文件,那么該文件只認識ANSI編碼(例如直接在電腦中創建文本文件) 38 */ 39 40 /** 41 * byte轉int的時候為什么非要先&0xff計算出來才是正確答案? 42 * 首先,java中的二進制采用的是補碼形式,並非原碼或反碼,這3個概念要搞清楚; 43 * 其次,byte占8位,int占32位,將byte強制轉換為int型時,如果沒有做 & 44 * 0xff運算,且byte對應的值為負數的話,就會對高位3個字節進行補位,這樣就有可能出現補位誤差的錯誤。 45 * 舉例來說,byte型的-1,其二進制(補碼)為11111111(即0xff),轉換成int型,值也應該為-1,但經過補位后, 46 * 得到的二進制為11111111111111111111111111111111(即0xffffffff),這就不是-1了,對吧? 47 * 而0xff默認是int型,所以,一個byte跟0xff相與,會先將那個byte轉化成int型運算,這樣,結果中的高位3個字節就總會被清0, 48 * 於是結果就是我們想要的了~ 49 */ 50 51 } 52 53 }
File類的使用:

1 import java.io.File; 2 import java.io.IOException; 3 4 public class FileDemo { 5 6 /** 7 * @param args 8 */ 9 public static void main(String[] args) { 10 // 了解構造函數的情況 查幫助ALT+/ 11 File file = new File("E:\\javaio\\imooc"); 12 // 判斷文件/文件夾是否存在 13 // System.out.println(file.exists()); 14 if (!file.exists()) 15 file.mkdir(); // file.mkdirs()如果文件不存在,直接創建文件夾 16 // mkdir創建的一級目錄,如果需要創建多級目錄可以使用mkdirs() 17 else 18 file.delete(); 19 20 // 是否是一個目錄 如果是目錄返回true,如果不是目錄or目錄不存在返回的是false 21 System.out.println(file.isDirectory()); 22 // 是否是一個文件 23 System.out.println(file.isFile()); 24 25 // File file2 = new File("e:\\javaio\\日記1.txt"); 26 File file2 = new File("e:\\javaio", "日記1.txt"); 27 if (!file2.exists()) 28 try { 29 file2.createNewFile(); 30 } catch (IOException e) { 31 // TODO Auto-generated catch block 32 e.printStackTrace(); 33 } 34 else 35 file2.delete(); 36 // 常用的File對象的API 37 System.out.println(file);// file.toString()的內容 38 System.out.println(file.getAbsolutePath()); 39 System.out.println(file.getName()); 40 System.out.println(file2.getName()); 41 System.out.println(file.getParent()); 42 System.out.println(file2.getParent()); 43 System.out.println(file.getParentFile().getAbsolutePath()); 44 } 45 46 }
遍歷目錄

1 import java.io.File; 2 import java.io.IOException; 3 4 //列出File的一些常用操作比如過濾,遍歷等操作 5 public class FileUtils { 6 /** 7 * 列出指定指定目錄下(包括其子目錄)的所有文件 8 * 9 * @param dir 10 * @throws IOException 11 */ 12 public static void listDirectory(File dir) throws IOException { 13 if (!dir.exists()) { 14 throw new IllegalArgumentException("目錄:" + dir + "不存在"); 15 } 16 if (!dir.isDirectory()) { 17 throw new IllegalArgumentException(dir + "不是目錄"); 18 } 19 20 // String[] fileNames = 21 // dir.list();//返回的是字符串數組,list()方法用於列出當前目錄下的子目錄和文件,直接子的名稱,不包含子目錄下的內容 22 // for (String string : fileNames) { 23 // System.out.println(dir+"\\"+string); 24 // } 25 // 26 // 如果要遍歷子目錄下的內容就需要構造成File對象做遞歸操作,File提供了直接返回File對象的API 27 File[] files = dir.listFiles();// 返回的是直接子目錄(文件)的抽象 28 if (files != null && files.length > 0) {// 確定存在子目錄 29 for (File file : files) { 30 if (file.isDirectory()) { 31 // 遞歸 32 listDirectory(file); 33 } else { 34 System.out.println(file); 35 } 36 } 37 } 38 } 39 }
RandomAccessFile的使用

1 import java.io.File; 2 import java.io.IOException; 3 import java.io.RandomAccessFile; 4 import java.util.Arrays; 5 6 public class RafDemo { 7 8 /** 9 * @param args 10 */ 11 public static void main(String[] args) throws IOException { 12 File demo = new File("demo"); 13 if (!demo.exists()) 14 demo.mkdir(); 15 File file = new File(demo, "raf.dat"); 16 if (!file.exists()) 17 file.createNewFile(); 18 19 RandomAccessFile raf = new RandomAccessFile(file, "rw"); 20 // 指針的位置 21 System.out.println(raf.getFilePointer()); 22 23 raf.write('A');// 只寫了一個字節 24 System.out.println(raf.getFilePointer()); 25 raf.write('B'); 26 27 int i = 0x7fffffff; 28 // 用write方法每次只能寫一個字節,如果要把i寫進去就得寫4次 29 raf.write(i >>> 24);// 高8位 30 raf.write(i >>> 16); 31 raf.write(i >>> 8); 32 raf.write(i); 33 System.out.println(raf.getFilePointer()); 34 35 // 可以直接寫一個int 36 raf.writeInt(i); 37 38 String s = "中"; 39 byte[] gbk = s.getBytes("gbk"); 40 raf.write(gbk); 41 System.out.println(raf.length()); 42 43 // 讀文件,必須把指針移到頭部 44 raf.seek(0); 45 // 一次性讀取,把文件中的內容都讀到字節數組中 46 byte[] buf = new byte[(int) raf.length()]; 47 raf.read(buf); 48 49 System.out.println(Arrays.toString(buf)); 50 for (byte b : buf) { 51 System.out.println(Integer.toHexString(b & 0xff) + " "); 52 } 53 raf.close(); 54 } 55 56 }

import java.io.IOException; import java.io.RandomAccessFile; public class RafReadDemo { /** * @param args */ public static void main(String[] args) throws IOException { // TODO Auto-generated method stub RandomAccessFile raf = new RandomAccessFile("demo/raf.dat", "r"); raf.seek(2); int i = 0; int b = raf.read();// 讀取到一個字節 System.out.println(raf.getFilePointer()); i = i | (b << 24); b = raf.read(); i = i | (b << 16); b = raf.read(); i = i | (b << 8); b = raf.read(); i = i | b; System.out.println(Integer.toHexString(i)); raf.seek(2); i = raf.readInt(); System.out.println(Integer.toHexString(i)); raf.close(); } }

1 import java.io.File; 2 import java.io.IOException; 3 import java.io.RandomAccessFile; 4 public class RandomAccessFileSeriaDemo { 5 6 /** 7 * @param args 8 */ 9 public static void main(String[] args) throws IOException { 10 // TODO Auto-generated method stub 11 File demo = new File("demo1"); 12 if (!demo.exists()) 13 demo.mkdir(); 14 File file = new File(demo, "raf.dat"); 15 if (!file.exists()) 16 file.createNewFile(); 17 // 打開文件,進行隨機讀寫 18 RandomAccessFile raf = new RandomAccessFile(file, "rw"); 19 /* 序列化 */ 20 int i = 0x7ffffff; 21 raf.write(i >>> 24); 22 raf.write(i >>> 16); 23 raf.write(i >>> 8); 24 raf.write(i); 25 System.out.println(raf.getFilePointer()); 26 27 /* 反序列化 */ 28 raf.seek(0); 29 int b = raf.read(); 30 i = i | (b << 24); 31 b = raf.read(); 32 i = i | (b << 16); 33 b = raf.read(); 34 i = i | (b << 8); 35 b = raf.read(); 36 i = i | b; 37 System.out.println(Integer.toHexString(i)); 38 raf.close(); 39 } 40 } 41 42 RandomAccessFileSeriaDemo
I/O 輸入輸出流
流的定義:
流就是程序和設備之間嫁接起來的一根用於數據傳輸的管道,這個管道上有很多按鈕,不同的按鈕可以實現不同的功能。
這根用於數據傳輸的管道就是流,流就是一根管道
輸入時,程序在源(文件,網絡,內存)上打開一個流,然后如圖一個一個順序讀。寫也一樣。
流的分類和使用:
四大基本抽象流,文件流,緩沖流,轉換流,數據流,Print流,Object流。
JAVA.io 包中定義了多個流類型(類或抽象類)來實現輸入/輸出功能;可以從不同角度對其進行分類:
*按數據流的方向不用可以分為輸入流和輸出流
*按處理數據單位不同可以分為字節流和字符流
*按照功能不同可以分為節點流和處理流
JAVA中所提供的的所有流類型位於包JAVA.io內,都分別繼承自以下四種抽象流類型:
節點流與處理流:
節點流可以從一個特定的數據源(節點)讀取數據(如:文件,內存)
處理流是“連接”在已存在的流(節點流或處理流)之上,通過對數據的處理為程序提供更為強大的讀寫功能。
節點流也叫原始流,處理流也叫包裹流。
流與類的關系:
如果一個類是用作設備和程序之間的數據傳輸,則這個類有一個新的名字叫做流
流一定是類,但類不一定是流
四大基本流的介紹
輸入流,輸出流,字節流,字符流
InputStream和OutputStream讀寫數據的單位是一個字節
Reader和Writer讀寫數據的單位是一個字符
在JAVA中一個字符占兩個字節
InputStream,OutputStream,Reader,Writer都是抽象類,或者說都是抽象流,通常我們使用的都是它們的子類,凡是以Stream結尾的都是字節流。
InputStream 流中的常用方法:
OutputStream 流中的常用方法:
Reader 流中的常用方法:
Writer 流中的常用方法:
文件流
文件流包括:
FileInputStream FileOutputStream --字節流
FileReader FileWriter --字符流
實例:讀取一個文件的內容並將其輸出到顯示器上,並統計讀取的字節個數

1 /* 2 利用FileReader流來讀取一個文件中的數據,並在顯示器上輸出! 3 */ 4 5 import java.io.*; 6 7 public class TestFileReader { 8 public static void main(String[] args) { 9 FileReader fr = null; 10 11 try { 12 fr = new FileReader("C:\\Documents and Settings\\others\\桌面\\java\\TestFileReader.java"); 13 int cnt = 0; 14 int ch; 15 16 while (-1 != (ch = fr.read())) // 20行 17 { 18 System.out.print((char) ch); // System.out.print(int ch); 19 // 這是在顯示器上輸出ch的整數值,所以必須的進行類型轉化,我們需要輸出的是ch所代表的整數對應的字符 20 ++cnt; 21 } 22 23 System.out.printf("總共從TestFileReader.java文件中讀取了%d個字符", cnt); 24 } catch (FileNotFoundException e) { 25 System.out.println("找不到文件!"); 26 System.exit(-1); 27 } catch (IOException e) { 28 System.out.println("文件讀取失敗!"); 29 System.exit(-1); 30 } 31 } 32 }
FileInputStream的使用
FileReader的使用
字節流與字符流的區別:
FileInputStream 和FileOutputStream 可以完成所有格式文件的復制
FileReader和FileWriter只可以完成文本文件的復制,卻無法完成其他格式文件的復制
因為字節是不需要解碼和編碼的,將字節轉化為字符才存在解碼和編碼的問題
字節流可以從所有格式的設備中讀寫數據,但字符流只能從文本格式的設備中讀寫數據
實例:編程實現文件的復制

1 /* 2 利用FileInputStream 和 FileOutputStream 可以完成所有格式文件的賦值 3 因為字節是不需要解碼和編碼的,將字節轉化為字符才存在解碼的問題 4 本程序完成了音頻文件的復制 5 */ 6 7 import java.io.*; 8 9 public class TestFileInputStreamOutputStreamCopy { 10 public static void main(String[] args) { 11 FileInputStream fi = null; 12 FileOutputStream fo = null; 13 14 try { 15 fi = new FileInputStream("E:\\綜藝\\歌曲\\卡農.mp3"); 16 fo = new FileOutputStream("d:/share/Output.txt"); //使用播放器可正常播放該文件 17 int ch; 18 19 while (-1 != (ch = fi.read())) { 20 fo.write(ch); 21 } 22 } catch (FileNotFoundException e) { 23 System.out.println("文件沒有找到!"); 24 System.exit(-1); 25 } catch (IOException e) { 26 System.out.println("文件讀寫錯誤!"); 27 System.exit(-1); 28 } finally { 29 try { 30 if (null != fi) { 31 fi.close(); 32 fi = null; 33 } 34 if (null != fo) { 35 fo.close(); 36 fo = null; 37 } 38 } catch (Exception e) { 39 e.printStackTrace(); 40 System.exit(-1); 41 } 42 } 43 44 System.out.println("文件復制成功!"); 45 } 46 }

1 /* 2 本程序證明了 FileReader 和 FileWriter 只可以完成文本文件的復制, 3 卻無法完成音頻格式文件的復制 4 */ 5 6 import java.io.*; 7 8 public class TestFileReaderWriterCopy { 9 public static void main(String[] args) { 10 FileReader fi = null; 11 FileWriter fo = null; 12 13 try { 14 fi = new FileReader("E:\\綜藝\\歌曲\\卡農.mp3"); 15 fo = new FileWriter("d:/share/Output.txt"); // Output.txt使用播放器打開失敗! 16 // 本程序證明了FileWriter 和 17 // FileReader 18 // 無法完成音頻文件的復制,實際上FileWriter 19 // 和 FileReader 20 // 只能完成文本文件的復制 21 int ch; 22 23 while (-1 != (ch = fi.read())) { 24 fo.write(ch); 25 } 26 } catch (FileNotFoundException e) { 27 System.out.println("文件沒有找到!"); 28 System.exit(-1); 29 } catch (IOException e) { 30 System.out.println("文件讀寫錯誤!"); 31 System.exit(-1); 32 } finally { 33 try { 34 if (null != fi) { 35 fi.close(); 36 fi = null; 37 } 38 if (null != fo) { 39 fo.close(); 40 fo = null; 41 } 42 } catch (Exception e) { 43 e.printStackTrace(); 44 System.exit(-1); 45 } 46 } 47 48 System.out.println("文件復制成功!"); 49 } 50 }
緩沖流
緩沖流就是帶有緩沖區的輸入輸出流
緩沖流可以顯著的減少我們對IO訪問的次數,保護我們的硬盤
緩沖流本事就是處理流(包裹流),緩沖流必須得依附於節點流(原始流)
處理流包裹在原始節點流上的流,相當於包裹在管道上的管道
緩沖流要"套接"在相應的節點流之上,對讀寫的數據提供了緩沖的功能,提高了讀寫的效率,同時增加了一些新的方法。JAVA提供了四種緩沖流,其常用的構造方法為:
BufferedOutputStream 和 BufferedInputStream
BufferedOutputStream :帶有緩沖的輸出流,允許一次向硬盤寫入多個字節的數據。
BufferedInputStream:帶緩沖的輸入流,允許一次向程序中讀入多個字節的數據。
BufferedOutputStream 和 BufferedInputStream都是包裹流,必須依附於OutputStream和InputStream
例子:利用BufferedOutputStream 和 BufferedInputStream 完成大容量文件的復制,這遠比單純利用FileInputStream和FileOutputStream要快的多

1 /* 2 利用BufferedOutputStream 和 BufferedInputStream完成大容量文件的復制 3 這遠比單純利用 FileInputStream 和 FileOutputStream 要快得多 4 5 BufferedOutputStream 和 BufferedInputStream 都是包裹流,必須的依附於 6 InputStream 和 OutputStream 7 */ 8 9 import java.io.*; 10 11 public class TestBufferedInputStreamOutputStreamCopy { 12 public static void main(String[] args) { 13 BufferedOutputStream bos = null; 14 BufferedInputStream bis = null; 15 16 try { 17 bos = new BufferedOutputStream(new FileOutputStream("e:/OutputView.txt")); // bos 18 // 輸出流有個默認的緩沖區,大小為32個字節 19 20 bis = new BufferedInputStream(new FileInputStream("c:\\[高清在線www.66ys.cn]海底總動員DVD中英字幕.rmvb")); // bis 21 // 輸入流有個默認的緩沖區,大小為32個字節 22 byte[] buf = new byte[1024]; 23 int len = bis.read(buf, 0, 1024); // 一定要注意,這不是從buf中讀數據,而是從bis所關聯到的D:\\綜藝\\電影\\貓和老鼠\\CD4.rmvb文件中讀取數據,並將讀取的數據寫入bis自己的默認緩沖區中,然后再將緩沖區的內容寫入buf數組中,每次最多向buf數組中寫入1024個字節,返回實際寫入buf數組的字節個數,如果讀到了文件的末尾,無法再向buf數組中寫入數據,則返回-1 24 while (-1 != len) { 25 bos.write(buf, 0, len); // 不是寫入buf數組,而是將buf數組中下標從0開始的到len-1為止的所有數據寫入bos所關聯到的"d:/share/OutputView.txt"文件中 26 len = bis.read(buf); // bis.read(buf); 等價於 bis.read(buf, 0, 27 // buf.length); 28 } 29 bos.flush(); 30 bis.close(); 31 bos.close(); 32 } catch (FileNotFoundException e) { 33 System.out.println("沒有找到文件!"); 34 System.exit(-1); 35 } catch (IOException e) { 36 System.out.println("文件讀寫錯誤!"); 37 System.exit(-1); 38 } 39 40 System.out.println("文件復制成功!"); 41 } 42 }

1 /* 2 本程序讀寫速度要慢於 "TestBufferedInputStreamOutputStreamCopy.java" 程序 3 即: 4 利用BufferedOutputStream 和 BufferedInputStream完成大容量文件的復制 5 這遠比單純利用 FileInputStream 和 FileOutputStream 要快得多 6 7 BufferedOutputStream 和 BufferedInputStream 都是包裹流,必須的依附於 8 OutputStream 和 OutputStream 9 */ 10 11 import java.io.*; 12 13 public class TestBufferedInputStreamOutputStreamCopy_2 { 14 public static void main(String[] args) { 15 FileOutputStream bos = null; 16 FileInputStream bis = null; 17 18 try { 19 bos = new FileOutputStream("e:/OutputView.txt"); 20 bis = new FileInputStream("c:\\[高清在線www.66ys.cn]海底總動員DVD中英字幕.rmvb"); 21 22 byte[] buf = new byte[1024]; 23 int len = bis.read(buf, 0, 1024); 24 while (-1 != len) { 25 bos.write(buf, 0, len); 26 len = bis.read(buf); 27 } 28 bos.flush(); 29 bis.close(); 30 bos.close(); 31 } catch (FileNotFoundException e) { 32 System.out.println("沒有找到文件!"); 33 System.exit(-1); 34 } catch (IOException e) { 35 System.out.println("文件讀寫錯誤!"); 36 System.exit(-1); 37 } 38 39 System.out.println("文件復制成功!"); 40 } 41 }
一定要注意,bis.read(buf,0,1024);這不是從buf中讀數據,而是從bis所關聯到的“D:\\綜藝\\電影\\貓和老鼠\\CD4.rmvb”文件中讀取數據,並將讀取的數據寫入bis自己的默認緩沖區中,然后再將緩沖區的內容寫入buf數組中,每次最多向buf數組中寫入1024個字節,返回實際寫入buf數組的字節個數,如果讀到了文件的末尾,無法再向buf數組中寫入數據,則返回-1
BufferedInputStream流中有public int read(byte[] b)方法用來把從當前流關聯到的設備中讀取出來的數據存入一個byte數組中
BufferedOutputStream 流中有public int write(byte[] b)方法用來把byte數組中的數據輸出來當前流所關聯到的設備中
如果我們希望用BufferedInputStream 和 BufferedOutputStream 完成“將一個設備中的數據導入另一個設備中”,我們就應該定義一個臨時的byte類型的數據,用這個臨時數組作為輸入流和輸出流進行交互的中轉樞紐。
BufferedReader 和 BufferedWriter
實例:利用BufferedReader 和 BufferedWriter完成文本文件的復制

1 /* 2 利用 BufferedReader 和 BufferedWriter 完成文本文件的復制 3 */ 4 import java.io.*; 5 6 public class TestBufferedReaderWriterCopy { 7 public static void main(String[] args) { 8 BufferedReader br = null; 9 BufferedWriter bw = null; 10 11 try { 12 br = new BufferedReader( 13 new FileReader("C:\\Documents and Settings\\others\\桌面\\java\\TestBufferedReaderWriterCopy.java")); 14 bw = new BufferedWriter(new FileWriter("d:/share/Writer.txt")); 15 String str = null; 16 17 while (null != (str = br.readLine())) // br.readLine()讀取一行字符,但會將讀取的換行符自動丟棄,即返回的String對象中並不包括換行符 18 { 19 bw.write(str); 20 bw.newLine(); // 寫入一個換行符 這行不能省 21 } 22 bw.flush(); 23 } catch (FileNotFoundException e) { 24 e.printStackTrace(); 25 System.exit(-1); 26 } catch (IOException e) { 27 e.printStackTrace(); 28 System.exit(-1); 29 } finally { 30 try { 31 bw.close(); 32 br.close(); 33 } catch (IOException e) { 34 e.printStackTrace(); 35 System.exit(-1); 36 } 37 } 38 } 39 }
數據流DataInputStream DataOutputStream
DataInputStream能夠以一種與機器無關的方式,直接從底層字節輸入流讀取JAVA基本類型和String類型的數據。常用方法包括:
DataInputStream 是包裹流,必須依附於InputStream
DataOutputStream能夠以一種機器無關的方式,直接將JAVA基本類型和String類型數據寫出到其他的字節輸出流。常用方法包括:
DataOutputStream 是包裹流,它必須依附於OutputStream
數據流實例:
編程實現將long類型數據寫入byte數組,然后再從byte數組中吧該數據讀出來{
*這是Socket編程中經常要完成的功能。
*因為網絡編程中經常要把數據存入byte數組中,然后把byte數組打包成數據包(DatagramPacket),再把數據包經過網絡傳輸到目的機,目的機再從byte數組中把原數值型數據還原回來。
}
本程序要使用到:
DataInputStream
DataOutputStream
ByteArrayInputStream
ByteArrayOutputStream

1 /* 2 功能:把一個long類型的數據寫入byte數組中,然后再從byte數組中讀取出 3 這個long類型的數據 4 5 因為網絡編程中經常要把數值型數據存入byte數組中然后打包成 6 DatagramPacket經過網絡傳輸到目的機,目的機再從byte數組中 7 把原數值型數據還原回來 8 9 目的: ByteArrayOutputStream DataOutputStream ByteInputStream DataInputStream 流的使用 10 記住: DataOutputStream流中的writeLong(long n)是把n變量在內存 11 中的二進制代碼寫入該流所連接到的設備中 12 13 注意:查API文檔得知: 14 構造 ByteArrayOutputStream 對象時不需要也不能指定緩沖數組,因為緩沖數組默認已經內置好了 15 構造 ByteArrayInputStream 對象時必須的指定緩沖數組是誰! 16 */ 17 18 import java.io.*; 19 20 public class TestByteArrayOutputStream1 21 { 22 public static void main(String args[]) throws Exception 23 { 24 long n = 9876543210L; 25 ByteArrayOutputStream baos = new ByteArrayOutputStream(); //9行 API:"public ByteArrayOutputStream(): 創建一個新的 byte 數組輸出流。緩沖區的容量最初是 32 字節,如有必要可增加其大小。 " 26 //9行代碼一旦執行完畢,意味着兩點: 1、在內存中生成了一個大小為32個字節的byte數組 2、有一根叫做baos的管道已鏈接到了該byte數組中,並且可以通過這個管道向該byte數組中寫入數據 27 //雖然此時可以通過baos向baos所連接到的在內存中分配好的byte數組中寫入數據,但是ByteArrayOutputStream流並沒有提供可以直接把long類型數據直接寫入ByteArrayOutputStream流所連接到的byte數組中的方法, 簡單說我們沒法通過baos向baos所連接到的byte數組中寫入long類型的數據, 查API文檔可以發現: ByteArrayOutputStream流中並沒有類似writeLong()這樣的方法,但是DataOutputStream流中卻有writeLong() writeFloat()等方法 28 DataOutputStream dos = new DataOutputStream(baos); 29 30 dos.writeLong(n); //把n變量所代表的10000L在內存中的二進制代碼寫入dos所依附的baos管道所連接到的內存中的大小為32字節的byte數組中,由運行結果來看,這是二進制寫入,既不是把10000L轉化為字符'1' '0' '0' '0' '0'寫入byte數組中,而是把10000L在內存中的總共8個字節的二進制代碼寫入byte數組中 31 32 dos.flush(); 33 byte[] buf = baos.toByteArray(); //DataOutputStream 流中並沒有toByteArray()方法,但是ByteArrayOutputStream 流中卻有toByteArray()方法, 所以不可以把baos 改為dos,否則編譯時會出錯! ByteArrayOutputStream流中toByteArray()方法的含義,摘自API“創建一個新分配的 byte 數組。其大小是此輸出流的當前大小,並且緩沖區的有效內容已復制到該數組中” 34 35 //利用ByteArrayInputStream 和 DataInputStream 可以從byte數組中得到原long類型的數值10000L 36 ByteArrayInputStream bais = new ByteArrayInputStream(buf); 37 DataInputStream dis = new DataInputStream(bais); 38 long l = dis.readLong(); 39 40 System.out.println("l = " + l); 41 dos.close(); 42 } 43 } 44 /* 45 在JDK 1.6中的運行結果是: 46 ---------------- 47 l = 9876543210 48 ---------------- 49 */

1 /* 2 功能: 3 將long類型數據寫入byte數組,然后在從byte數組中把該數據讀出來 4 */ 5 6 import java.io.*; 7 8 public class TestByteArrayOutputStream2 9 { 10 public static void main(String[] args) throws Exception 11 { 12 long n = 1234567; 13 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 14 DataOutputStream dos = new DataOutputStream(baos); 15 dos.writeLong(n); 16 17 byte[] buf = baos.toByteArray(); 18 ByteArrayInputStream bis = new ByteArrayInputStream(buf); 19 DataInputStream dis = new DataInputStream(bis); 20 long n2 = dis.readLong(); 21 System.out.println("n2 = " + n2); 22 23 dos.close(); 24 dis.close(); 25 } 26 }
轉換流:OutputStreamWriter InputStreamReader
OutputStreamWriter 流是把OutputStream流 轉化成Writer流的流
InputStreamReader 流是把InputStream流轉化為Reader
OutputStreamWriter 和 InputStreamReader都是包裹流
實例:如何將鍵盤輸入的字符組成字符串直接賦給String對象。

1 /* 2 如何將鍵盤輸入的字符組成字符串直接賦給String 對象 3 4 預備知識: 5 -------------------------------- 6 Reader FileReader InputStream FileInputStream BufferedInputStream 7 流中都沒有 readLine 方法 8 DataInputStream 流中有 readLine方法,但已經 被標記為過時 9 BufferedReader 流中有readLine方法,並且該方法是可以正確被使用的 10 -------------------------------- 11 */ 12 13 import java.io.*; 14 15 public class TestStringInput 16 { 17 public static void main(String[] args) 18 { 19 String str = null; 20 BufferedReader br = new BufferedReader ( //21行 21 new InputStreamReader(System.in) 22 ); //23行 查API:從21行到23行的代碼是不會拋出任何異常的 23 24 try 25 { 26 str = br.readLine(); //會拋出IOException異常 27 } 28 catch (IOException e) 29 { 30 e.printStackTrace(); 31 System.exit(-1); 32 } 33 34 System.out.println("str = " + str); 35 try 36 { 37 br.close(); //會拋出IOException異常 38 } 39 catch (IOException e) 40 { 41 e.printStackTrace(); 42 System.exit(-1); 43 } 44 } 45 } 46 /* 47 在JDK 1.6中的運行結果是: 48 -------------------------------- 49 sadd行政村123Asd?asd撒旦 50 str = sadd行政村123Asd?asd撒旦 51 -------------------------------- 52 */
readLine()與回車符的問題:
Print流 PrintWriter PrintStream
Print 流只有輸出,沒有輸入
分類:
PrintWriter輸入字符
PrintStream輸出字符
PrintWriter在OutputStream基礎之上提供了增強的功能,既可以方便地輸出各種類型數據(而不僅限於byte型)的格式化表示形式。
PrintStream重載了print和println方法,用於各種不同類型數據的格式化輸出。
格式化輸出是指將一個數據用其字符串格式輸出。
DataOutputStream 中的 WriteXXX(data)方法是把data在內存中的二進制數據寫入文件
PrintStream 中的println(data)是該數據格式化后的字符串寫入文件

1 /* 2 DataOutputStream 中的 writeXXX(data)方法 3 與 4 PrintStream 中的 println(data)的區別 5 6 總結: 7 DataOutputStream 中的 writeXXX(data)方法是把data在內存中的二進制數據寫入文件 8 PrintStream 中的 println(data)寫出的是該數據的格式化后的字符串 9 */ 10 11 import java.io.*; 12 13 public class TestPrintStream_1 14 { 15 public static void main(String[] args) throws Exception 16 { 17 DataOutputStream dos = new DataOutputStream(new FileOutputStream("d:/share/kk.txt")); 18 dos.writeLong(12345); //實際寫入文件的是00 00 00 00 00 00 30 39 19 dos.close(); 20 System.out.printf("%#X\n", 12345); 21 22 PrintStream ps = new PrintStream(new FileOutputStream("d:/share/kk2.txt"), true); 23 ps.println(12345); //實際寫入文件的是'1' '2' '3' '4' '5' 24 ps.close(); 25 } 26 }
PrintWriter 提供了PrintStream的所有打印方法, 其方法也從不拋出IOException。
與PrintStream的區別:
標准輸入輸出的重定向:
實例:編程實現將鍵盤輸入的數據輸入A文件中,如果輸入有誤,則把出錯信息輸出到B文件

1 import java.io.*; 2 3 public class TestSetSystemOut { 4 public static void main(String[] args) { 5 PrintStream ps_out = null; 6 7 try { 8 ps_out = new PrintStream(new FileOutputStream("d:/share/ww.txt")); 9 System.setOut(ps_out); // 將System.out的值重新設置為ps_out,即System.out不在關聯到顯示器,而是關聯到"d:/share/ww.txt"文件 10 System.out.println(12); // 這實際上是把12輸出到了System.out所關聯的d:/share/ww.txt中 11 System.out.println(55.5); // 同上 12 } catch (Exception e) { 13 e.printStackTrace(); 14 } finally { 15 try { 16 ps_out.close(); 17 } catch (Exception e) { 18 e.printStackTrace(); 19 } 20 21 } 22 } 23 }

1 /* 2 功能: 將鍵盤輸入的數據輸入A文件中,如果輸入有誤, 3 則把出錯信息輸出到B文件中 4 5 標准輸入輸出流的重定向 6 */ 7 8 import java.io.*; 9 import java.util.*; 10 11 public class TestSetOutErr { 12 public static void main(String[] args) { 13 PrintStream psOut = null; 14 PrintStream psError = null; 15 Scanner sc = null; 16 17 try { 18 psOut = new PrintStream("d:/Out.txt"); 19 psError = new PrintStream("d:/error.txt"); 20 sc = new Scanner(System.in); 21 int num; 22 System.setOut(psOut); 23 System.setErr(psError); 24 25 while (true) { 26 num = sc.nextInt(); 27 System.out.println(num); 28 } 29 } catch (Exception e) { 30 System.err.println("出錯的信息是:"); // 不可以寫成System.out.println("出錯的信息是:"); 31 e.printStackTrace(); // e.printStackTrace(); 默認是輸出到System.err所關聯的設備中 32 } 33 } 34 }

實例:

1 import java.io.*; 2 3 public class TestObjectIO 4 { 5 public static void main(String[] args) 6 { 7 ObjectOutputStream oos = null; 8 ObjectInputStream ois = null; 9 Student ss = new Student("zhansan", 1000, 88.8f); //注意88.8f不能改為88.8 10 Student ss2 = null; 11 12 try 13 { 14 FileOutputStream fos = new FileOutputStream("d:/share/java/ObjectOut.txt"); 15 oos = new ObjectOutputStream(fos); 16 oos.writeObject(ss); 17 18 ois = new ObjectInputStream(new FileInputStream("d:/share/java/ObjectOut.txt")); 19 ss2 = (Student)ois.readObject(); //(Student)不能省 ois.readObject();如果ois中的某個成員是transient,則該成員是不會被讀取的,因為該成員不會被保存,何來讀取之說?! 20 21 System.out.println("ss2.sname = " + ss2.sname); 22 System.out.println("ss2.sid = " + ss2.sid); 23 System.out.println("ss2.sscore = " + ss2.sscore); 24 } 25 catch (FileNotFoundException e) 26 { 27 System.out.println("文件沒有找到!"); 28 System.exit(-1); 29 } 30 catch (Exception e) 31 { 32 e.printStackTrace(); 33 System.exit(-1); 34 } 35 finally 36 { 37 try 38 { 39 oos.close(); 40 ois.close(); 41 } 42 catch (Exception e) 43 { 44 e.printStackTrace(); 45 System.exit(-1); 46 } 47 } 48 } 49 } 50 51 class Student implements Serializable //如果將implements Serializable 注釋掉,則程序編譯時就會報錯 52 { 53 public String sname = null; 54 public int sid = 0; 55 transient public float sscore = 0; //表示sscore成員不能被序列化,所謂不能被序列化就是指:“該成員調用ObjectOutputStream 的writeOnbject()時不會被保存,調用ObjectInputStream的readObject()方法時不會被讀取” 56 57 public Student(String name, int id, float score) 58 { 59 this.sname = name; 60 this.sid = id; 61 this.sscore = score; 62 } 63 }