国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【Java基礎(chǔ)教程】(四十五)IO篇 · 中:轉(zhuǎn)換流、內(nèi)存流和打印流(探索裝飾設(shè)計模式與PrintStream類的進階),文件操作案例實踐、字符編碼問題~

這篇具有很好參考價值的文章主要介紹了【Java基礎(chǔ)教程】(四十五)IO篇 · 中:轉(zhuǎn)換流、內(nèi)存流和打印流(探索裝飾設(shè)計模式與PrintStream類的進階),文件操作案例實踐、字符編碼問題~。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

【Java基礎(chǔ)教程】(四十五)IO篇 · 中:轉(zhuǎn)換流、內(nèi)存流和打印流(探索裝飾設(shè)計模式與PrintStream類的進階),文件操作案例實踐、字符編碼問題~,# Java基礎(chǔ)教程,java,設(shè)計模式,開發(fā)語言,學(xué)習(xí),java-ee,jvm,后端

??本節(jié)學(xué)習(xí)目標(biāo)

  • 掌握內(nèi)存操作流、轉(zhuǎn)換流、打印流的使用;
  • 掌握文件復(fù)制操作;
  • 掌握字符的主要編碼類型以及亂碼問題產(chǎn)生的原因;

1?? 轉(zhuǎn)換流

雖然字節(jié)流與字符流表示兩種不同的數(shù)據(jù)流操作,但是這兩種流彼此間是可以實現(xiàn)互相轉(zhuǎn)換的,而要實現(xiàn)這樣的轉(zhuǎn)換可以通過 InputStreamReader、OutputStreamWriter 兩個類。首先介紹這兩個類的繼承結(jié)構(gòu)以及構(gòu)造方法。

名稱 InputStreamReader OutputStreamWriter
定義結(jié)構(gòu) public class InputStreamReader extends Reader public class OutputStreamWriter extends Writer
構(gòu)造方法 public InputStreamReader(InputStream in) public OutputStreamWriter(OutputStream out)

可以發(fā)現(xiàn):

  • InputStreamReader 類的構(gòu)造方法中接收 InputStream 類的對象,而 InputStreamReaderReader 的子類,該類對象可以直接向上轉(zhuǎn)型為 Reader 類對象,這樣就表示可以將接收到的字節(jié)輸入流轉(zhuǎn)換為字符輸入流;
  • OutputStreamWriter 類的構(gòu)造方法接收 OutputStream 類的對象,而 OutputStreamWriterWriter 的子類,該類對象可以直接向上轉(zhuǎn)型為 Writer 類對象,這樣就表示可以將接收到的字節(jié)輸出流轉(zhuǎn)換為字符輸出流,Writer 類中也提供了直接輸出字符串的操作。
//	范例 1: 實現(xiàn)輸出流轉(zhuǎn)換
package com.xiaoshan.demo;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;

public class TestDemo {
	public static void main(String[] args) throws Exception{
		File file = new File("d:" + File.separator + "demo" + File.separator + "xiaoshan.txt");	//1.定義要輸出文件的路徑
		if (!file.getParentFile().exists()){	//判斷父路徑是否存在
			file.getParentFile().mkdirs();	//創(chuàng)建父路徑
		}
		OutputStream output = new FileOutputStream(file); //將OutputStream 類對象傳遞給OutputStreamWriter類的構(gòu)造方法而后向上轉(zhuǎn)型為 Writer
		Writer out = new OutputStreamWriter(output); 
		out.write("更多知識請訪問:https://lst66.blog.csdn.net");	//Writer 類的方法
		out.flush();
		out.close();
	}
}

運行結(jié)果:

【Java基礎(chǔ)教程】(四十五)IO篇 · 中:轉(zhuǎn)換流、內(nèi)存流和打印流(探索裝飾設(shè)計模式與PrintStream類的進階),文件操作案例實踐、字符編碼問題~,# Java基礎(chǔ)教程,java,設(shè)計模式,開發(fā)語言,學(xué)習(xí),java-ee,jvm,后端

此程序利用 OutputStreamWriter 類將字節(jié)輸出流轉(zhuǎn)換為字符輸出流,這樣就可以方便地實現(xiàn)字符串?dāng)?shù)據(jù)的輸出。

從實際的開發(fā)來講,轉(zhuǎn)換流的使用情況并不多,并且JDK隨著版本的提高會擴充越來越多方便的類庫,所以這種轉(zhuǎn)換流的意義大部分也只會停留在理論分析上。

通過之前的講解可以發(fā)現(xiàn),四個流的操作類如果要操作文件都要求分別使用不同的子類(FileXxx)。而 FileOutputStream、FilelnputStream、FileWriter、 FileReader 四個類的繼承結(jié)構(gòu)如圖所示。

【Java基礎(chǔ)教程】(四十五)IO篇 · 中:轉(zhuǎn)換流、內(nèi)存流和打印流(探索裝飾設(shè)計模式與PrintStream類的進階),文件操作案例實踐、字符編碼問題~,# Java基礎(chǔ)教程,java,設(shè)計模式,開發(fā)語言,學(xué)習(xí),java-ee,jvm,后端
圖1 文件操作類的繼承結(jié)構(gòu)

通過繼承結(jié)構(gòu)可以發(fā)現(xiàn),FileWriterFileReader 都是轉(zhuǎn)換流的子類,也就證明所有要讀取的文件數(shù)據(jù)都是字節(jié)數(shù)據(jù),所有的字符都是在內(nèi)存中處理后形成的。

2?? 案例:文件復(fù)制

在 命令行工具中,可以利用copy 實現(xiàn)文件的復(fù)制操作。此命令的語法為:“copy 源文件路徑 目標(biāo)文件路徑”。在文件復(fù)制過程中,如果源文件不存在或參數(shù)個數(shù)不足,都會產(chǎn)生錯誤,而本案例將模擬copy命令實現(xiàn)一個與之功能相同的程序。

同時對于此部分的程序也屬于InputStreamOutputStream的應(yīng)用總結(jié),并且本處講解的代碼,在實際的開發(fā)中也會使用到。

現(xiàn)在要求實現(xiàn)一個文件的復(fù)制操作,在復(fù)制的過程中利用初始化參數(shù)設(shè)置復(fù)制的源路徑與目標(biāo)路徑,同時在本程序執(zhí)行時可以復(fù)制任何文件,例如:圖片、視頻、文本等。

對于此程序的要求,首先必須確認要使用何種數(shù)據(jù)流進行操作。由于程序要求可以復(fù)制任意類型的文件,所以很明顯必須利用字節(jié)流 (InputStream、OutputStream) 類完成。而具體的復(fù)制操作實現(xiàn), 有以下兩種做法。

(1)做法一:將所有的文件內(nèi)容先一次性讀取到程序中,再一次性輸出。這種實現(xiàn)方式有一個缺陷: 如果要讀取的文件量過大,就會造成程序的內(nèi)存崩潰;
(2)做法二:采用邊讀取邊輸出的操作方式,每次從源文件輸入流中讀取部分數(shù)據(jù),而后將這部分數(shù)據(jù)交給輸出流輸出,這樣的做法不會占用較大的內(nèi)存空間,但是會適當(dāng)損耗一些時間,當(dāng)然也可以通過限制文件大小來避免此類問題。

如果要想完成本操作,實際上需要使用InputStreamOutputStream類的兩個操作方法。

  • InputStream類:public int read(byte[] b) throws IOException,將內(nèi)容讀取到字節(jié)數(shù)組中,如果沒有數(shù)據(jù)則返回 -1,否則就是讀取長度;
  • OutputStream類:public void write(byte[] b, int off, int len) throws IOException,要設(shè)置的字節(jié)數(shù)組實際上就是在read()方法里面使用的數(shù)組,數(shù)據(jù)輸出一定是從字節(jié)數(shù)組的第0個元素開始,輸出讀取到的數(shù)據(jù)長度的數(shù)據(jù)。

在實際的開發(fā)中,最常見的是這兩個方法的結(jié)合使用。

//	范例 2: 實現(xiàn)文件復(fù)制操作
package com.xiaoshan.demo;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

public class CopyDemo{
	public static void main(String[] args) throws Exception{ 
		long start = System.currentTimeMillis();	//取得復(fù)制開始的時間
		if (args.length != 2){		//初始化參數(shù)不足2位
			System.out.println("命令執(zhí)行錯誤!"); 
			System.exit(1);	//程序退出執(zhí)行
		}
		//如果輸入?yún)?shù)正確,應(yīng)該進行源文件有效性的驗證 
		File inFile = new File(args[0]);	//第一個為源文件路徑
		if (!inFile.exists()){		//源文件不存在
			System.out.println("源文件不存在,請確認執(zhí)行路徑。");
			System.exit(1);       //程序退出
		}
		//如果此時源文件正確,就需要定義輸出文件,同時要考慮到輸出文件有目錄
		File outFile = new File(args[1]);
		if(!outFile.getParentFile().exists()){   //輸出文件路徑不存在
			outFile.getParentFile().mkdirs(); 	//創(chuàng)建目錄
		}
		//實現(xiàn)文件內(nèi)容的復(fù)制,分別定義輸出流與輸入流對象
		InputStream input = new FileInputStream(inFile);
		OutputStream output = new FileOutputStream(outFile);
		int temp = 0;             	//保存每次讀取的數(shù)據(jù)長度
		byte data[] = new byte[1024];     	//每次讀取1024個字節(jié)
		//將每次讀取進來的數(shù)據(jù)保存在字節(jié)數(shù)組里面,并且返回讀取的個數(shù)
		while((temp = input.read(data)) != -1){		//循環(huán)讀取數(shù)據(jù)
			output.write(data, 0, temp);		//輸出數(shù)組
		}
		input.close();	//關(guān)閉輸入流
		output.close();	//關(guān)閉輸出流
		long end = System.currentTimeMillis();	//取得操作結(jié)束時間
		System.out.println("復(fù)制所花費的時間:" + (end-start));
	}
}

設(shè)置初始化參數(shù): java d:\demo\xiaoshan.txt d:\demo\xiaoshan-copy.txt
程序執(zhí)行結(jié)果:

復(fù)制所花費的時間:15

【Java基礎(chǔ)教程】(四十五)IO篇 · 中:轉(zhuǎn)換流、內(nèi)存流和打印流(探索裝飾設(shè)計模式與PrintStream類的進階),文件操作案例實踐、字符編碼問題~,# Java基礎(chǔ)教程,java,設(shè)計模式,開發(fā)語言,學(xué)習(xí),java-ee,jvm,后端


【Java基礎(chǔ)教程】(四十五)IO篇 · 中:轉(zhuǎn)換流、內(nèi)存流和打印流(探索裝飾設(shè)計模式與PrintStream類的進階),文件操作案例實踐、字符編碼問題~,# Java基礎(chǔ)教程,java,設(shè)計模式,開發(fā)語言,學(xué)習(xí),java-ee,jvm,后端

此程序?qū)崿F(xiàn)了完整的開發(fā)要求,同時程序的執(zhí)行效率較高,整體操作只花費了300毫秒左右的時間。 文件復(fù)制程序的流程如下圖所示:

【Java基礎(chǔ)教程】(四十五)IO篇 · 中:轉(zhuǎn)換流、內(nèi)存流和打印流(探索裝飾設(shè)計模式與PrintStream類的進階),文件操作案例實踐、字符編碼問題~,# Java基礎(chǔ)教程,java,設(shè)計模式,開發(fā)語言,學(xué)習(xí),java-ee,jvm,后端
圖2 文件復(fù)制流程

3?? 字符編碼

