欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

目錄

柚子快報(bào)激活碼778899分享:【Java】I/O 操作詳解

柚子快報(bào)激活碼778899分享:【Java】I/O 操作詳解

http://yzkb.51969.com/

??個(gè)人主頁(yè):island1314

?? ?歡迎關(guān)注:?點(diǎn)贊 ??留言 ?收藏 ?? ? ?

目錄

1. 引言 ?

2. File?類 ?

2.1 創(chuàng)建 File?對(duì)象

2.2 File 類的常用方法

2.3 遍歷目錄下的文件

2.4 刪除文件及目錄

3. 字節(jié)流 ?

3.1 基本概念

3.2 字節(jié)流讀文件

3.3 字節(jié)流寫文件

3.4 字節(jié)流復(fù)制文件

4. 字符流 ?

4.1 字符流定義及基本用法

4.2 字符流讀文件

4.3 字符流寫文件

4.4 數(shù)據(jù)編碼解碼問(wèn)題

5. 轉(zhuǎn)換流 ?

6. 緩沖流 ?

6.1 字節(jié)緩沖流

6.2 字符緩沖流

7. 序列化反序列化 ?

8. 小結(jié) ?

1. 引言 ?

?I/O 操作主要是指 使用 Java 程序完成輸入(Input)、輸出(Output) 操作。輸入是指將文件內(nèi)容以數(shù)據(jù)流的形式讀入內(nèi)存,輸出是指通過(guò) Java 程序?qū)?nèi)容中的數(shù)據(jù)寫入文件,輸入輸出操作在實(shí)際開(kāi)發(fā)中比較廣泛。

IO:輸入/輸出(Input/Output)流:是一種抽象概念,是對(duì)數(shù)據(jù)傳輸?shù)目偡Q.也就是說(shuō)數(shù)據(jù)在設(shè)備間的傳輸稱為流,流的本質(zhì)是數(shù)據(jù)傳輸IO流就是用來(lái)處理設(shè)備間數(shù)據(jù)傳輸問(wèn)題的.常見(jiàn)的應(yīng)用: 文件復(fù)制; 文件上傳; 文件下載

IO流的分類:

(1)按照數(shù)據(jù)的流向

輸入流:讀數(shù)據(jù)輸出流:寫數(shù)據(jù)

(2)按照數(shù)據(jù)類型來(lái)分:

字節(jié)流

字節(jié)輸入流字節(jié)輸出流字符流

字符輸入流字符輸出流

IO流的使用場(chǎng)景

如果操作的是純文本文件,優(yōu)先使用字符流如果操作的是圖片、視頻、音頻等二進(jìn)制文件,優(yōu)先使用字節(jié)流如果不確定文件類型,優(yōu)先使用字節(jié)流,字節(jié)流是萬(wàn)能的流

2. File?類 ?

java.io 包中的?File 類?是唯一一個(gè)可以代表磁盤文件的對(duì)象,它定義了一些用于操作文件的方法。通過(guò)調(diào)用?File 類?提供的各種方法,可以創(chuàng)建、刪除或者重命名文件,判斷硬盤上某個(gè)文件是否存在,查詢文件最后修改時(shí)間,等等。本節(jié)將針對(duì)File 類?進(jìn)行詳細(xì)講解。創(chuàng)建File對(duì)象

2.1 創(chuàng)建 File?對(duì)象

File 類?提供了多個(gè)構(gòu)造方法用于創(chuàng)建?File?對(duì)象。File 類?的常用構(gòu)造方法如下所示:

方法聲明功能描述FILE(String pathname)通過(guò)指定的 一個(gè)字符串類型的文件路徑?創(chuàng)建一個(gè) FILE 對(duì)象FILE(String parent, String child)根據(jù)指定的?一個(gè)字符串類型的父路徑和一個(gè)字符串類型的子路徑(包括文件名稱)創(chuàng)建一個(gè) FILE 對(duì)象FILE (FILE parent, String child)根據(jù)指定的?一個(gè)FILE 類的父路徑和一個(gè)字符串類型的子路徑(包括文件名稱)創(chuàng)建一個(gè) FILE 對(duì)象

所有的構(gòu)造方法都需要傳入文件路徑,那么我們應(yīng)該如何去用呢?

如果程序只處理一個(gè)目錄和文件,并且知道該目錄或文件的路徑,就建議使用 構(gòu)造 1如果程序處理的是一個(gè)公共目錄中的若干子目錄或文件,就建議使用 構(gòu)造 2 和 構(gòu)造 3

案例:

public static void main(String[] args) {

// 方法一:通過(guò)絕對(duì)路徑創(chuàng)建

File f1 = new File("D:\\file\\a.txt");

// 方法二:通過(guò)相對(duì)路徑創(chuàng)建

File f2 = new File("src\\Hello.txt");

}

注:目錄符號(hào)(\) 用 \\ 表示,因?yàn)?\ 在Java中是特殊字符,具有轉(zhuǎn)義作用,因此用 \\ 表示,此外我們也可以用 / 來(lái)作目錄符號(hào)。

2.2 File 類的常用方法

方法聲明功能描述boolean exists()判定 File? 對(duì)象對(duì)應(yīng)的文件或目錄是否存在boolean delete()刪除 File? 對(duì)象對(duì)應(yīng)的文件或目錄boolean createNewFile()當(dāng) File 對(duì)象對(duì)應(yīng)文件不存在時(shí)則創(chuàng)建新文件,并且將新建的 File 對(duì)象指向新文件String getName()?返回 File 對(duì)象 表示的文件或目錄的名稱String getPath()?返回 File 對(duì)象 表示的文件或目錄的路徑String getAbsolutePath()? 返回 File 對(duì)象 表示的文件或目錄的相對(duì)路徑

在 UNIX / Linux 等系統(tǒng)上,如果路徑以 斜線 / 開(kāi)始,則這個(gè)路徑為絕對(duì)路徑在 Widows?等系統(tǒng)上,如果路徑以 盤符?開(kāi)始,則這個(gè)路徑為絕對(duì)路徑String getParentFile()?返回 File 對(duì)象 對(duì)應(yīng)目錄的父目錄(注:返回的目錄不包含最后一級(jí)子目錄)boolean canRead()判定 File? 對(duì)象對(duì)應(yīng)的文件或目錄是否可讀boolean canWrite()判定 File? 對(duì)象對(duì)應(yīng)的文件或目錄是否可寫boolean isFile()判斷 File 對(duì)象對(duì)應(yīng)的是否是文件boolean isDirectory()判斷 File 對(duì)象對(duì)應(yīng)的是否是目錄boolean isAbsolute()判斷 File 對(duì)象對(duì)應(yīng)的是否是絕對(duì)路徑long lastModified()返回 1970 年 1 月 1 日 0 時(shí) 0 分 0 秒 到文件最后修改時(shí)間的 毫秒值long length()返回文件內(nèi)容的長(zhǎng)度(注:?jiǎn)挝粸?字節(jié))String[] list()遞歸列出指定目錄的全部?jī)?nèi)容(包括子目錄和文件),只列出名稱File[] listFiles()返回一個(gè)包含 File 對(duì)象所有子文件和子目錄的 File 數(shù)組

