日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

第10章 流

發布時間:2024/4/17 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 第10章 流 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

2019獨角獸企業重金招聘Python工程師標準>>>

File 類

  • java.io.File類:文件和目錄路徑名的抽象表示形式,與平臺無關。
  • File 能新建、刪除、重命名文件和目錄,但 File 不能訪問文件內容本身。 如果需要訪問文件內容本身,則需要使用 輸入/輸出流
  • File對象可以作為參數傳遞給流的構造函數。

File的靜態屬性

String separator存儲了當前系統的路徑分隔符。 在UNIX中,此字段為‘/’,在Windows中,為‘\’。

File類的常見構造方法

public File(String pathname)

以pathname為路徑創建File對象,可以是絕對路徑或者相對路徑,如果pathname是相對路徑,則默認的當前路徑在系統屬性user.dir中存儲。

public File(String parent,String child)

以parent為父路徑,child為子路徑創建File對象。

File類的常見方法

  • 訪問文件名:

getName() getPath() getAbsoluteFile() getAbsolutePath() getParent() renameTo(File newName)

  • 文件檢測:

exists() canWrite() canRead() isFile() isDirectory()

  • 獲取常規文件信息:

lastModified() length()

  • 文件操作相關:

createNewFile() delete()

  • 目錄操作相關:

mkDir() mkDirs() list() listFiles()

File dir1 = new File("D:/IOTest/dir1"); // 如果D:/IOTest/dir1不存在,就創建為目錄 if (!dir1.exists()) {dir1.mkdir(); } // 創建以dir1為父目錄,名為"dir2"的File對象 File dir2 = new File(dir1, "dir2"); if (!dir2.exists()) { // 如果還不存在,就創建為目錄dir2.mkdirs(); } File dir4 = new File(dir1, "dir3/dir4"); if (!dir4.exists()) {dir4.mkdirs(); } // 創建以dir2為父目錄,名為"test.txt"的File對象 File file = new File(dir2, "test.txt"); if (!file.exists()) { // 如果還不存在,就創建為文件try {file.createNewFile();} catch (IOException e) {e.printStackTrace();} }

練習

利用File構造器,new 一個目錄file
1)在其中創建多個文件和目錄。
2)編寫方法,實現刪除file中文件的操作。

public class Test2 {public static void main(String[] args) {File dir = new File("d:\\test2\\");if (!dir.exists()) {dir.mkdir();}File file = new File(dir, "test.txt");if (!file.exists()) { // 如果還不存在,就創建為文件try {file.createNewFile();} catch (IOException e) {e.printStackTrace();}System.out.println("創建的文件名是:"+file.getName());}//刪除文件file.delete();if(!file.exists()){System.out.println("文件刪除成功");}} }

Java IO原理

  • IO流用來處理設備之間的數據傳輸。
  • Java程序中,對于數據的輸入/輸出操作以“流(stream)”的方式進行。
  • java.io包下提供了各種“流”類和接口,用以獲取不同種類的數據,并通過標準的方法輸入或輸出數據。
  • 輸入input:讀取外部數據(磁盤、光盤等存儲設備的數據)到程序(內存)中。
  • 輸出output:將程序(內存)數據輸出到磁盤、光盤等存儲設備中。

流的分類

  • 按操作數據單位不同分為:字節流(8 bit),字符流(16 bit) 。
  • 按數據流的流向不同分為:輸入流,輸出流。
  • 按流的角色的不同分為:節點流,處理流。

  • Java的IO流共涉及40多個類,實際上非常規則,都是從如下4個抽象基類派生的。
  • 由這四個類派生出來的子類名稱都是以其父類名作為子類名后綴。

IO 流體系

節點流和處理流

  • 節點流可以從一個特定的數據源讀寫數據。

  • 處理流是“連接”在已存在的流(節點流或處理流)之上,通過對數據的處理為程序提供更為強大的讀寫功能。

InputStream & Reader

  • InputStream 和 Reader 是所有輸入流的基類。
  • InputStream(典型實現:FileInputStream)。

int read(); int read(byte[] b); int read(byte[] b, int off, int len);

  • Reader(典型實現:FileReader)

int read(); int read(char [] c); int read(char [] c, int off, int len);

  • 程序中打開的文件IO資源不屬于內存里的資源,垃圾回收機制無法回收該資源,所以應該顯式關閉文件IO資源。

OutputStream & Writer

