程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 舉例解說Java中的Stream流概念

舉例解說Java中的Stream流概念

編輯:關於JAVA

舉例解說Java中的Stream流概念。本站提示廣大學習愛好者:(舉例解說Java中的Stream流概念)文章只能為提供參考,不一定能成為您想要的結果。以下是舉例解說Java中的Stream流概念正文


1、根本的輸出流和輸入流
流是 Java 中最重要的根本概念之一。文件讀寫、網絡收發、進程通訊,簡直一切需求輸出輸入的中央,都要用到流。

流是做什麼用的呢?就是做輸出輸入用的。為什麼輸出輸入要用“流”這種方式呢?由於順序輸出輸入的根本單位是字節,輸出就是獲取一串字節,輸入就是發送一串字節。但是很多狀況下,順序不能夠接納一切的字節之後再停止處置,而是接納一點處置一點。比如你下載魔獸世界,不能夠全部下載到內存裡再保管到硬盤上,而是下載一點就保管一點。這時,流這種方式就十分合適。

在 Java 中,每個流都是一個對象。流分為兩種:輸出流(InputStream)和輸入流(OutputStream)。關於輸出流,你只需從流當中不停地把字節取出來就是了;而關於輸入流,你只需把預備好的字節串傳給它就行。

流對象是怎樣取得的呢?不同的內部零碎,獲取流的方式也不同。例如,文件讀寫就要創立 FileInputStream/FileOutputStream 對象,而網絡通訊是經過 Socket 對象來獲取輸出輸入流的。普通來說,假如一個類有 getInputStream() 或 getOutputStream() 這樣的辦法,就標明它是經過流對象來停止輸出輸入的。

InputStream 是輸出流,上面是一個經過 InputStream 讀取文件的例子:

import java.io.File; 
import java.io.FileInputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.FileNotFoundException; 
import java.util.Arrays; 
 
/** 
 * 經過流讀取文件 
 */ 
public class ReadFileDemo { 
 
 // 順序入口 
 public static void main(String[] args) { 
  String path = "c:/boot.ini"; 
  File file = new File(path); 
 
  // 創立輸出流 
  InputStream is; 
  try { 
   is = new FileInputStream(file); 
  } catch (FileNotFoundException e) { 
   System.err.println("文件 " + path + " 不存在。"); 
   return; 
  } 
 
  // 開端讀取 
  byte[] content = new byte[0];  // 保管讀取出來的文件內容 
  byte[] buffer = new byte[10240]; // 定義緩存 
 
  try { 
   int eachTime = is.read(buffer); // 第一次讀取。假如前往值為 -1 就表示沒有內容可讀了。 
   while (eachTime != -1) { 
    // 讀取出來的內容放在 buffer 中,如今將其兼並到 content。 
    content = concatByteArrays(content, buffer, eachTime); 
    eachTime = is.read(buffer); // 持續讀取 
   } 
  } catch (IOException e) { 
   System.err.println("讀取文件內容失敗。"); 
   e.printStackTrace(); 
  } finally { 
   try { 
    is.close(); 
   } catch (IOException e) { 
    // 這裡的異常可以疏忽不處置 
   } 
  } 
 
  // 輸入文件內容 
  String contentStr = new String(content); 
  System.out.println(contentStr); 
 } 
 
 /** 
  * 兼並兩個字節串 
  * 
  * @param bytes1  字節串1 
  * @param bytes2  字節串2 
  * @param sizeOfBytes2 需求從 bytes2 中取出的長度 
  * 
  * @return bytes1 和 bytes2 中的前 sizeOfBytes2 個字節兼並後的後果 
  */ 
 private static byte[] concatByteArrays(byte[] bytes1, byte[] bytes2, int sizeOfBytes2) { 
  byte[] result = Arrays.copyOf(bytes1, (bytes1.length + sizeOfBytes2)); 
  System.arraycopy(bytes2, 0, result, bytes1.length, sizeOfBytes2); 
  return result; 
 } 
} 

雖然寫得很啰嗦,但這的確是 InputStream 的根本用法。留意,這只是一個例子,闡明如何從輸出流中讀取字節串。實踐上,Java 提供更復雜的方式來讀取文本文件。當前將會引見。

相比從流中讀取,運用 OutputStream 輸入則是十分復雜的事情。上面是一個例子:

import java.io.OutputStream; 
import java.io.FileOutputStream; 
import java.io.File; 
import java.io.IOException; 
import java.util.Date; 
 
/** 
 * 將以後日期保管到文件 
 */ 
public class SaveFileDemo { 
 
 public static void main(String[] args) throws IOException { 
  String path = "c:/now.txt"; 
 
  File file = new File(path); 
  if (!file.exists() && !file.createNewFile()) { 
   System.err.println("無法創立文件。"); 
   return; 
  } 
 
  OutputStream os = new FileOutputStream(file); // 創立輸入流(前提是文件存在) 
  os.write(new Date().toString().getBytes());  // 將以後時間寫入文件 
  os.close();          // 必需封閉流,內容才會寫入文件。 
  System.out.println("文件寫入完成。"); 
 } 
} 