計算機中所有信息都是由二進制數(shù)據(jù)組成的,因此所有能夠描述出的中文文字都是經(jīng)過處理后的結(jié)果。在計算機的世界里,所有的語言文字都會使用編碼來進行描述,例如:最常見的編碼是 ASCⅡ 碼。在實際的工作里面最為常見的4種編碼如下。

  • GBK、GB2312:中文的國標(biāo)編碼,其中 GBK 包含簡體中文與繁體中文兩種,而 GB2312 只包含簡體中文;
  • ISO8859-1:國際編碼,可以描述任何文字信息(中文需要轉(zhuǎn)碼);
  • UNICODE:是十六進制編碼,但是在傳遞字符信息時會造成傳輸?shù)臄?shù)據(jù)較大;
  • UTF 編碼 (Unicode Transformation Format):是一種 UNICODE 的可變長度編碼,常見的編碼為 UTF-8 編碼。

實際上對于編碼問題,在實際的項目開發(fā)過程中,往往都會以 UTF-8編碼為主,所以在編寫代碼時建議將文件編碼都統(tǒng)一設(shè)置為UTF-8的形式。

既然計算機世界中存在這么多編碼,在實際項目的開發(fā)中就有可能在數(shù)據(jù)傳輸中出現(xiàn)編碼與解碼所使用的字符集不統(tǒng)一的問題,而這樣就會產(chǎn)生亂碼。我們可以利用 System 類取得當(dāng)前系統(tǒng)中的環(huán)境屬性,從而知道當(dāng)前系統(tǒng)所使用的默認編碼。

//	范例 3: 取得當(dāng)前系統(tǒng)中的環(huán)境屬性中的文件編碼
package com.xiaoshan.demo;

public class TestDemo {
	public static void main(String[] args) throws Exception{
		System.getProperties().list(System.out);  //  列出全部系統(tǒng)屬性
	}
}

程序執(zhí)行結(jié)果:

file.encoding=GBK
……

此程序的功能是列出全部的系統(tǒng)屬性,其中會發(fā)現(xiàn)一個"file.encoding" 的屬性名稱,此屬性定義的是文件的默認編碼,可以發(fā)現(xiàn)編碼方式為GBK。

System類中定義的取得系統(tǒng)屬性的方法為:public static Properties getProperties(), 此方法返回的是一個 Properties類對象,此類將在后續(xù)文章為大家講解,在此處并不需要關(guān)注具體的代碼,只需要關(guān)注程序的執(zhí)行結(jié)果。

另外在系統(tǒng)屬性輸出時可以發(fā)現(xiàn)存在一個"file.separator=\"的信息,此處描述的就是文件的路徑分隔符定義,也就是 File.separator 常量的內(nèi)容。

因為默認的編碼為 GBK, 所以當(dāng)程序向文件中輸出信息時,文件就會使用 GBK 編碼,而文件的內(nèi)容也應(yīng)該是GBK 編碼,此處如果強行修改為其他編碼,就會出現(xiàn)亂碼。所謂亂碼就是指編碼與解碼字符集不統(tǒng)一所造成的問題。

//	范例 4: 程序出現(xiàn)亂碼
package com.xiaoshan.demo;

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;

public class TestDemo  {
	public static void main(String[] args)  throws Exception{
		File file = new File("D:" + File.separator + "小山.txt");
		OutputStream output = new FileOutputStream(file);
		//強制改變文字的編碼,此操作可以通過String類的getBytes(方法實現(xiàn)
		output.write("更多文章請訪問:https://lst66.blog.csdn.net".getBytes("ISO8859-1"));
		output.close();
	}
}

在當(dāng)前系統(tǒng)中默認的編碼應(yīng)該使用 GBK, 但是在程序處理時強制性地 將內(nèi)容編碼轉(zhuǎn)換為了“ISO8859-1”, 這樣程序的編碼與文件的保存編碼就會發(fā)生沖突,那么保存后的文件就會出現(xiàn)中文亂碼問題,保存后的文件內(nèi)容如下所示:

【Java基礎(chǔ)教程】(四十五)IO篇 · 中:轉(zhuǎn)換流、內(nèi)存流和打印流(探索裝飾設(shè)計模式與PrintStream類的進階),文件操作案例實踐、字符編碼問題~,# Java基礎(chǔ)教程,java,設(shè)計模式,開發(fā)語言,學(xué)習(xí),java-ee,jvm,后端

4?? 內(nèi)存流

在流的操作中除了進行文件的輸入與輸出操作之外,還可以針對內(nèi)存進行同樣的操作。假設(shè)某一種應(yīng)用需要進行 IO 操作,但是又不希望在磁盤上產(chǎn)生一些文件時, 就可以將內(nèi)存當(dāng)作一個臨時文件進行操作。在 Java 中,針對內(nèi)存操作提供了以下兩組類。

【Java基礎(chǔ)教程】(四十五)IO篇 · 中:轉(zhuǎn)換流、內(nèi)存流和打印流(探索裝飾設(shè)計模式與PrintStream類的進階),文件操作案例實踐、字符編碼問題~,# Java基礎(chǔ)教程,java,設(shè)計模式,開發(fā)語言,學(xué)習(xí),java-ee,jvm,后端
圖3 內(nèi)存流的繼承結(jié)構(gòu)

  • 字節(jié)內(nèi)存流: ByteArrayInputStream (內(nèi)存字節(jié)輸入流)、 ByteArrayOutputStream (內(nèi)存字節(jié)輸出流);
  • 字符內(nèi)存流: CharArrayReader (內(nèi)存字符輸入流)、 CharArrayWriter (內(nèi)存字符輸出流)。

字節(jié)內(nèi)存流與字符內(nèi)存流兩者唯一的區(qū)別就在于操作數(shù)據(jù)類型上,字節(jié)內(nèi)存流操作使用byte數(shù)據(jù)類型,而字符內(nèi)存流操作使用char數(shù)據(jù)類型。但是這兩類操作的基本結(jié)構(gòu)相同,考慮到實際的開發(fā)情況,本節(jié)主要講解字節(jié)內(nèi)存流的使用。

雖然清楚了內(nèi)存流的操作結(jié)構(gòu),但是要想真正使用內(nèi)存流還必須清楚內(nèi)存流定義的構(gòu)造方法(以字節(jié)內(nèi)存流為例)。內(nèi)存流定義的構(gòu)造方法如下。

  • ByteArrayInputStream 類構(gòu)造: public ByteArrayInputStream(byte[] buf);
  • ByteArrayOutputStream 類構(gòu)造: public ByteArrayOutputStream()。

通過 ByteArrayInputStream 類的構(gòu)造可以發(fā)現(xiàn),在內(nèi)存流對象實例化時就必須準(zhǔn)備好要操作的數(shù)據(jù)信息,所以內(nèi)存流的操作實質(zhì)上就是將操作數(shù)據(jù)首先保存到內(nèi)存中,然后利用IO 流操作進行單個字節(jié)的處理。

下面演示通過內(nèi)存流實現(xiàn)一個小寫字母轉(zhuǎn)大寫字母的操作。程序不使用 String 類中提供的 toUpperCase() 方法,而是利用IO 操作,將每一個字節(jié)進行大寫字母轉(zhuǎn)換;為了方便地實現(xiàn)字母的轉(zhuǎn)大寫操作(避免不必要的字符也被轉(zhuǎn)換)可以借助 Character 包裝類的方法:

//轉(zhuǎn)小寫字母
public static char toLowerCase(char ch);
//轉(zhuǎn)大寫字母
public static char toUpperCase(char ch);
//	范例 5 
package com.xiaoshan.demo;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

public class TestDemo{
	public static void main(String[] args) throws Exception{
		String str= "https://blog.csdn.net/LVSONGTAO1225";
		//本次將通過內(nèi)存操作流實現(xiàn)轉(zhuǎn)換,先將數(shù)據(jù)保存在內(nèi)存流里面,再從里面取出每一個數(shù)據(jù) 
		//將所有要讀取的數(shù)據(jù)設(shè)置到內(nèi)存輸入流中,本次利用向上轉(zhuǎn)型為InputStream類實例化
		InputStream input = new ByteArrayInputStream(str.getBytes());
		//為了能夠?qū)⑺械膬?nèi)存流數(shù)據(jù)取出,可以使用ByteArrayOutputStream 
		OutputStream output = new ByteArrayOutputStream();
		int temp = 0;     	//讀取每一個字節(jié)數(shù)據(jù)
		//經(jīng)過此次循環(huán)后,所有的數(shù)據(jù)都將保存在內(nèi)存輸出流對象中
		while ((temp = input.read())!= -1){                                //每次讀取一個數(shù)據(jù)
			//將讀取進來的數(shù)據(jù)轉(zhuǎn)換為大寫字母,利用Character.toUpperCase()可以保證只轉(zhuǎn)換字母 	
			output.write(Character.toUpperCase(temp));	// 字節(jié)輸出流
		}
		System.out.println(output);
		input.close();	//關(guān)閉輸入流
		output.close();	//關(guān)閉輸出流
	}
}

程序執(zhí)行結(jié)果:

HTTPS://BLOG.CSDN.NET/LVSONGTAO1225

此程序分別利用 ByteArrayInputStreamByteArrayOutputStreamInputStreamOutputStream 類對象實例化,同時在實例化 ByteArrayInputStream 類對象時需要設(shè)置好操作的數(shù)據(jù),這樣才可以利用 InputStream 通過內(nèi)存進行讀取。讀取數(shù)據(jù)時采用循環(huán)的方式,并且為了防止將非字母進行轉(zhuǎn)換的操作,使用了 “Character.toUpperCase()”方法操作。本程序的執(zhí)行流程如下圖所示。

【Java基礎(chǔ)教程】(四十五)IO篇 · 中:轉(zhuǎn)換流、內(nèi)存流和打印流(探索裝飾設(shè)計模式與PrintStream類的進階),文件操作案例實踐、字符編碼問題~,# Java基礎(chǔ)教程,java,設(shè)計模式,開發(fā)語言,學(xué)習(xí),java-ee,jvm,后端
圖4 內(nèi)存流操作流程

范例5的程序是利用子類對象向上轉(zhuǎn)型實現(xiàn)的輸入流與輸出流類對象的實例化操作,這樣操作的好處是可以利用統(tǒng)一的 I0 操作標(biāo)準(zhǔn),但是在 ByteArrayOutputStream 類里面卻會存在一個重要的方法,即通過內(nèi)存輸出流取得全部數(shù)據(jù):

public byte[] toByteArray()

此方法可以將所有暫時保存在內(nèi)存輸出流中的字節(jié)數(shù)據(jù)全部以字節(jié)數(shù)組的形式返回,而利用這樣的方法,就可以實現(xiàn)多個文件的合并讀取操作。

//	范例 6: 實現(xiàn)文件的合并讀取
package com.xiaoshan.demo;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;

public class TestDemo  {
	public static void main(String[] args) throws  Exception{	
		File fileA = new File("D:" + File.separator + "a.txt");   //文件路徑
		File fileB = new File("D:" + File.separator + "b.txt"); 	//文件路徑
		InputStream inputA = new FileInputStream(fileA);		//字節(jié)輸入流
		InputStream inputB = new FileInputStream(fileB);		//字節(jié)輸入流
		ByteArrayOutputStream output = new ByteArrayOutputStream();	//內(nèi)存輸出流
		int temp = 0;		//每次讀取一個字節(jié)
		while ((temp = inputA.read()) != -1){		//循環(huán)讀取數(shù)據(jù)
			output.write(temp);			//將數(shù)據(jù)保存到輸出流
		}
		while ((temp = inputB.read()) != -1){		//循環(huán)讀取數(shù)據(jù)
			output.write(temp);			//將數(shù)據(jù)保存到輸出流
		}
		//現(xiàn)在所有的內(nèi)容都保存在了內(nèi)存輸出流里面,所有的內(nèi)容變?yōu)樽止?jié)數(shù)組取出
		byte data[] = output.toByteArray();		//取出全部數(shù)據(jù)
		output.close();		//關(guān)閉輸出流
		inputA.close();		//關(guān)閉輸入流
		inputB.close();		//關(guān)閉輸入流
		System.out.println(new String(data));	//字節(jié)轉(zhuǎn)換為字符串輸出
	}
}

查看D:\a.txtD:\b.txt 文件內(nèi)容:

【Java基礎(chǔ)教程】(四十五)IO篇 · 中:轉(zhuǎn)換流、內(nèi)存流和打印流(探索裝飾設(shè)計模式與PrintStream類的進階),文件操作案例實踐、字符編碼問題~,# Java基礎(chǔ)教程,java,設(shè)計模式,開發(fā)語言,學(xué)習(xí),java-ee,jvm,后端

程序執(zhí)行結(jié)果:

小山Code:https://lst66.blog.csdn.net
Hello World

此程序首先定義了兩個要讀取的文件路徑,并且利用這兩個路徑分別創(chuàng)建了各自的 InputStream 類實例化對象,由于需要進行文件的合并,所以將所有 InputStream 讀取進來的數(shù)據(jù)都保存在 ByteArrayOutputStream 類對象中。當(dāng)數(shù)據(jù)讀取完畢后,可以直接利用 ByteArrayOutputStream 類中的 toByteArray() 方法將讀取進來的全部數(shù)據(jù)變?yōu)樽址筝敵觥?br>

5?? 打印流

java.io 包中 OutputStream 是進行輸出操作的最核心控制類,但是利用 OutputStream 會存在一個問題:所有的輸出數(shù)據(jù)必須以字節(jié)類型的數(shù)據(jù)為主,也就是說如果現(xiàn)在要輸出的數(shù)據(jù)是 int (Integer)、double(Double)java.util.Date 等常用類型都需要將其轉(zhuǎn)換為字節(jié)后才可以輸出。為了解決這樣的矛盾問題,在 java.io 包中又專門提供了一組打印流(字節(jié)打印流: PrintStream, 字符打印流 :PrintWriter) 方便用戶的輸出操作。

5.1 打印流設(shè)計思想——裝飾設(shè)計模式

java.io.OutputStream 類主要是進行數(shù)據(jù)輸出,如果要設(shè)計更加合適的打印流操作類,就必須解決 OutputStream 輸出數(shù)據(jù)類型有限(只有 byte 類型)的問題。這時可以采用一種包裝設(shè)計的模式,即將 OutputStream 類利用其他類進行包裝,并且在這個類中提供了各種常見數(shù)據(jù)類型的輸出操作,這樣用戶在進行輸出操作時就可以回避字節(jié)數(shù)據(jù)的操作。打印流實現(xiàn)思想如下圖所示。

【Java基礎(chǔ)教程】(四十五)IO篇 · 中:轉(zhuǎn)換流、內(nèi)存流和打印流(探索裝飾設(shè)計模式與PrintStream類的進階),文件操作案例實踐、字符編碼問題~,# Java基礎(chǔ)教程,java,設(shè)計模式,開發(fā)語言,學(xué)習(xí),java-ee,jvm,后端
圖5 打印流設(shè)計思想

可以發(fā)現(xiàn),打印流的核心思想就是首先包裝一個 OutputStream 類的實例化對象,然后在打印流的內(nèi)部自動幫助用戶處理好各種數(shù)據(jù)類型與字節(jié)數(shù)組的轉(zhuǎn)換操作。也就是說 OutputStream 的本質(zhì)功能沒有改變,但是操作的形式變得更加多樣化,也更加方便用戶使用,這樣的設(shè)計就屬于裝飾設(shè)計模式。下面來看打印流代碼的實現(xiàn)。

//	范例 7: 定義打印流工具類
package com.xiaoshan.demo;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

class PrintUtil {		//實現(xiàn)專門的輸出操作功能
	//輸出只能依靠OutputStream
	private OutputStream output;	
	
	/**
	*輸出流的輸出目標(biāo)要通過構(gòu)造方法傳遞
	*@param  output
	*/
	public PrintUtil(OutputStream output){
		this.output = output;
	}
	public void print(int x){	//輸出int型數(shù)據(jù)
		this.print(String.valueOf(x));	//調(diào)用本類字符串的輸出方法
	}
	public void print(String x)(
		try {		//采用OutputStream 類中定義的方法,將字符串轉(zhuǎn)變?yōu)樽止?jié)數(shù)組后輸出
			this.output.write(x.getBytes());
		}  catch(IOException  e){
			e.printStackTrace();
		}
	}
	public void print(double x){	//輸出double型數(shù)據(jù)
		this.print(String.valueOf(x));
	}
	
	public void println(int x){
		this.println(String.valueOf(x));
	}
	public void println(String x){
		this.print(x.concat("\n"));	//輸出數(shù)據(jù)后換行
	}
	public void println(double x){	//輸出double型數(shù)據(jù)
		this.println(String.valueOf(x));
	}
	
	public void close(){	//輸出流關(guān)閉
		try  {
			this.output.close();
		}catch(IOException e){
			e.printStackTrace();
		}
	}
}

public class TestDemo{
	public static void main(String[] args) throws Exception{
		PrintUtil printUtil = new PrintUtil(new FileOutputStream(new File("d:"+ File.separator+ "xiaoshan.txt")));
		printUtil.print("小山的博客:");
		printUtil.println("https://lst66.blog.csdn.net");
		printUtil.println(1+1);
		printUtil.println(1.1 + 1.5);
		printUtil.close();
	}
}

運行結(jié)果:

【Java基礎(chǔ)教程】(四十五)IO篇 · 中:轉(zhuǎn)換流、內(nèi)存流和打印流(探索裝飾設(shè)計模式與PrintStream類的進階),文件操作案例實踐、字符編碼問題~,# Java基礎(chǔ)教程,java,設(shè)計模式,開發(fā)語言,學(xué)習(xí),java-ee,jvm,后端

此程序利用 PrintUtil 類包裝了 OutputStream類,在實例化 PrintStream 類對象時需要傳遞輸出的位置(實際上就是傳遞 OutputStream 類的子類), 這樣就可以利用 PrintUtil 類中提供的一系列方法實現(xiàn)數(shù)據(jù)的輸出操作,而這樣的做法對于客戶端而言是比較容易的,因為客戶端沒有必要再去關(guān)心數(shù)據(jù)類型的轉(zhuǎn)換操作。

但是從實際的開發(fā)來講,面對的數(shù)據(jù)類型可能會有多種,如果這樣的工具類全部都由用戶自己來實現(xiàn),那么明顯是不現(xiàn)實的,為此 java.io 包提供了專門的打印流處理類: PrintStreamPrintWriter。

5.2 打印流

OutputStream 提供了核心的數(shù)據(jù)輸出操作標(biāo)準(zhǔn),但是為了更方便地實現(xiàn)輸出操作, java.io 包提供了兩個數(shù)據(jù)打印流的操作類: PrintStream (打印字節(jié)流)、PrintWriter(打印字符流)。以PrintStream 類為例,此類的繼承結(jié)構(gòu)如下所示:

【Java基礎(chǔ)教程】(四十五)IO篇 · 中:轉(zhuǎn)換流、內(nèi)存流和打印流(探索裝飾設(shè)計模式與PrintStream類的進階),文件操作案例實踐、字符編碼問題~,# Java基礎(chǔ)教程,java,設(shè)計模式,開發(fā)語言,學(xué)習(xí),java-ee,jvm,后端
圖6 PrintStream 繼承結(jié)構(gòu)

下面列出了PrintStream 類的常用操作方法。

方法 類型 說明
public PrintStream(OutputStream out) 構(gòu)造方法 通過已有OutputStream確定輸出目標(biāo)
public void print(數(shù)據(jù)類型 參數(shù)名稱) 普通方法 輸出各種常見數(shù)據(jù)類型
public void println(數(shù)據(jù)類型 參數(shù)名稱) 普通方法 輸出各種常見數(shù)據(jù)類型,并追加一個換行

可以發(fā)現(xiàn), PrintStream ( 或 PrintWriter) 類中提供了一系列 print()println() 方法,并且這些方法適合各種常見數(shù)據(jù)類型的輸出 (例如: int、doublelong、Object 等)。而這些方法就相當(dāng)于為用戶隱藏了 OutputStream 類中的 write()方法,即將原本的 OutputStream 類的功能進行包裝,在保持原方法功能不變的情況下,提供更方便的操作,這就是裝飾設(shè)計模式的體現(xiàn)。

//	范例 8: 使用 PrintStream 類實現(xiàn)輸出
package com.xiaoshan.demo;

import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintStream;

public class TestDemo {
	public static void main(String[] args) throws Exception{
		//實例化PrintStream類對象,本次利用FileOutputStream類實例化PrintStream類對象 
		PrintStream pu = new PrintStream(new FileOutputStream(new File("d:" + File.separator + "xiaoshan.txt")));
		pu.print("小山的博客:");
		pu.println("https://lst66.blog.csdn.net");
		pu.println(1+1);
		pu.println(1.1+1.5);
		pu.close();
	}
}

此程序在實例化 PrintStream 類對象時傳遞了一個 FileOutputStream 類對象,表示將進行文件內(nèi)容的輸出,隨后調(diào)用了PrintStream 類中的 print()println()兩個方法進行文件內(nèi)容的輸出。

實際上在上一節(jié)中所講解的內(nèi)容就是 PrintStream(PrintWriter) 類的實現(xiàn)原理,也講解了為什么在 PrintStream 類的對象實例化中需要使用OutputStream的子類。 本類設(shè)計屬于裝飾設(shè)計模式,即將原本功能不足的類使用另外一個類包裝,并提供更多更方便的操作方法。

5.3 PrintStream 類的改進

PrintStram 類在最初設(shè)計時主要是為了彌補 OutputStream 輸出類的功能不足,但是從JDK 1.5開始, Java 為 PrintStream 增加了格式化輸出的支持方法:

public PrintStream printf(String format, Object... args)

利用這些方法可以使用像 C 語言那樣的數(shù)據(jù)標(biāo)記實現(xiàn)內(nèi)容填充,常見的輸出標(biāo)記為:整數(shù) (%d)、 字符串 (%s)、小數(shù) (%m.nf)、字符 ( %c)。

//	范例 9:格式化輸出
package com.xiaoshan.demo;

import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintStream;

public class TestDemo{
	public static void main(String[] args) throws Exception{
		String name = "小山";
		int age =19;
		double score = 59.95891023456;
		PrintStream pu = new PrintStream(new FileOutputStream(new File("d:" + File.separator + "xiaoshan.txt")));
		pu.printf("姓名:%s, 年齡:%d, 成績:%5.2f", name, age, score); 
		pu.close();
	}
}

運行結(jié)果:

【Java基礎(chǔ)教程】(四十五)IO篇 · 中:轉(zhuǎn)換流、內(nèi)存流和打印流(探索裝飾設(shè)計模式與PrintStream類的進階),文件操作案例實踐、字符編碼問題~,# Java基礎(chǔ)教程,java,設(shè)計模式,開發(fā)語言,學(xué)習(xí),java-ee,jvm,后端

此程序利用 printf() 進行了格式化輸出操作,在輸出字符串時使用了一系列占位符進行標(biāo)記,由于 printf() 方法中設(shè)置的參數(shù)使用了可變參數(shù)類型,所以只需要根據(jù)參數(shù)意義依次傳遞數(shù)據(jù)即可,同時在格式化操作中還具備四舍五入的功能 (本次使用的是“%5.2f”, 表示整數(shù)位為3位,小數(shù)位為2位,一共5位)。

從JDK 1.5開始在String類中也提供了一個格式化字符串的方法,即格式化字符串:

public static String format(String format, Object... args)

由于format()方法使用了static進行定義,所以可以直接利用String類調(diào)用,在本方法使用中需要傳遞數(shù)據(jù)的標(biāo)記與相應(yīng)的數(shù)據(jù)才可以實現(xiàn)最終顯示結(jié)果的拼湊。此方法在《【Java基礎(chǔ)教程】(九)面向?qū)ο笃?· 第三講:深入探究String類——實例化方式及其區(qū)別、字符串常量說明、享元設(shè)計模式解析、不可改變性特征以及String類的常用方法~》一文中已經(jīng)詳細講解過,此處不再過多介紹。

?? 總結(jié)

在本文中,我們深入研究了幾個與文件和字符編碼有關(guān)的主題。首先,我們討論了轉(zhuǎn)換流,它提供了在字節(jié)流和字符流之間進行字符編碼轉(zhuǎn)換的功能。通過使用InputStreamReaderOutputStreamWriter,我們可以將字節(jié)流轉(zhuǎn)換為字符流,并在不同的字符編碼之間進行轉(zhuǎn)換。

接下來,我們通過一個案例演示了如何使用轉(zhuǎn)換流實現(xiàn)文件復(fù)制。這個案例展示了轉(zhuǎn)換流在處理大文件時的效率優(yōu)勢,并且通過適當(dāng)?shù)鼐彌_數(shù)據(jù)提高了性能。

我們還探討了內(nèi)存流,它是基于內(nèi)存操作的流類型。內(nèi)存流允許我們在內(nèi)存中讀寫數(shù)據(jù),而無需依賴于物理存儲介質(zhì)。這對于一些特殊應(yīng)用場景,例如內(nèi)存數(shù)據(jù)交換或緩存操作非常有用。

最后,我們介紹了打印流及其設(shè)計思想——裝飾設(shè)計模式。通過PrintStream類,我們可以方便地輸出各種類型的數(shù)據(jù)到控制臺或文件。并且我們提到了PrintStream類的改進,它提供了更多的輸出選項,例如自動刷新、格式化輸出和異常處理等特性。

通過學(xué)習(xí)轉(zhuǎn)換流、案例:文件復(fù)制、字符編碼、內(nèi)存流和打印流,我們拓寬了處理文件和字符編碼的技能。同時,我們了解到了裝飾設(shè)計模式在打印流中的應(yīng)用。這些知識可以幫助我們處理不同類型的數(shù)據(jù)和特殊場景的需求,并提高代碼的可讀性和靈活性。


? 溫習(xí)回顧上一篇(點擊跳轉(zhuǎn))
《【Java基礎(chǔ)教程】(四十四)IO篇 · 上:解析Java文件操作——File類、字節(jié)流與字符流,分析字節(jié)輸出流、字節(jié)輸入流、字符輸出流和字符輸入流的區(qū)別》

? 繼續(xù)閱讀下一篇(點擊跳轉(zhuǎn))
《【Java基礎(chǔ)教程】(四十六)IO篇 · 下:System類對IO的支持:錯誤輸出、信息輸出、系統(tǒng)輸入,字符緩沖流、掃描流和對象序列化流~》
文章來源地址http://www.zghlxwxcb.cn/news/detail-603913.html

【Java基礎(chǔ)教程】(四十五)IO篇 · 中:轉(zhuǎn)換流、內(nèi)存流和打印流(探索裝飾設(shè)計模式與PrintStream類的進階),文件操作案例實踐、字符編碼問題~,# Java基礎(chǔ)教程,java,設(shè)計模式,開發(fā)語言,學(xué)習(xí),java-ee,jvm,后端