演示:

public static void main(String[] args) {

File file = new File("src/test.txt"); // / 也可以作 目錄符號(hào)

System.out.println("文件是否存在:" + file.exists());

System.out.println("文件名:" + file.getName());

// ... 具體大家自己可以實(shí)踐

}

補(bǔ)充學(xué)習(xí):?createTempFile() 方法 和 deleteOnExit() 方法

在一些特定情況下,程序需要讀寫一些臨時(shí)文件,為此,F(xiàn)ile類提供了createTempFile() 方法 和 deleteOnExit() 方法,用于操作臨時(shí)文件。createTempFile() 方法用于創(chuàng)建一個(gè)臨時(shí)文件,deleteOnExit()?方法在Java虛擬機(jī)退出時(shí)自動(dòng)刪除臨時(shí)文件。

下面通過(guò)一個(gè)案例演示這兩個(gè)方法的使用:

public static void main(String[] args) throws IOException {

// 提供臨時(shí)文件的前綴和擴(kuò)展名

File file = File.createTempFile("itcast-", ".txt");

file.deleteOnExit(); // java 虛擬機(jī)退出時(shí) 自動(dòng)刪除文件 file

System.out.println("file 是否為文件:" + file.isFile());

System.out.println("file 的相對(duì)路徑:" + file.getPath());

}

2.3 遍歷目錄下的文件

File 類中提供了 list()方法,可以獲取目錄下所有文件和目錄的名稱。獲取目錄下所有文件和目錄名稱后,可以通過(guò)這些名稱遍歷目錄下的文件,按照調(diào)用方法的不同,對(duì)目錄下的文件遍歷可分為以下3種方式。

遍歷指定目錄下的所有文件遍歷指定目錄下指定擴(kuò)展名的文件遍歷包括子目錄中的文件在內(nèi)的所有文件

下面分別對(duì)這3種遍歷方式進(jìn)行詳細(xì)講解。

(1)遍歷指定目錄下的所有文件

File 類的 list()方法可以遍歷指定目錄下的所有文件。下面通過(guò)一個(gè)案例演示如何使用?list()方法遍歷目錄下的所有文件,如下:

public static void main(String[] args) {

File file = new File("src/IO");

if(file.isDirectory()) {

String[] names = file.list(); // 獲取目錄下所有文件的文件名

for(String name:names) {

System.out.println(name); //輸出文件名

}

}

}

(2)遍歷指定目錄下指定擴(kuò)展名的文件 ? 上述代碼實(shí)現(xiàn)了遍歷一個(gè)目錄下所有文件的功能,然而有時(shí)程序只需要獲取指定類型的文件,如獲取指定目錄下所有擴(kuò)展名為“.java”的文件。

針對(duì)這種需求,F(xiàn)ile類提供了一個(gè)重載的 list()方法,該方法接收一個(gè) FilenameFilter 類型的參數(shù)。FilenameFilter 是一個(gè)接口,被稱作文件過(guò)濾器,其中定義了抽象方法accept()用于依次對(duì)指定File的所有子目錄或文件進(jìn)行迭代。在調(diào)用list()方法時(shí),需要實(shí)現(xiàn) FilenameFilter,并在accept()方法中進(jìn)行篩選,從而獲得指定類型的文件。

下面通過(guò)一個(gè)案例演示如何遍歷指定目錄下所有擴(kuò)展名為“.java”的文件,如下:

public static void main(String[] args) {

File file = new File("src/IO");

// 創(chuàng)建文件過(guò)濾器對(duì)象

FilenameFilter filter = new FilenameFilter() {

// 實(shí)現(xiàn) accept 方法

@Override

public boolean accept(File dir, String name) {

File currFile = new File(dir, name);

// 如果文件以 .java 結(jié)尾返回true

if(currFile.isFile() && name.endsWith(".java")){

return true;

}

else return false;

}

};

if(file.exists()) {

String[] lists = file.list(); // 獲取目錄下所有文件的文件名

for(String name:lists) {

System.out.println(name); //輸出文件名

}

}

}

(3)遍歷包括子目錄下的文件在內(nèi)的所有文件 ? 前面的兩個(gè)例子演示的都是遍歷當(dāng)前目錄下的文件。有時(shí)候在一個(gè)目錄下,除了文件,還有子目錄,如果想獲取所有子目錄下的文件,list()方法顯然不能滿足要求,這時(shí)可以使用File 類提供的另一個(gè)方法—— listFiles()。

? 該方法返回一個(gè)File對(duì)象數(shù)組,當(dāng)對(duì)數(shù)組中的元素進(jìn)行遍歷時(shí),如果元素中還有子目錄需要遍歷,則可以遞歸遍歷子目錄。下面通過(guò)一個(gè)案例演示包括子目錄文件的所有文件的遍歷,如下:

public static void main(String[] args) {

// 創(chuàng)建一個(gè)代表目錄的 File 對(duì)象

File file = new File("src");

fileDir(file);

}

public static void fileDir(File dir)

{

File[] files = dir.listFiles(); // 獲得表示目錄下的所有文件數(shù)組

for(File file :files) // 遍歷所有子目錄和文件

{

if(file.isDirectory()){

fileDir(file); // 如果是目錄則遞歸調(diào)用

}

System.out.println(file.getAbsolutePath()); // 獲取文件的絕對(duì)路徑

}

}

2.4 刪除文件及目錄

?在操作文件時(shí),可能會(huì)遇到需要?jiǎng)h除一個(gè)目錄下某個(gè)文件或刪除整個(gè)目錄的操作,這時(shí)就可以調(diào)用File 類中的 delete() 方法。

public static void main(String[] args) {

File file = new File("src/IO");

if(file.exists()){

System.out.println(file.delete());

}

}

// 輸出

false

為啥會(huì)輸出 false 呢?

?因?yàn)槲募h除失敗了,F(xiàn)ile 類中的 delete() 方法只能刪除一個(gè)指定的文件,假如 File 對(duì)象代表一個(gè)目錄,而且這個(gè)目錄下包含子目錄或文件,則?File 類中的 delete() 方法 時(shí)不允許刪除整個(gè)目錄的。 此時(shí)就需要采用遞歸的方法來(lái)全部刪除

public static void main(String[] args) {

File file = new File("src/IO");

deleteDir(file);

System.out.println("刪除成功??!");

}

public static void deleteDir(File dir)

{

if(dir.exists())

{

File[] files = dir.listFiles(); // 獲得表示目錄下的所有文件數(shù)組

for(File file :files) // 遍歷所有子目錄和文件

{

if(file.isDirectory()){

deleteDir(file); // 如果是目錄則遞歸調(diào)用

}

else file.delete();// 如果是文件直接刪除

}

// 刪除整個(gè)目錄下的所有文件之后,就刪除這個(gè)目錄

dir.delete();

}

}

注意:

刪除目錄是從 Java 虛擬機(jī)直接刪除而不放入到回收站,文件一旦被刪除就無(wú)法恢復(fù),因此在進(jìn)行文件刪除操作的時(shí)候需要格外小心!?

3. 字節(jié)流 ?

3.1 基本概念

? 在程序的開(kāi)發(fā)中,經(jīng)常需要處理設(shè)備之間的數(shù)據(jù)傳輸,而在計(jì)算機(jī)中,無(wú)論是文本,圖片、音頻還是視頻,所有文件都是以二進(jìn)制(字節(jié))形式存在的。對(duì)于字節(jié)的輸入輸出,I/0 系統(tǒng)提供了一系列流,統(tǒng)稱為字節(jié)流。字節(jié)流是程序中最常用的流,根據(jù)數(shù)據(jù)的傳輸方向可將其分為字節(jié)輸入流和字節(jié)輸出流。 ? JDK 提供了兩個(gè)抽象類—— InputStream?和 OutputStream?,它們是字節(jié)流的頂級(jí)父類,所有的字節(jié)輸入流都繼承?InputStream?,所有的字節(jié)輸出流都繼承?OutputStream?。

字節(jié)流抽象基類

InputStream:這個(gè)抽象類是表示字節(jié)輸入流的所有類的超類OutputStream:這個(gè)抽象類是表示字節(jié)輸出流的所有類的超類子類名特點(diǎn):子類名稱都是以其父類名作為子類名的后綴字節(jié)輸出流

FileOutputStream(String name):創(chuàng)建文件輸出流以指定的名稱寫入文件

?注: I/O 流的輸入輸出是相對(duì)于 程序而言的

InputStream 類常用方法

方法聲明功能描述int read()從輸入流讀取一字節(jié)(8位), 把它轉(zhuǎn)化位 0 - 255 的整數(shù),并返回這個(gè)整數(shù)int read (byte[ ] b)從輸入流讀取若干字節(jié),把它們保存到參數(shù) b? 指定的字節(jié)數(shù)組中,返回的整數(shù)表示讀取的字節(jié)數(shù)int read (byte[ ] b, int off, int len)從輸入流讀取若干字節(jié),把它們保存到參數(shù) b? 指定的字節(jié)數(shù)組中,off指定字節(jié)數(shù)組保存數(shù)據(jù)的起始索引,len 表示讀取的字節(jié)數(shù)void close()關(guān)閉輸入流并且釋放與其相關(guān)的所有系統(tǒng)資源

上表中的3個(gè) read()?方法都是用來(lái)讀數(shù)據(jù)的。其中:

第一個(gè) read()?方法是從輸入流中逐個(gè)讀入字節(jié);而第二個(gè)和第三個(gè)read()方法則可以將若干字節(jié)以字節(jié)數(shù)組的形式一次性讀入,從而提高讀數(shù)據(jù)的效率。在進(jìn)行 I/O?操作時(shí),當(dāng)前 I/O 流會(huì)占用一定的內(nèi)存,由于系統(tǒng)資源非常寶貴,因此,在I/0操作結(jié)束后,應(yīng)該調(diào)用close()方法關(guān)閉 I/O 流,從而釋放當(dāng)前 I/O 流 所占的系統(tǒng)資源。

OutputStream 類常用方法

方法聲明功能描述void write(int b)將指定的字節(jié)寫入此文件輸出流,一次寫一個(gè)字節(jié)數(shù)據(jù)void write(byte[] b)將參數(shù) b指定的字節(jié)數(shù)組的所有字節(jié)寫入到此文件輸出流,一次寫一個(gè)字節(jié)數(shù)組數(shù)據(jù)void write(byte[] b, int off, int len)將指定 byte 數(shù)組從偏移量off(起始索引)開(kāi)始的 len字節(jié)寫入此文件輸出流?void flush()刷新輸出流并且強(qiáng)制寫出所有緩沖的輸出字節(jié)void close()關(guān)閉輸出流并且釋放與其關(guān)聯(lián)的所有系統(tǒng)資源

?上表前3個(gè)是重載的write()方法,都用于向輸出流寫入字節(jié)。

其中,第一個(gè)write()方法逐個(gè)寫入字節(jié);后兩個(gè)write()方法將若干字節(jié)以字節(jié)數(shù)組的形式一次性寫人,從而提高寫數(shù)據(jù)的效率。flush()方法用來(lái)將當(dāng)前輸出流緩沖區(qū)(通常是字節(jié)數(shù)組)中的數(shù)據(jù)強(qiáng)制寫入目標(biāo)設(shè)備,此過(guò)程稱為刷新。close()方法用來(lái)關(guān)閉1/0流并釋放與當(dāng)前1/0流相關(guān)的系統(tǒng)資源。

InputStream?和 OutputStream 這兩個(gè)類雖然提供了一系列和讀寫數(shù)據(jù)有關(guān)的方法,但是這兩個(gè)類是抽象類,不能被實(shí)例化,因此,針對(duì)不同的功能, InputStream?類?和 OutputStream 類提供了不同的子類,形成了體系結(jié)構(gòu),如下圖:

InputStream 體系結(jié)構(gòu)圖:

OutputStream 體系結(jié)構(gòu)圖:

3.2 字節(jié)流讀文件

里InputStream?就是JDK提供的基本輸入流,它是所有輸入流的父類,F(xiàn)ileInputStream?是InputStream?的子類,它是操作文件的字節(jié)輸入流,專門用于讀取文件中的數(shù)據(jù)。因?yàn)閺奈募x取數(shù)據(jù)是重復(fù)的操作,所以需要通過(guò)循環(huán)語(yǔ)句實(shí)現(xiàn)數(shù)據(jù)的持續(xù)讀取。

下面通過(guò)一個(gè)案例實(shí)現(xiàn)字節(jié)流對(duì)文件數(shù)據(jù)的讀取。在實(shí)現(xiàn)案例之前,先做以下操作:

首先在 Java項(xiàng)目的根目錄下創(chuàng)建文本文件test.txt在文件中輸入內(nèi)容“itcast”?并保存然后使用字節(jié)輸入流對(duì)象讀取 test.txt文本文件

案例代碼:

public static void main(String[] args) throws IOException {

// 創(chuàng)建一個(gè)文件字節(jié)輸入流,并且指定源文件名稱

FileInputStream in = new FileInputStream("src/IO/test.txt");

int b = 0; // 定義 int 類型的變量 b,用于 記住每次讀取的 1 字節(jié)

while(true) {

b = in.read(); // 變量 b 記住讀取的每一字節(jié)

if(b == -1){ // 如果讀取的字節(jié) 位 -1,則跳出循環(huán)

break;

}

System.out.println(b + " "); // 否則輸出b

}

in.close();

}