Java 還提供其它的流操作方式,但它們都是對 InputStream 和 OutputStream 停止擴展或包裝。所以這兩個類是根底,必需要了解它們的運用。

2、Reader 和 Writer
引見了 InputStream 和 OutputStream,接上去引見 Reader 和 Writer。這兩個類其實就是將 InputStream 和 OutputStream 包裝了一下。不過它們處置的不是字節(byte),而是字符(char)。假如一個流當中的內容都是文本,那麼用 Reader/Writer 處置起來會復雜些。上面是一個用 Reader 讀取文本文件的例子:

import java.io.FileReader; 
import java.io.IOException; 
import java.io.Reader; 
 
/** 
 * 讀取文本文件 
 */ 
public class ReadTextFileDemo { 
 
 // 順序入口 
 public static void main(String[] args) { 
  String path = "c:/boot.ini"; 
  String content = ""; 
 
  try { 
   Reader reader = new FileReader(path); 
   char[] buffer = new char[10240]; 
   int count; 
 
   while ((count = reader.read(buffer)) != -1) { 
    content += new String(buffer, 0, count); 
   } 
  } catch (IOException e) { 
   System.err.println("讀取文件失敗。"); 
   e.printStackTrace(); 
  } 
 
  System.out.println(content); 
 } 
 
} 

至於如何用 Writer 將文本內容寫入文件,這裡就不給出例子了,看官自己試著寫一下吧。

下面這個例子,依然不是讀取文本文件最常用的方式。Java 提供 BufferedReader,我們通常用它來讀取文本文件。上面是一個例子:

import java.io.BufferedReader; 
import java.io.FileReader; 
import java.io.IOException; 
 
/** 
 * 用 BufferedReader 讀取文本文件 
 */ 
public class ReadTextDemo2 { 
 
 public static void main(String[] args) { 
  String path = "c:/boot.ini"; 
  String content = ""; 
 
  try { 
   BufferedReader reader = new BufferedReader(new FileReader(path)); 
   String line; 
   while ((line = reader.readLine()) != null) { 
    content += line + "/n"; 
   } 
  } catch (IOException e) { 
   System.err.println("讀取文件失敗。"); 
   e.printStackTrace(); 
  } 
 
  System.out.println(content); 
 } 
} 

3、對象序列化
對象序列化也是流使用的一個重要方面。序列化就是把一個對象轉換成一串字節,既可以保管起來,也可以傳給另外的 Java 順序運用。ObjectOutputStream 和 ObjectInputStream 就是專門用來停止序列化和反序列化的。上面就是一個復雜的例子:

import java.io.ObjectOutputStream; 
import java.io.FileOutputStream; 
import java.io.File; 
import java.io.IOException; 
import java.io.Serializable; 
import java.io.ObjectInputStream; 
import java.io.FileInputStream; 
import java.io.EOFException; 
  
/** 
 * ObjectOutputStream/ObjectInputStream 示例。 
 * 這兩個類辨別用於序列化和反序列化。 
 */ 
public class SerializationDemo { 
  
  public static void main(String[] args) throws Exception { 
    String path = "c:/persons.data"; 
    File f = new File(path); 
    if (!f.exists()) { 
      f.createNewFile(); 
    } 
  
    writePersons(path); 
    readPersons(path); 
  } 
  
  // 從指定的文件中讀取 Person 對象 
  private static void readPersons(String path) throws IOException, ClassNotFoundException { 
    ObjectInputStream ois = new ObjectInputStream(new FileInputStream(path)); 
  
    Person p; 
    while (true) { 
      try { 
        p = (Person) ois.readObject(); 
        System.out.println(p); 
      } catch (EOFException e) { 
        break; 
      } 
    } 
  } 
  
  // 將 Person 對象保管到指定的文件中 
  private static void writePersons(String path) throws IOException { 
    Person[] persons = new Person[]{ 
        new Person("張三", 23), 
        new Person("李四", 24) 
    }; 
  
    ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(path)); 
    for (Person person : persons) { 
      oos.writeObject(person); 
    } 
    oos.close(); 
  } 
  
  /////////////////////////////////////////////////////////// 
  
  private static class Person implements Serializable { 
  
    private String name; 
  
    private int age; 
  
    public Person() { 
    } 
  
    public Person(String name, int age) { 
      this.name = name; 
      this.age = age; 
    } 
  
    public String getName() { 
      return name; 
    } 
  
    public void setName(String name) { 
      this.name = name; 
    } 
  
    public int getAge() { 
      return age; 
    } 
  
    public void setAge(int age) { 
      this.age = age; 
    } 
  
    @Override 
    public String toString() { 
      return "Person{" + 
          "name='" + name + '/'' + 
          ", age=" + age + 
          '}'; 
    } 
  } 
} 

這個例子外面看不到字節和字符的讀寫,由於這兩個類都包裝好了。下面只是一個復雜的例子,序列化要寫好的話還是有不少考究的。想深化理解序列化,可以看看這裡。本文只關注跟流有關的局部。其實序列化用的很少,由於序列化降低了靈敏性,所以可以不必的話普通都不會用。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved