主要內容 1.編碼問題 2.File類的使用 3.RandomAccessFile的使用 4.I/O 輸入輸出流 編碼問題: 1 import java.io.UnsupportedEncodingException; 2 3 public class 編碼問題 { 4 public static ...
主要內容
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 }View Code
File類的使用:
JAVA.io.File類用於表示文件(目錄) File類只用於表示文件( 目錄)的信息(名稱、大小等),不能用於文件內容的訪問 File類的常用API: 1.創建File對象:File file=new File(String path);註意:File.seperater();獲取系統分隔符,如:”\“. 2.boolean file.exists();是否存在. 3.file.mkdir();或者file.mkdirs();創建目錄或多級目錄。 4.file.isDirectory()或者file.isFile()判斷是否是目錄或者是否是文件。 5.file.delete();刪除文件或目錄。 6.file.createNewFile();創建新文件。 7.file.getName()獲取文件名稱或目錄絕對路徑。 8.file.getAbsolutePath()獲取絕對路徑。 9.file.getParent();獲取父級絕對路徑。 10.file.getSize();獲取文件大小。 11.file.getFormat();獲取文件格式名。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 }FileDemo
遍歷目錄
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 }FileUtils
RandomAccessFile的使用
RandomAccessFile JAVA提供的對文件內容的訪問,既可以讀文件,也可以寫文件。 RandomAccessFile支持隨機訪問文件,可以訪問文件的任意位置 (1)JAVA文件模型 在硬碟上的文件是byte byte byte存儲的,是數據的集合 (2)打開文件 有兩種模式"rw"(讀寫) "r"(只讀) RandomAccessFile raf = new RandomeAccessFile(file,"rw") 文件指針,打開文件時指針在開頭 pointer = 0; (3) 寫方法 raf.write(int)--->只寫一個位元組(後8位),同時指針指向下一個位置,準備再次寫入 提供和很多方法能夠一次讀寫一個基本類型的數據 (4)讀方法 int b = raf.read()--->讀一個位元組 (5)文件讀寫完成以後一定要關閉(Oracle官方說明)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 }RafDemo
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(); } }RafReadDemo 序列化與基本類型序列化 1)將類型int 轉換成byte或將其他數據類型轉換成byte的過程叫序列化 數據---->n byte 2)反序列化 將n個byte 轉換成一個數據的過程 nbyte ---> 數據 3)RandomAccessFile提供基本類型的讀寫方法,可以將基本類型數據 序列化到文件或者將文件內容反序列化為數據
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 RandomAccessFileSeriaDemoRandomAccessFileSeriaDemo
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 }View Code
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 }TestFileInputStreamOutputStreamCopy
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 }TestFileReaderWriterCopy
緩衝流
緩衝流就是帶有緩衝區的輸入輸出流
緩衝流可以顯著的減少我們對IO訪問的次數,保護我們的硬碟
緩衝流本事就是處理流(包裹流),緩衝流必須得依附於節點流(原始流)
處理流包裹在原始節點流上的流,相當於包裹在管道上的管道
緩衝流要"套接"在相應的節點流之上,對讀寫的數據提供了緩衝的功能,提高了讀寫的效率,同時增加了一些新的方法。JAVA提供了四種緩衝流,其常用的構造方法為:
BufferedOutputStream 和 BufferedInputStream
BufferedOutputStream :帶有緩衝的輸出流,允許一次向硬碟寫入多個位元組的數據。
BufferedInputStream:帶緩衝的輸入流,允許一次向程式中讀入多個位元組的數據。
BufferedOutputStream 和 BufferedInputStream都是包裹流,必須依附於OutputStream和InputStream
例子:利用BufferedOutputStream 和 BufferedInputStream 完成大容量文件的複製,這遠比單純利用FileInputStream和FileOutputStream要快的多
1 /* 2 利用BufferedOutputStream 和 BufferedInputStream完成大容量文件的複製 3