// 輸出

105 116 99 97 115 116

由于計(jì)算機(jī)中的數(shù)據(jù)都是以字節(jié)的形式存在的。在test.txt文件中,字符i、?t、c、a、s、t 各占一字節(jié),所以最終結(jié)果顯示的就是文件test.txt中的6字節(jié)對(duì)應(yīng)的十進(jìn)制數(shù)(即這6個(gè)字母的ASCII碼值)。

? 注意:

有時(shí),在文件讀取的過(guò)程中可能會(huì)發(fā)生錯(cuò)誤。例如,由于文件不存在而導(dǎo)致無(wú)法讀取?;蛘哂脩魶](méi)有讀取權(quán)限等等。這些錯(cuò)誤都由Java虛擬機(jī)自動(dòng)封裝成 IOException 異常并拋出。例如,當(dāng)讀取一個(gè)不存在的文件時(shí),控制臺(tái)會(huì)報(bào)告異常信息,

當(dāng)讀取一個(gè)不存在的文件時(shí),程序就會(huì)有一個(gè)潛在的問(wèn)題。如果文件讀取過(guò)程中發(fā)生了 I/O 錯(cuò)誤,InputStream?就無(wú)法正常關(guān)閉,系統(tǒng)資源也無(wú)法及時(shí)釋放,這樣會(huì)造成系統(tǒng)資源浪費(fèi)。

對(duì)此,可以使用?try…· finally 語(yǔ)句保證?InputStream?在任何情況下都能夠正確關(guān)閉。修改上述代碼,將讀取文件的代碼放入try語(yǔ)句塊中,將關(guān)閉輸入流的代碼放入finaly語(yǔ)句塊中,具體代碼如下:

public static void main(String[] args) throws Exception {

InputStream input = null;

try {

// 創(chuàng)建一個(gè)文件字節(jié)輸入流

FileInputStream in = new FileInputStream("src/IO/test.txt");

int b = 0; // 定義 int 類型的變量 b,用于 記住每次讀取的 1 字節(jié)

while (true) {

b = in.read(); // 變量 b 記住讀取的每一字節(jié)

if (b == -1) { // 如果讀取的字節(jié) 位 -1,則跳出循環(huán)

break;

}

System.out.print(b + " "); // 否則輸出b

}

} finally {

if (input != null) {

input.close();

}

}

}

3.3 字節(jié)流寫文件

OutputStream 是JDK提供的基本輸出流,與InputStream類似.

OutputStream是所有輸出流的父類。OutputStream?是一個(gè)抽象類,如果使用此類,則必須先通過(guò)子類實(shí)例化對(duì)象。OutputStream類有多個(gè)子類,其中FileOutputStream子類是操作文件的字節(jié)輸出流,專門用于把數(shù)據(jù)寫入文件。

案例演示:

public static void main(String[] args) throws Exception {

OutputStream out = new FileOutputStream("src/IO/example.txt");

String str = "Island1314";

byte[] b = str.getBytes();

for(int i = 0; i < b.length; i++){

out.write(b[i]);

}

out.close();

}

由上可知,使用 FileOutputStream?寫數(shù)據(jù)時(shí),程序自動(dòng)創(chuàng)建了文件 example.txt,并將數(shù)據(jù)寫入example.txt?文件。需要注意的是,如果通過(guò)?FileOutputStream?向一個(gè)已經(jīng)存在的文件中寫入數(shù)據(jù),那么該文件中的數(shù)據(jù)會(huì)被覆蓋。

若希望在已存在的文件內(nèi)容之后追加新內(nèi)容,我們應(yīng)該怎么做:

可使用?FileOutputStream?的構(gòu)造函數(shù)?public FileOutputStream(String name,boolean append)創(chuàng)建文件輸出流以指定的名稱寫入文件,并把a(bǔ)ppend參數(shù)的值設(shè)置為true。如果第二個(gè)參數(shù)為true ,則字節(jié)將寫入文件的末尾而不是開(kāi)頭

public static void main(String[] args) throws Exception {

OutputStream out = new FileOutputStream("src/IO/example.txt",true);

String str = "\r\n201314";

byte[] b = str.getBytes();

for(int i = 0; i < b.length; i++){

out.write(b[i]);

}

out.close();

}

// 在 example.txt 查看

Island1314

201314

// 解釋:程序通過(guò)字節(jié)輸出流對(duì)象out向文件example.txt寫入后,并沒(méi)有將文件原來(lái)的數(shù)據(jù)清空,而是將新寫入的數(shù)據(jù)追加到了文件的末尾。

上面的 \r \n 又是什么意思呢 》 解釋如下:

對(duì)于字節(jié)流寫數(shù)據(jù),應(yīng)該如何實(shí)現(xiàn)換行

windows:\r\nlinux:\nmac:\r

需要注意的是:I/O流 在進(jìn)行數(shù)據(jù)讀寫操作時(shí)會(huì)出現(xiàn)異常。為了保持代碼的簡(jiǎn)潔,在InputStream 讀文件和OutputStream寫文件的程序中都使用了throws關(guān)鍵字將異常拋出。然而一旦遇到 I/O異常,I/O流 的 close()方法 將無(wú)法得到執(zhí)行,I/O流 對(duì)象占用的系統(tǒng)資源將得不到釋放。

因此,為了保證I/O流 的 close()方法 必須執(zhí)行,通常將關(guān)閉?I/O流 的操作寫在?finally代碼塊中。

3.4 字節(jié)流復(fù)制文件

在應(yīng)用程序中,I/O 流通常都是成對(duì)出現(xiàn)的,即輸入流和輸出流一起使用。例如:文件的復(fù)制就需要通過(guò)輸入流讀取一個(gè)文件中的數(shù)據(jù),再通過(guò)輸出流將數(shù)據(jù)寫入另一個(gè)文件。

下面通過(guò)一個(gè)案例演示文件內(nèi)容的復(fù)制:

首先在 src 項(xiàng)目的根目錄下創(chuàng)建 source目錄和 target 目錄,然后在 source 目錄中存放 a.png文件,最后將 source目錄下的 a.png 復(fù)制到 target 目錄下并重新命名為 b.png。

public static void main(String[] args) throws Exception{

// 創(chuàng)建一個(gè)文件輸入流,用于讀取 sorce 目錄的 a.png 文件

InputStream in = new FileInputStream("src/source/a.png");

// 創(chuàng)建一個(gè)文件輸出流,用于將讀取數(shù)據(jù)寫入到 target 目錄的 b.png 文件

OutputStream out = new FileOutputStream("src/target/b.png");

int len; //用于記住每次讀取的 1 字節(jié)

// 獲取復(fù)制文件前的系統(tǒng)時(shí)間

long begintime = System.currentTimeMillis();

while ((len = in.read())!= -1){ // 讀取 1 字節(jié)并且判斷是否讀到文件末尾

out.write(len); // 將讀取的 1 字節(jié)寫入文件

}

// 獲取文件復(fù)制結(jié)束后的時(shí)間

long endtime = System.currentTimeMillis();

System.out.println("復(fù)制文件所消耗時(shí)間:" + (endtime - begintime) + "ms");

in.close();

out.close();

}