  • OutputStream 和 Writer 是所有輸出流的基類。
  • OutputStream(典型實現:FileOutputStream)。

void write(int b/int c); void write(byte[] b/char[] cbuf); void write(byte[] b/char[] buff, int off, int len); void flush(); void close(); //需要先刷新,再關閉此流。

  • 因為字符流直接以字符作為操作單位,所以 Writer 可以用字符串來替換字符數組,即以 String 對象作為參數。

void write(String str); void write(String str, int off, int len);

文件流

讀取文件

  • 建立一個流對象,將已存在的一個文件加載進流。 FileReader fr = new FileReader(“Test.txt”);
  • 創建一個臨時存放數據的數組。 char[] ch = new char[1024];
  • 調用流對象的讀取方法將流中的數據讀入到數組中。 fr.read(ch);
FileReader fr = null; try {fr = new FileReader("c:\\test.txt");char[] buf = new char[1024];int len = 0;while ((len = fr.read(buf)) != -1) {System.out.println(new String(buf, 0, len));} } catch (IOException e) {System.out.println("read-Exception :" + e.toString()); } finally {if (fr != null) {try {fr.close();} catch (IOException e) {System.out.println("close-Exception :" + e.toString());}} }

寫入文件

  • 創建流對象,建立數據存放文件。
    FileWriter fw = new FileWriter("Test.txt")

  • 調用流對象的寫入方法,將數據寫入流。
    fw.write("text")

  • 關閉流資源,并將流中的數據清空到文件中。
    fw.close()

例:

FileWriter fw = null; try {fw = new FileWriter("Test.txt");fw.write("text"); } catch (IOException e) {e.printStackTrace(); } finally {if (fw != null) {try {fw.close();} catch (IOException e) {System.out.println(e.toString());}} }

注意

  • 定義文件路徑時,注意:可以用“/”或者“\”。
  • 在寫入一個文件時,如果目錄下有同名文件將被覆蓋。
  • 在讀取文件時,必須保證該文件已存在,否則出異常。

處理流之一:緩沖流

  • 為了提高數據讀寫的速度,Java API提供了帶緩沖功能的流類,在使用這些流類時,會創建一個內部緩沖區數組。
  • 根據數據操作單位可以把緩沖流分為:

BufferedInputStream 和 BufferedOutputStream
BufferedReader 和 BufferedWriter