到了這里,關(guān)于【Java基礎(chǔ)教程】(四十五)IO篇 · 中:轉(zhuǎn)換流、內(nèi)存流和打印流(探索裝飾設(shè)計模式與PrintStream類的進階),文件操作案例實踐、字符編碼問題~的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 【Java基礎(chǔ)教程】(四十七)網(wǎng)絡(luò)編程篇:網(wǎng)絡(luò)通訊概念,TCP、UDP協(xié)議,Socket與ServerSocket類使用實踐與應(yīng)用場景~

    【Java基礎(chǔ)教程】(四十七)網(wǎng)絡(luò)編程篇:網(wǎng)絡(luò)通訊概念,TCP、UDP協(xié)議,Socket與ServerSocket類使用實踐與應(yīng)用場景~

    了解多線程與網(wǎng)絡(luò)編程的操作關(guān)系; 了解網(wǎng)絡(luò)程序開發(fā)的主要模式; 了解 TCP 程序的基本實現(xiàn); 在Java中,網(wǎng)絡(luò)編程的核心意義是實現(xiàn)不同電腦主機之間的數(shù)據(jù)交互。Java采用了一種簡化的概念,將這個過程進一步抽象為JVM(Java虛擬機)進程之間的通信??梢栽谕慌_電腦上

    2024年02月15日
    瀏覽(98)
  • 【從零開始學(xué)習(xí)JAVA | 第三十五篇】IO流綜合練習(xí)

    【從零開始學(xué)習(xí)JAVA | 第三十五篇】IO流綜合練習(xí)

    目錄 前言: 1.拷貝文件(含子文件) 思路: 2.文件加密 思路: 3.修改文件中的數(shù)據(jù): 思路: 總結(jié): ? ? ? ? 在前面我們?yōu)榇蠹医榻B了FILE類和IO類。這篇文章我們來練習(xí)一些綜合使用的例子以此來鞏固我們自己的所學(xué)知識。 建立一個讀文件的流來讀取文件,一個寫文件的流

    2024年02月14日
    瀏覽(88)
  • C++IO流和類型處理(13)

    C++IO流和類型處理(13)

    IO流包括 標(biāo)準(zhǔn)IO流,字符串流,文件流 基礎(chǔ)使用 C++預(yù)定義的類和函數(shù)參考手冊:https://zh.cppreference.com/w/cpp 成員函數(shù) C語言的字符串處理庫函數(shù) 字符指針 ------- char * C++預(yù)定義了string類來表示字符串 構(gòu)造初始化 重載的運算符 成員函數(shù) 完善寫的mystring類 重載實現(xiàn) + += == [] = 添加

    2024年02月11日
    瀏覽(11)
  • 【Java基礎(chǔ)教程】(四十二)多線程篇 · 上:多進程與多線程、并發(fā)與并行的關(guān)系,多線程的實現(xiàn)方式、線程流轉(zhuǎn)狀態(tài)、常用操作方法解析~

    【Java基礎(chǔ)教程】(四十二)多線程篇 · 上:多進程與多線程、并發(fā)與并行的關(guān)系,多線程的實現(xiàn)方式、線程流轉(zhuǎn)狀態(tài)、常用操作方法解析~

    理解進程與線程的區(qū)別; 掌握Java 中多線程的兩種實現(xiàn)方式及區(qū)別; 掌握線程的基本操作方法; 進程是程序的一次動態(tài)執(zhí)行過程,它經(jīng)歷了從代碼加載、執(zhí)行到執(zhí)行完畢的一個完整過程,這個過程也是進程本身從產(chǎn)生、發(fā)展到最終消亡的過程 。多進程操作系統(tǒng)能同時運行多

    2024年02月16日
    瀏覽(30)
  • 10 | Tensorflow io流和 tfrecord讀取操作

    tf.io 模塊是 TensorFlow 中用于處理輸入輸出(I/O)操作的工具模塊,提供了許多常見的函數(shù),用于讀寫文件、處理圖像、序列化和反序列化數(shù)據(jù)等。以下是一些常見的 tf.io 模塊中的函數(shù): 文件操作 : tf.io.read_file(file) :讀取文件內(nèi)容。 tf.io.write_file(file, contents) :將內(nèi)容寫入文

    2024年01月20日
    瀏覽(14)
  • IO流 p5 節(jié)點流和處理流

    IO流 p5 節(jié)點流和處理流

    目錄 節(jié)點流 和 處理流 一、基本介紹 二、節(jié)點流 和 處理流 的區(qū)別和聯(lián)系 三、處理流的功能主要體現(xiàn)在以下兩個方面: 四、處理流 — BufferedReader和BufferedWriter 節(jié)點流和處理流一覽圖: ?【圖片來源】http://t.csdn.cn/d52a1 節(jié)點流: 節(jié)點流可以從一個特定的數(shù)據(jù)源 讀寫數(shù)據(jù) ,

    2024年02月08日
    瀏覽(13)
  • 【Java基礎(chǔ)教程】(十五)面向?qū)ο笃?· 第九講:抽象類和接口——定義、限制與應(yīng)用的細節(jié),初窺模板設(shè)計模式、工廠設(shè)計模式與代理設(shè)計模式~

    【Java基礎(chǔ)教程】(十五)面向?qū)ο笃?· 第九講:抽象類和接口——定義、限制與應(yīng)用的細節(jié),初窺模板設(shè)計模式、工廠設(shè)計模式與代理設(shè)計模式~

    掌握 抽象類和接口的定義、使用、區(qū)別、常見設(shè)計模式; 抽象類是代碼開發(fā)中的重要組成部分,利用抽象類可以明確地定義子類需要覆寫的方法,這樣相當(dāng)于在語法程度上對子類進行了嚴(yán)格的定義限制,代碼的開發(fā)也就更加標(biāo)準(zhǔn)。下面具體介紹抽象類的概念。 普通類可以直

    2024年02月16日
    瀏覽(26)
  • 四十五、時間/空間復(fù)雜度分析

    四十五、時間/空間復(fù)雜度分析

    (1)看循環(huán) 一層循環(huán)為O(N),兩層循環(huán)為O(n^2) 不包含輸入輸出所必須的循環(huán) 若兩個循環(huán),不互相嵌套,分別為m與n,則為O(m+n) (2)看遞歸 主定理,不適用太麻煩 例如快排與歸并排序: 一共logn層,每一層是O(N)的時間復(fù)雜度,則總復(fù)雜度為O(nlogn) (3)一些看似為O(n^2),但實

    2024年02月13日
    瀏覽(20)
  • 【LeetCode75】第四十五題 重新規(guī)劃路線

    【LeetCode75】第四十五題 重新規(guī)劃路線

    目錄 題目: 示例: 分析: 代碼: 給我們一個表示城市連通情況的有向圖,要求每個城市都要可以通向0號城市,不同城市之間只有一條路線,我們每次可以改變一條路線的指向,問我們需要操作多少次才可以達到每個城市都可以通向0號城市的要求。 由于不同城市之間只有

    2024年02月10日
    瀏覽(17)
  • web學(xué)習(xí)筆記(四十五)Node.js

    web學(xué)習(xí)筆記(四十五)Node.js

    目錄 1. Node.js 1.1 什么是Node.js 1.2 為什么要學(xué)node.js 1.3??node.js的使用場景 1.4 Node.js 環(huán)境的安裝 1.5 如何查看自己安裝的node.js的版本 1.6 常用終端命令 2. fs 文件系統(tǒng)模塊 2.1引入fs核心模塊 2.2?讀取指定文件的內(nèi)容 2.3??向文件寫入指定內(nèi)容 2.4 創(chuàng)建文件夾? 2.5 判斷文件夾是否存

    2024年04月16日
    瀏覽(31)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包