// 輸出:

復(fù)制文件所消耗時(shí)間:6038ms

上述代碼實(shí)現(xiàn)了文件的復(fù)制:

通過(guò)while循環(huán)將a.png的所有字節(jié)逐個(gè)進(jìn)行復(fù)制。每循環(huán)一次,就通過(guò)調(diào)用FileInputStream的read()方法讀取一字節(jié),并通過(guò)調(diào)用FileOutputStream 的write()方法將該字節(jié)寫入指定文件,直到 len 的值為 -1,表示讀到了文件末尾,結(jié)束循環(huán),完成文件的復(fù)制。程序運(yùn)行結(jié)束后,會(huì)在命令行窗口打印復(fù)制文件所消耗的時(shí)間。由上可知,程序復(fù)制文件共消耗了6038ms。在復(fù)制文件時(shí),由于計(jì)算機(jī)性能等各方面原因,會(huì)導(dǎo)致復(fù)制文件所消耗的時(shí)間不確定,因此每次運(yùn)行程序的結(jié)果未必相同。

在程序運(yùn)行結(jié)束后,打開(kāi)target目錄,發(fā)現(xiàn)source目錄中的 a.png 文件被成功復(fù)制到 target目錄中

注意事項(xiàng):

上述實(shí)現(xiàn)的文件復(fù)制過(guò)程是逐字節(jié)讀寫,需要頻繁地操作文件,效率非常低

打個(gè)比方:

從北京運(yùn)送烤鴨到上海,如果有一萬(wàn)只烤鴨,每次運(yùn)送一只,就必須運(yùn)輸一萬(wàn)次,這樣的效率顯然非常低。為了減少運(yùn)輸次數(shù),可以先把一批烤鴨裝在車廂中,這樣就可以成批地運(yùn)送烤鴨,這時(shí)的車廂就相當(dāng)于一個(gè)緩沖區(qū)

因此在通過(guò)流的方式復(fù)制文件時(shí),為了提高效率,也可以定義一個(gè)字節(jié)數(shù)組作為緩沖區(qū)。

在復(fù)制文件時(shí),可以一次性讀取多個(gè)字節(jié)的數(shù)據(jù),并保存在字節(jié)數(shù)組中,然后將字節(jié)數(shù)組中的數(shù)據(jù)一次性寫入文件。程序中的緩沖區(qū)就是一塊內(nèi)存,它主要用于暫時(shí)存放輸入輸出的數(shù)據(jù),由于使用緩沖區(qū)減少了對(duì)文件的操作次數(shù),所以可以提高數(shù)據(jù)的讀寫效率。

利用緩沖區(qū)復(fù)制文件,修改代碼如下:

public static void main(String[] args) throws Exception{

// 創(chuàng)建一個(gè)文件輸入流,用于讀取 sorce 目錄的 a.png 文件

InputStream in = new FileInputStream("src/source/a.png");

// 創(chuàng)建一個(gè)文件輸出流,用于將讀取數(shù)據(jù)寫入到 target 目錄的 b.png 文件

OutputStream out = new FileOutputStream("src/target/b.png");

// 以下是用 緩沖區(qū) 讀寫文件

byte[] buff = new byte[1024]; // 定義一個(gè)字節(jié)數(shù)組作緩沖區(qū)

int len; //用于記住每次讀取的 1 字節(jié)

// 獲取復(fù)制文件前的系統(tǒng)時(shí)間

long begintime = System.currentTimeMillis();

while ((len = in.read(buff))!= -1){ // 讀取 1 字節(jié)并且判斷是否讀到文件末尾

out.write(buff, 0, len); // 將讀取的 1 字節(jié)寫入文件

}

// 獲取文件復(fù)制結(jié)束后的時(shí)間

long endtime = System.currentTimeMillis();

System.out.println("復(fù)制文件所消耗時(shí)間:" + (endtime - begintime) + "ms");

in.close();

out.close();

}

// 輸出:

復(fù)制文件所消耗時(shí)間:8ms

可以看出復(fù)制文件消耗時(shí)間明顯減少,說(shuō)明使用緩沖區(qū)讀寫文件可以有效地提高程序讀寫效率

4. 字符流 ?

4.1 字符流定義及基本用法

? 前面講解的內(nèi)容都是通過(guò)字節(jié)流直接對(duì)文件進(jìn)行讀寫。如果讀寫的文件內(nèi)容是字符,考慮到使用字節(jié)流讀寫字符可能存在傳輸效率以及數(shù)據(jù)編碼問(wèn)題、此時(shí)建議使用字符流。

同字節(jié)流一樣,字符流也有兩個(gè)抽象的頂級(jí)父類,分別是 Reader類 和?Writer類。

Reader 類是字符輸入流,用于從某個(gè)源設(shè)備讀取字符;Writer類是字符輸出流。用于向某個(gè)目標(biāo)設(shè)備寫入字符。在JDK中,Reader 類和Writer 類提供了一系列與讀寫數(shù)據(jù)相關(guān)的方法。

注:字符流 = 字節(jié)流 + 編碼表

Reader 類的常用方法

方法聲明功能描述int read()以字符為單位讀數(shù)據(jù)int read(char[] cbuf)將數(shù)據(jù)讀入 char 類型的數(shù)組,并返回?cái)?shù)組長(zhǎng)度int read(char[] cbuf, int off, int len)將數(shù)據(jù)讀入 char 類型的數(shù)組的指定區(qū)間,并返回?cái)?shù)組長(zhǎng)度void close()關(guān)閉數(shù)據(jù)流long transferTo(Writer out)將數(shù)據(jù)之間讀入字符輸出流

Writer 類的常用方法

方法聲明功能描述void write(int c)以字符為單位寫數(shù)據(jù)void write(char[] cbuf)將 char 類型的數(shù)組中的數(shù)據(jù)寫出void write(char[] cbuf, int off, int len)將 char 類型的數(shù)組中指定區(qū)間的數(shù)據(jù)寫出void write(String str)將 String 類型的數(shù)據(jù)寫出void write(String str, , int off, int len)將 String 類型中指定區(qū)間的數(shù)據(jù)寫出void flush()強(qiáng)制將緩沖區(qū)的數(shù)據(jù)同步到輸出流 (刷新流),之后還可以繼續(xù)寫數(shù)據(jù)void close()關(guān)閉數(shù)據(jù)流

?Reader?類?和 Writer?類作為字符流的頂級(jí)父類,也有許多子類,形成了體系結(jié)構(gòu),分別如下:

Reader 體系結(jié)構(gòu)圖:

