java 流的概念_举例讲解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 +
'}';
}
}
}
這個例子里面看不到字節和字符的讀寫,因為這兩個類都包裝好了。上面只是一個簡單的例子,序列化要寫好的話還是有不少講究的。想深入了解序列化,可以看看這里。本文只關注跟流有關的部分。其實序列化用的很少,因為序列化降低了靈活性,所以可以不用的話一般都不會用。
總結
以上是生活随笔為你收集整理的java 流的概念_举例讲解Java中的Stream流概念的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 原神夏祭游鱼食谱怎么获得?
- 下一篇: 请问大家一个小小的问题,治疗灰指甲要多少