  • 緩沖流要“套接”在相應的節點流之上,對讀寫的數據提供了緩沖的功能,提高了讀寫的效率,同時增加了一些新的方法。
  • 對于輸出的緩沖流,寫出的數據會先在內存中緩存,使用flush()將會使內存中的數據立刻寫出。
BufferedReader br = null; BufferedWriter bw = null; try {//step1:創建緩沖流對象:它是過濾流,是對節點流的包裝br = new BufferedReader(new FileReader("d:\\IOTest\\source.txt"));bw = new BufferedWriter(new FileWriter("d:\\IOTest\\destBF.txt"));String str = null;while ((str = br.readLine()) != null) {//一次讀取字符文本文件的一行字符bw.write(str); //一次寫入一行字符串bw.newLine(); //寫入行分隔符}bw.flush(); //step2:刷新緩沖區 } catch (IOException e) {e.printStackTrace(); } finally {// step3: 關閉IO流對象try {if (bw != null) {//關閉過濾流時,會自動關閉它所包裝的底層節點流bw.close(); }} catch (IOException e) {e.printStackTrace();}try {if (br != null) {br.close();}} catch (IOException e) {e.printStackTrace();} }

練習

分別使用
節點流:FileInputStream、FileOutputStream

緩沖流:BufferedInputStream、BufferedOutputStream
實現文本文件/圖片/視頻文件的復制。
并比較二者在數據復制方面的效率。

public class Test3 {public static void main(String[] args) throws IOException {FileInputStream fis = new FileInputStream("src/main/java/io/Test3.java");FileOutputStream fos = new FileOutputStream("copy.txt");int len = 0;byte[] b = new byte[1024];while ((len = fis.read(b)) != -1) {fos.write(b, 0, len);}fis.close();fos.close();System.out.println("復制完成");} } public class Test4 {public static void main(String[] args) throws IOException {BufferedInputStream bis = new BufferedInputStream(new FileInputStream("src/main/java/io/Test4.java"));BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.txt"));int len = 0;byte[] b = new byte[1024];while ((len = bis.read(b)) != -1) {bos.write(b, 0, len);}bis.close();bos.close();System.out.println("復制完成");} }

處理流之二:轉換流

  • 轉換流提供了在字節流和字符流之間的轉換。
  • Java API提供了兩個轉換流:

InputStreamReader 和 OutputStreamWriter

  • 字節流中的數據都是字符時,轉成字符流操作更高效。

InputStreamReader

  • 用于將字節流中讀取到的字節按指定字符集解碼成字符。需要和InputStream“套接”。
  • 構造方法:
    public InputStreamReader(InputStream in)
    public InputSreamReader(InputStream in,String charsetName)
    如:
    Reader isr = new InputStreamReader(System.in,”ISO5334_1”);

OutputStreamWriter

  • 用于將要寫入到字節流中的字符按指定字符集編碼成字節。需要和OutputStream“套接”。
  • 構造方法:
    public OutputStreamWriter(OutputStream os)
    public OutputSreamWriter(OutputStream os,String charsetName)

public void testMyInput() throws Exception {FileInputStream fis = new FileInputStream("dbcp.txt");FileOutputStream fos = new FileOutputStream("dbcp5.txt");InputStreamReader isr = new InputStreamReader(fis, "GBK");OutputStreamWriter osw = new OutputStreamWriter(fos, "GBK");BufferedReader br = new BufferedReader(isr);BufferedWriter bw = new BufferedWriter(osw);String str = null;while ((str = br.readLine()) != null) {bw.write(str);bw.newLine();bw.flush();}bw.close();br.close(); }

補充:字符編碼

  • 編碼表的由來

計算機只能識別二進制數據,早期由來是電信號。為了方便應用計算機,讓它可以識別各個國家的文字。就將各個國家的文字用數字來表示,并一一對應,形成一張表。這就是編碼表。

  • 常見的編碼表

ASCII:美國標準信息交換碼。用一個字節的7位可以表示。 ISO8859-1:拉丁碼表。歐洲碼表。用一個字節的8位表示。 GB2312:中國的中文編碼表。 GBK:中國的中文編碼表升級,融合了更多的中文文字符號。 Unicode:國際標準碼,融合了多種文字。所有文字都用兩個字節來表示,Java語言使用的就是unicode。 UTF-8:最多用三個字節來表示一個字符。

  • 編碼:字符串 → 字節數組
  • 解碼:字節數組 → 字符串
  • 轉換流的編碼應用

可以將字符按指定編碼格式存儲。 可以對文本數據按指定編碼格式來解讀。 指定編碼表的動作由構造器完成。

練習

將“你好”兩個字符查指定的utf-8的碼表,獲取對應的數字,并寫入到text.txt文件中。

public class Test {public static void main(String[] args) throws IOException {OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("text.txt"), "utf-8");osw.write("你好");osw.close();//讀取硬盤上的文件數據,將獲取到的數據查指定utf-8 的碼表來解析該數據。InputStreamReader isr = new InputStreamReader(new FileInputStream("text.txt"), "utf-8");char[] buf = new char[10];int num = isr.read(buf);String s = new String(buf, 0, num);System.out.println(s);//傳入編碼表的方法都會拋出不支持編碼異常(UnsupportedEncodingException);} }

處理流之三:標準輸入輸出流

  • System.in和System.out分別代表了系統標準的輸入和輸出設備。
  • 默認輸入設備是鍵盤,輸出設備是顯示器。
  • System.in的類型是InputStream。
  • System.out的類型是PrintStream,其是OutputStream的子類FilterOutputStream 的子類。
  • 通過System類的setIn,setOut方法對默認設備進行改變。 public static void setIn(InputStream in) public static void setOut(PrintStream out)

例題

從鍵盤輸入字符串,要求將讀取到的整行字符串轉成大寫輸出。然后繼續進行輸入操作,直至當輸入“e”或者“exit”時,退出程序。

public class Test {public static void main(String[] args) {System.out.println("請輸入信息(退出輸入e或exit):");//把"標準"輸入流(鍵盤輸入)這個字節流包裝成字符流,再包裝成緩沖流BufferedReader br = new BufferedReader(new InputStreamReader(System.in));String s = null;try {while ((s = br.readLine()) != null) { //讀取用戶輸入的一行數據 --> 阻塞程序if (s.equalsIgnoreCase("e") || s.equalsIgnoreCase("exit")) {System.out.println("安全退出!!");break;}//將讀取到的整行字符串轉成大寫輸出System.out.println("-->:" + s.toUpperCase());System.out.println("繼續輸入信息");}} catch (IOException e) {e.printStackTrace();} finally {try {if (br != null) {br.close(); //關閉過濾流時,會自動關閉它包裝的底層節點流}} catch (IOException e) {e.printStackTrace();}}} }

或者

public class Test5 {public static void main(String[] args) {Scanner input = new Scanner(System.in);System.out.println("請輸入字符串:");while (input.hasNext()) {String line = input.nextLine();if ("e".equals(line) || "exit".equals(line)) {System.exit(0);}String upperStr = line.toUpperCase();System.out.println(upperStr);}} }

處理流之四:打印流(了解)

  • 在整個IO包中,打印流是輸出信息最方便的類。
  • PrintStream(字節打印流)和PrintWriter(字符打印流)。

提供了一系列重載的print和println方法,用于多種數據類型的輸出。 PrintStream和PrintWriter的輸出不會拋出異常。 PrintStream和PrintWriter有自動flush功能。 System.out返回的是PrintStream的實例。

public class Test {public static void main(String[] args) {FileOutputStream fos = null;try {fos = new FileOutputStream(new File("D:\\IO\\text.txt"));} catch (FileNotFoundException e) {e.printStackTrace();}//創建打印輸出流,//設置為自動刷新模式(寫入換行符或字節 '\n' 時都會刷新輸出緩沖區)PrintStream ps = new PrintStream(fos, true);if (ps != null) { // 把標準輸出流(控制臺輸出)改成文件System.setOut(ps);}for (int i = 0; i <= 255; i++) { //輸出ASCII字符System.out.print((char) i);if (i % 50 == 0) { //每50個數據一行System.out.println(); // 換行}}ps.close();} }

處理流之五:數據流(了解)

  • 為了方便地操作Java語言的基本數據類型的數據,可以使用數據流。
  • 數據流有兩個類:(用于讀取和寫出基本數據類型的數據)

DataInputStream 和 DataOutputStream
分別“套接”在 InputStream 和 OutputStream 節點流上。

  • DataInputStream中的方法:

boolean readBoolean()
char readChar()
float readFloat()
double readDouble()
byte readByte()
short readShort()
int readInt()
long readLong()
String readUTF()
void readFully(byte[] b)

  • DataOutputStream中的方法

將上述的方法的read改為相應的write即可。

public class Test {public static void main(String[] args) {DataOutputStream dos = null;try {//創建連接到指定文件的數據輸出流對象dos = new DataOutputStream(new FileOutputStream("d:\\IOTest\\destData.dat"));dos.writeUTF("ab中國"); //寫UTF字符串dos.writeBoolean(false); //寫入布爾值dos.writeLong(1234567890L); //寫入長整數System.out.println("寫文件成功!");} catch (IOException e) {e.printStackTrace();} finally { //關閉流對象try {if (dos != null) {// 關閉過濾流時,會自動關閉它包裝的底層節點流dos.close();}} catch (IOException e) {e.printStackTrace();}}} }

處理流之六:對象流

  • ObjectInputStream 和 OjbectOutputSteam

用于存儲和讀取對象的處理流。它的強大之處就是可以把Java中的對象寫入到數據源中,也能把對象從數據源中還原回來。

  • 序列化(Serialize):用ObjectOutputStream類將一個Java對象寫入IO流中。
  • 反序列化(Deserialize):用ObjectInputStream類從IO流中恢復該Java對象。

ObjectOutputStream和ObjectInputStream不能序列化static和transient修飾的成員變量。

對象的序列化

  • 對象序列化機制允許把內存中的Java對象轉換成平臺無關的二進制流,從而允許把這種二進制流持久地保存在磁盤上,或通過網絡將這種二進制流傳輸到另一個網絡節點。當其它程序獲取了這種二進制流,就可以恢復成原來的Java對象
  • 序列化的好處在于可將任何實現了Serializable接口的對象轉化為字節數據,使其在保存和傳輸時可被還原
  • 序列化是 RMI(Remote Method Invoke – 遠程方法調用)過程的參數和返回值都必須實現的機制,而 RMI 是 JavaEE 的基礎。因此序列化機制是 JavaEE 平臺的基礎
  • 如果需要讓某個對象支持序列化機制,則必須讓其類是可序列化的,為了讓某個類是可序列化的,該類必須實現如下兩個接口之一:

Serializable
Externalizable

  • 凡是實現Serializable接口的類都有一個表示序列化版本標識符的靜態變量: private static final long serialVersionUID;

serialVersionUID用來表明類的不同版本間的兼容性。 如果類沒有顯示定義這個靜態變量,它的值是Java運行時環境根據類的內部細節自動生成的。若類的源代碼作了修改,serialVersionUID 可能發生變化。故建議,顯示聲明。

  • 顯示定義serialVersionUID的用途:

希望類的不同版本對序列化兼容,因此需確保類的不同版本具有相同的serialVersionUID。 不希望類的不同版本對序列化兼容,因此需確保類的不同版本具有不同的serialVersionUID。

使用對象流序列化對象

  • 若某個類實現了 Serializable 接口,該類的對象就是可序列化的:

創建一個 ObjectOutputStream。
調用 ObjectOutputStream對象的writeObject()方法輸出可序列化對象。
注意寫出一次,操作flush()。

  • 反序列化

創建一個 ObjectInputStream。
調用 readObject() 方法讀取流中的對象。

  • 強調:如果某個類的字段不是基本數據類型或 String 類型,而是另一個引用類型,那么這個引用類型必須是可序列化的,否則擁有該類型的 Field 的類也不能序列化。
class Person implements Serializable {private static final long serialVersionUID = 4911899814118879158L;private String name;private int age;public Person(String name, int age) {this.name = name;this.age = age;} }public class Test {public static void main(String[] args) throws Exception {//序列化:將對象寫入到磁盤或者進行網絡傳輸。 要求對象必須實現序列化。ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("test3.txt"));Person p = new Person("韓梅梅", 18);oos.writeObject(p);oos.flush();oos.close();//反序列化:將磁盤中的對象數據源讀出。ObjectInputStream ois = new ObjectInputStream(new FileInputStream("test3.txt"));Person p1 = (Person) ois.readObject();System.out.println(p1.toString());ois.close();} }

RandomAccessFile 類

  • RandomAccessFile 類支持 “隨機訪問” 的方式,程序可以直接跳到文件的任意地方來讀、寫文件。

支持只訪問文件的部分內容。
可以向已存在的文件后追加內容。

  • RandomAccessFile 對象包含一個記錄指針,用以標示當前讀寫處的位置。RandomAccessFile 類對象可以自由移動記錄指針:

long getFilePointer():獲取文件記錄指針的當前位置。 void seek(long pos):將文件記錄指針定位到 pos 位置。

  • 構造器

public RandomAccessFile(File file, String mode)
public RandomAccessFile(String name, String mode)

  • 創建 RandomAccessFile 類實例需要指定一個 mode 參數,該參數指定 RandomAccessFile 的訪問模式:

r: 以只讀方式打開。
rw:打開以便讀取和寫入。
rwd:打開以便讀取和寫入;同步文件內容的更新。
rws:打開以便讀取和寫入;同步文件內容和元數據的更新。

讀取文件內容

public class Test {public static void main(String[] args) throws Exception {RandomAccessFile raf = new RandomAccessFile("test.txt", "rw");raf.seek(5);byte[] b = new byte[1024];int off = 0;int len = 5;raf.read(b, off, len);String str = new String(b, 0, len);System.out.println(str);raf.close();} }

寫入文件內容

public class Test {public static void main(String[] args) throws Exception {RandomAccessFile raf = new RandomAccessFile("test.txt", "rw");raf.seek(5);//先讀出來String temp = raf.readLine();raf.seek(5);raf.write("xyz".getBytes());raf.write(temp.getBytes());raf.close();} }

流的基本應用小節

  • 流是用來處理數據的。
  • 處理數據時,一定要先明確數據源,與數據目的地。

數據源可以是文件,可以是鍵盤。
數據目的地可以是文件、顯示器或者其他設備。

  • 而流只是在幫助數據進行傳輸,并對傳輸的數據進行處理,比如過濾處理、轉換處理等。

  • 字節流-緩沖流(重點)

輸入流:InputStream、FileInputStream、BufferedInputStream
輸出流:OutputStream、FileOutputStream、BufferedOutputStream

  • 字符流-緩沖流(重點)

輸入流:Reader、FileReader、BufferedReader
輸出流:Writer、FileWriter、BufferedWriter

  • 轉換流(字節流轉換為字符流)

InputSteamReader、OutputStreamWriter

  • 對象流(難點)

序列化:ObjectInputStream
反序列化:ObjectOutputStream

  • 隨機存取流(掌握讀取、寫入)

RandomAccessFile

轉載于:https://my.oschina.net/mondayer/blog/3027711

總結

以上是生活随笔為你收集整理的第10章 流的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。