Writer 體系結(jié)構(gòu)圖:

? 在上面我們可以看到字符流的繼承關(guān)系和字節(jié)流的繼承關(guān)系類似,Reader 類 和 Writer 類的很多子類都是成對(duì)出現(xiàn)。例如:

FileReader 和 FileWriter 用于讀寫文件BufferedReader 和 BufferedWriter 是具有緩沖功能的字符流,使用他們可以提高讀寫效率

4.2 字符流讀文件

塞在程序開(kāi)發(fā)中,經(jīng)常需要對(duì)文本文件的內(nèi)容進(jìn)行讀取。如果想從文件中直接讀取字符,便可以使用字符輸入流?FileReader,通過(guò)它可以從關(guān)聯(lián)的文件中讀取一個(gè)或一組字符。

下面通過(guò)一個(gè)案例演示如何使用?FileReader 讀取文件中的字符:

首先新建文本文件?test.txt?并在其中輸入字符 “itcast”然后創(chuàng)建字符輸入流 FileReader對(duì)象以讀取 reader.txt文件中的內(nèi)容

public static void main(String[] args) throws Exception {

// 創(chuàng)建一個(gè) FileReader 對(duì)象,用來(lái)讀取文件字符

FileReader reader = new FileReader("src/IO/test.txt");

int ch; // 用于記錄讀取的字符

while((ch = reader.read()) != -1){ // 循環(huán)判斷是否讀到文件末尾

System.out.print((char) ch); // 不是文件末尾就打印字符

}

reader.close(); // 關(guān)閉字符輸入流,釋放資源

}

// 輸出

itcast

注:FileReader對(duì)象的 read() 方法返回的是 int 類型的值,如果想獲得字符,就必須進(jìn)行強(qiáng)制類型轉(zhuǎn)換。

4.3 字符流寫文件

???上面講解了字符流對(duì)文本文件內(nèi)容的讀取。現(xiàn)在講解通過(guò)字符流向文本文件中寫入內(nèi)容,此時(shí)需要使用FileWriter類,該類可以一次向文件中寫人一個(gè)或一組字符。

下面通過(guò)一個(gè)案例演示如何使用 ?FileWriter?將字符寫入文件

public static void main(String[] args) throws Exception {

// 創(chuàng)建一個(gè) FileWriter 對(duì)象,用于向文件寫入數(shù)據(jù)

FileWriter writer = new FileWriter("src/IO/example.txt");

String str = "IsLand1314";

writer.write(str); // 將字符數(shù)據(jù)寫入到文本文件中

writer.write("\r\n"); //輸出換行

writer.close();

}

注意:

?FileWriter 同 FileOutputStream?一樣,如果指定的文件不存在,就會(huì)先創(chuàng)建文件,再寫入數(shù)據(jù);如果文件存在,則原文件內(nèi)容會(huì)被覆蓋。如果想在文件末尾追加數(shù)據(jù),同樣需要調(diào)用重載的構(gòu)造方法,將上面第三行代碼修改為:

FileWriter writer = new FileWriter("src/IO/example.txt", true);

再次運(yùn)行程序就可以在文件中實(shí)現(xiàn)追加的功能

4.4 數(shù)據(jù)編碼解碼問(wèn)題

由于字節(jié)流操作中文不是特別的方便,所以Java就提供字符流

字符流 = 字節(jié)流 + 編碼表

中文的字節(jié)存儲(chǔ)方式

用字節(jié)流復(fù)制文本文件時(shí),文本文件也會(huì)有中文,但是沒(méi)有問(wèn)題,原因是最終底層操作會(huì)自動(dòng)進(jìn)行字節(jié)拼接成中文,如何識(shí)別是中文的呢?漢字在存儲(chǔ)的時(shí)候,無(wú)論選擇哪種編碼存儲(chǔ),第一個(gè)字節(jié)都是負(fù)數(shù)

函數(shù)聲明功能描述byte[] getBytes()使用平臺(tái)的默認(rèn)字符集將該 String編碼為一系列字節(jié)byte[] getBytes(String charsetName)使用指定的字符集將該 String編碼為一系列字節(jié)String(byte[] bytes)使用平臺(tái)的默認(rèn)字符集解碼指定的字節(jié)數(shù)組來(lái)創(chuàng)建字符串String(byte[] bytes, String charsetName)通過(guò)指定的字符集解碼指定的字節(jié)數(shù)組來(lái)創(chuàng)建字符串

代碼演示:

public static void main(String[] args) throws UnsupportedEncodingException {

//定義一個(gè)字符串

String s = "中國(guó)";

//byte[] bys = s.getBytes(); //[-28, -72, -83, -27, -101, -67]

//byte[] bys = s.getBytes("UTF-8"); //[-28, -72, -83, -27, -101, -67]

byte[] bys = s.getBytes("GBK"); //[-42, -48, -71, -6]

System.out.println(Arrays.toString(bys));

//String ss = new String(bys);

//String ss = new String(bys,"UTF-8");

String ss = new String(bys,"GBK");

System.out.println(ss);

}

5. 轉(zhuǎn)換流 ?

? 前面提到I/0流分為字節(jié)流和字符流,字節(jié)流和字符流之間可以進(jìn)行轉(zhuǎn)換。JDK提供了兩個(gè)類用于將字節(jié)流轉(zhuǎn)換為字符流,分別是 InputStreamReader 和 ?OutputStreamReader。

InputStreamReader:是從字節(jié)流到字符流的橋梁,父類是 Reader

它讀取字節(jié),并使用指定的編碼將其解碼為字符它使用的字符集可以由名稱指定,也可以被明確指定,或者可以接受平臺(tái)的默認(rèn)字符集

OutputStreamReader:是從字符流到字節(jié)流的橋梁,父類是 Writer

是從字符流到字節(jié)流的橋梁,使用指定的編碼將寫入的字符編碼為字節(jié)它使用的字符集可以由名稱指定,也可以被明確指定,或者可以接受平臺(tái)的默認(rèn)字符集

通過(guò)?InputStreamReader 和 OutputStreamReader 將字節(jié)流轉(zhuǎn)換為字符流,可以提高文件的讀寫效率

方法聲明功能描述InputStreamReader(InputStream in)使用默認(rèn)字符編碼創(chuàng)建InputStreamReader對(duì)象InputStreamReader(InputStream in,String chatset)使用指定的字符編碼創(chuàng)建InputStreamReader對(duì)象OutputStreamWriter(OutputStream out)使用默認(rèn)字符編碼創(chuàng)建OutputStreamWriter對(duì)象OutputStreamWriter(OutputStream out,String charset)使用指定的字符編碼創(chuàng)建OutputStreamWriter對(duì)象

下面通過(guò)一個(gè)案例演示如何將字節(jié)流轉(zhuǎn)為字符流

首先.在src項(xiàng)目的根目錄下新建文本文件 test.txt并在文件中輸入“Island1314”其次,在sre文件夾中創(chuàng)建一個(gè)類,在類中創(chuàng)建字節(jié)輸入流 FileInputStream對(duì)象讀取src.txt文件中的內(nèi)容,并將字節(jié)輸入流轉(zhuǎn)換成字符輸入流。再次,創(chuàng)建一個(gè)字節(jié)輸出流對(duì)象,并指定目標(biāo)文件為des.txt最后,將字節(jié)輸出流轉(zhuǎn)換成字符輸出流將字符輸出到文件中

public static void main(String[] args) throws Exception {

// 創(chuàng)建字節(jié)輸入流 in ,并且指定源文件 test.txt

FileInputStream in = new FileInputStream("src/IO/test.txt");

// 將字節(jié)輸入流 in 轉(zhuǎn)化為 字符輸入流 isr

InputStreamReader isr = new InputStreamReader(in);

// 創(chuàng)建字節(jié)輸出流 out ,并且指定源文件 des.txt

FileOutputStream out = new FileOutputStream("src/IO/des.txt");

// 將字節(jié)輸出流 out 轉(zhuǎn)化為 字符輸出流 osw

OutputStreamWriter osw = new OutputStreamWriter(out);

int ch; // 定義一個(gè)變量用于記錄讀取的字符

while((ch = isr.read()) != -1) // 循環(huán)判斷是否讀到文件末尾

{

osw.write(ch);

}

isr.close(); // 關(guān)閉字符輸入流,節(jié)省資源

osw.close(); // 關(guān)閉字符輸出流,節(jié)省資源

}

?

6. 緩沖流 ?

6.1 字節(jié)緩沖流

BufferedOutputStream:該類實(shí)現(xiàn)緩沖輸出流.通過(guò)設(shè)置這樣的輸出流,應(yīng)用程序可以向底層輸出流寫入字節(jié),而不必為寫入的每個(gè)字節(jié)導(dǎo)致底層系統(tǒng)的調(diào)用BufferedInputStream:創(chuàng)建BufferedInputStream將創(chuàng)建一個(gè)內(nèi)部緩沖區(qū)數(shù)組.當(dāng)從流中讀取或跳過(guò)字節(jié)時(shí),內(nèi)部緩沖區(qū)將根據(jù)需要從所包含的輸入流中重新填充,一次很多字節(jié)字節(jié)流緩沖區(qū)的核心優(yōu)勢(shì)就是一次讀取多個(gè)字節(jié)數(shù)據(jù),從而減少硬盤操作子樹(shù)

構(gòu)造方法:

BufferedOutputStream(OutputStream out)創(chuàng)建字節(jié)緩沖輸出流對(duì)象BufferedInputStream(InputStream in)創(chuàng)建字節(jié)緩沖輸入流對(duì)象

public static void main(String[] args) throws IOException {

//字節(jié)緩沖輸出流:BufferedOutputStream(OutputStream out)

BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("src/IO/test.txt"));

//寫數(shù)據(jù)

bos.write("hello\r\n".getBytes());

bos.write("world\r\n".getBytes());

//釋放資源

bos.close();

//字節(jié)緩沖輸入流:BufferedInputStream(InputStream in)

BufferedInputStream bis = new BufferedInputStream(new FileInputStream("src/IO/test.txt"));

//一次讀取一個(gè)字節(jié)數(shù)據(jù)

// int by;

// while ((by=bis.read())!=-1) {

// System.out.print((char)by);

// }

//一次讀取一個(gè)字節(jié)數(shù)組數(shù)據(jù)

byte[] bys = new byte[1024];

int len;

while ((len=bis.read(bys))!=-1) {

System.out.print(new String(bys,0,len));

}

//釋放資源

bis.close();

}

6.2 字符緩沖流

BufferedWriter:將文本寫入字符輸出流,緩沖字符,以提供單個(gè)字符,數(shù)組和字符串的高效寫入,可以指定緩沖區(qū)大小,或者可以接受默認(rèn)大小。默認(rèn)值足夠大,可用于大多數(shù)用途BufferedReader:從字符輸入流讀取文本,緩沖字符,以提供字符,數(shù)組和行的高效讀取,可以指定緩沖區(qū)大小,或者可以使用默認(rèn)大小。 默認(rèn)值足夠大,可用于大多數(shù)用途

BufferedWriter(Writer out)創(chuàng)建字符緩沖輸出流對(duì)象BufferedReader(Reader in)創(chuàng)建字符緩沖輸入流對(duì)象

public static void main(String[] args) throws IOException {

//創(chuàng)建字符緩沖輸出流

BufferedWriter bw = new BufferedWriter(new FileWriter("src/IO/test.txt"));

//寫數(shù)據(jù)

for (int i = 0; i < 10; i++) {

bw.write("hello" + i);

//bw.write("\r\n");

bw.newLine();

bw.flush();

}

//釋放資源

bw.close();

//創(chuàng)建字符緩沖輸入流

BufferedReader br = new BufferedReader(new FileReader("src/IO/test.txt"));

String line;

while ((line=br.readLine())!=null) {

System.out.println(line);

}

br.close();

}

7. 序列化反序列化 ?

? 程序在運(yùn)行過(guò)程中,數(shù)據(jù)都保存在Java對(duì)象(內(nèi)存)中,但很多情況下還需要將一些數(shù)據(jù)永久保存到磁盤上。為此,Java 提供了對(duì)象序列化機(jī)制,可以將對(duì)象中的數(shù)據(jù)保存到磁盤。

對(duì)象序列化(serialize)是指將一個(gè)Java對(duì)象轉(zhuǎn)換成一個(gè)?I/O流?的字節(jié)序列的過(guò)程。

對(duì)象序列化機(jī)制可以使內(nèi)存中的Java對(duì)象轉(zhuǎn)換成與平臺(tái)無(wú)關(guān)的二進(jìn)制流,通過(guò)編寫程序,既可以將這種二進(jìn)制流持久地保存在磁盤上,又可以通過(guò)網(wǎng)絡(luò)將其傳輸?shù)搅硪粋€(gè)網(wǎng)絡(luò)節(jié)點(diǎn)。

論 其他程序在獲得了二進(jìn)制流后,還可以將二進(jìn)制流恢復(fù)成原來(lái)的Java對(duì)象,這種將 I/O流 中的字節(jié)序列恢復(fù)為Java對(duì)象的過(guò)程稱為 反序列化(deserialize)。

? 如果想讓某個(gè)對(duì)象支持序列化機(jī)制,那么這個(gè)對(duì)象所屬的類必須是可序列化的。在Java中,可序列化的類必須實(shí)現(xiàn) Serializable 或 Externalizable 兩個(gè)接口之一。

Serializable?接口或 Externalizable 接口實(shí)現(xiàn)序列化機(jī)制的主要區(qū)別

Serializable 接口Externalizable 接口系統(tǒng)自動(dòng)存儲(chǔ)必要的信息由程序員自己決定要存儲(chǔ)的信息Java 內(nèi)部支持,易于實(shí)現(xiàn),只需實(shí)現(xiàn)該接口即可,不需要其他代碼支持該接口只提供了兩個(gè)抽象方法,實(shí)現(xiàn)該接口時(shí)必須重寫這兩個(gè)抽象方法性能較差性能較好

? 與實(shí)現(xiàn)?Serializable??接口相比,雖然實(shí)現(xiàn) Externalizable 接口可以帶來(lái)性能上的一定提升,但由于后者需要實(shí)現(xiàn)兩個(gè)抽象方法,所以將導(dǎo)致編程的復(fù)雜度提高。

在實(shí)際開(kāi)發(fā)時(shí),大部分情況下使用Serializable 接口的方式實(shí)現(xiàn)對(duì)象序列化。

?使用Serializable?接口實(shí)現(xiàn)對(duì)象序列化非常簡(jiǎn)單,只需要讓目標(biāo)類實(shí)現(xiàn) Serializable 接口即可,無(wú)須實(shí)現(xiàn)任何方法。例如,自定義Person類,讓Person類實(shí)現(xiàn)?Serializable接口,如下:

public class Person implements Serializable{

// 為該類指定 serialVersionUID 變量值

private static final long serialVersionUID = 1L;

// 聲明變量

private int id;

private String name;

private int age;

//... 此處省略各屬性的 gettter 和 setter 方法

}

? 在上述代碼中,Person類實(shí)現(xiàn)了?Serializable接口,并指定了?serialVersionUID變量值,該屬性的值的作用是標(biāo)識(shí)Java類的序列化版本。如果不顯式定義 serialVersionUID變量值,那么serialVersionUID屬性的值將由 Java 虛擬機(jī) 根據(jù)類的相關(guān)信息計(jì)算得出

補(bǔ)充知識(shí):serialVersionUID

? serialVersionUID適用于Java的對(duì)象序列化機(jī)制。簡(jiǎn)單來(lái)說(shuō),Java的對(duì)象序列化機(jī)制是通過(guò)判斷類的?serialVersionUID?來(lái)驗(yàn)證版本一致性的。在進(jìn)行反序列化時(shí),Java虛擬機(jī)會(huì)把字節(jié)流中的?serialVersionUID?與本地相應(yīng)實(shí)體類的?serialVersionUID?進(jìn)行比較。如果相同,就認(rèn)為是一致的,可以進(jìn)行反序列化;否則就會(huì)拋出序列化版本不一致的異常。

因此,為了在反序列化時(shí)確保序列化版本的兼容性,最好在每一個(gè)要序列化的類中加入 private static final long serialVersionUID 的變量值,具體數(shù)值可自定義,默認(rèn)是1L。如果不顯式指定 serialVersionUID?的值,系統(tǒng)可以根據(jù)類名、接口名、成員方法及屬性等生成一個(gè)64位的哈希值,將這個(gè)哈希值作為serialVersionUID的值。定義了serialVersionUID的值,如果serialVersionUID所屬類的某個(gè)對(duì)象被序列化,即使該對(duì)象對(duì)應(yīng)的類被修改了,該對(duì)象也依然可以被正確地反序列化。

8. 小結(jié) ?

本章主要介紹了 I/O流 的相關(guān)知識(shí)。

? 包括File類,包括創(chuàng)建File對(duì)象、File 類的常用方法、遍歷目錄下的文件和刪除文件及目錄;字節(jié)流,包括字節(jié)流的概念、字節(jié)流讀文件、字節(jié)流寫文件和文件的復(fù)制;字符流,包括字符流的定義及基本用法、字符流讀文件和字符流寫文件;轉(zhuǎn)換流的使用;序列化和反序列化。通過(guò)本章的學(xué)習(xí),讀者應(yīng)該了解 I/O 流,并且熟練掌握了 I/O 流的相關(guān)知識(shí)。

補(bǔ)充:字節(jié)流與字符流區(qū)別

字節(jié)流是IO中最基礎(chǔ)的形式,它以字節(jié)(8位)為單位進(jìn)行數(shù)據(jù)傳輸,適用于處理所有類型的數(shù)據(jù),包括文本、圖片、音頻和視頻等二進(jìn)制數(shù)據(jù)。在Java中,字節(jié)流的基類是InputStream和OutputStream。字節(jié)流在操作時(shí)通常不會(huì)使用緩沖區(qū),直接與文件本身進(jìn)行操作,這意味著每次調(diào)用read方法都可能伴隨著一次磁盤IO,因此效率相對(duì)較低。為了提高效率,可以使用如BufferedInputStream和BufferedOutputStream這樣的緩沖字節(jié)流。

字符流則是以Unicode碼元(16位)為單位進(jìn)行數(shù)據(jù)傳輸,主要用于處理文本數(shù)據(jù)。字符流在處理數(shù)據(jù)時(shí)會(huì)涉及字符編碼的轉(zhuǎn)換,如UTF-8或GBK等。在Java中,字符流的基類是Reader和Writer。字符流在輸出前會(huì)完成Unicode碼元序列到相應(yīng)編碼方式的字節(jié)序列的轉(zhuǎn)換,并使用內(nèi)存緩沖區(qū)來(lái)存放轉(zhuǎn)換后的字節(jié)序列,等待都轉(zhuǎn)換完畢再一同寫入磁盤文件中。

主要區(qū)別在于:

字節(jié)流操作的基本單元為字節(jié),而字符流操作的基本單元為Unicode碼元。 字節(jié)流不使用緩沖區(qū),字符流使用緩沖區(qū)。 字節(jié)流可以處理任何類型的數(shù)據(jù),字符流主要處理文本數(shù)據(jù)。 字節(jié)流與文件直接操作,字符流在操作時(shí)使用緩沖區(qū)。

【*★,°*:.☆( ̄▽ ̄)/$:*.°★* 】那么本篇到此就結(jié)束啦,如果我的這篇博客可以給你提供有益的參考和啟示,可以三連支持一下 !!??????

我的博客即將同步至騰訊云開(kāi)發(fā)者社區(qū),邀請(qǐng)大家一同入駐:https://cloud.tencent.com/developer/support-plan?invite_code=1uyo4puciczbw

柚子快報(bào)激活碼778899分享:【Java】I/O 操作詳解

http://yzkb.51969.com/

好文閱讀

評(píng)論可見(jiàn),查看隱藏內(nèi)容

本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場(chǎng)。

轉(zhuǎn)載請(qǐng)注明,如有侵權(quán),聯(lián)系刪除。

本文鏈接:http://gantiao.com.cn/post/19573303.html

發(fā)布評(píng)論

您暫未設(shè)置收款碼

請(qǐng)?jiān)谥黝}配置——文章設(shè)置里上傳

掃描二維碼手機(jī)訪問(wèn)

文章目錄