IO流上:概述、字符流、緩衝區(java基礎)
一、IO流概述
概述:
IO流簡單來說就是Input和Output流,IO流主要是用來處理設備之間的數據傳輸, java對於數據的操作都是通過流實現,而java用於操作流的對象都在IO包中。
分類:
按操作數據分爲:字節流和字符流。 如:Reader和InpurStream
按流向分:輸入流和輸出流。如:InputStream和OutputStream
IO流常用的基類:
* InputStream , OutputStream
字符流的抽象基類:
* Reader , Writer
由上面四個類派生的子類名稱都是以其父類名作爲子類的後綴:
如:FileReader和FileInputStream
二、字符流
1. 字符流簡介:
字符流中的對象融合了編碼表,也就是系統默認的編碼表。我們的系統一般都是GBK編碼。
字符流只用來處理文本數據,字節流用來處理媒體數據。
數據最常見的表現方式是文件,字符流用於操作文件的子類一般是FileReader和FileWriter。
2.字符流讀寫:
注意事項:
寫入文件後必須要用flush()刷新。
用完流後記得要關閉流
使用流對象要拋出IO異常
定義文件路徑時,可以用“/”或者“\”。
在創建一個文件時,如果目錄下有同名文件將被覆蓋。
在讀取文件時,必須保證該文件已存在,否則出異常
示例1:在硬盤上創建一個文件,並寫入一些文字數據
class FireWriterDemo {
public static void main(String[] args) throws IOException { //需要對IO異常進行處理
//創建一個FileWriter對象,該對象一被初始化就必須要明確被操作的文件。
//而且該文件會被創建到指定目錄下。如果該目錄有同名文件,那麼該文件將被覆蓋。
FileWriter fw = new FileWriter("F:\\1.txt");//目的是明確數據要存放的目的地。
//調用write的方法將字符串寫到流中
fw.write("hello world!");
//刷新流對象緩衝中的數據,將數據刷到目的地中
fw.flush();
//關閉流資源,但是關閉之前會刷新一次內部緩衝中的數據。當我們結束輸入時候,必須close();
fw.write("first_test");
fw.close();
//flush和close的區別:flush刷新後可以繼續輸入,close刷新後不能繼續輸入。
}
}
示例2:FileReader的reade()方法.
要求:用單個字符和字符數組進行分別讀取
class FileReaderDemo {
public static void main(String[] args) {
characters();
}
/*****************字符數組進行讀取*********************/
private static void characters() {
try {
FileReader fr = new FileReader("Demo.txt");
char [] buf = new char[6];
//將Denmo中的文件讀取到buf數組中。
int num = 0;
while((num = fr.read(buf))!=-1) {
//String(char[] value , int offest,int count) 分配一個新的String,包含從offest開始的count個字符
sop(new String(buf,0,num));
}
sop('\n');
fr.close();
}
catch (IOException e) {
sop(e.toString());
}
}
/*****************單個字母讀取*************************/
private static void singleReader() {
try {
//創建一個文件讀取流對象,和指定名稱的文件關聯。
//要保證文件已經存在,否則會發生異常:FileNotFoundException
FileReader fr = new FileReader("Demo.txt");
//如何調用讀取流對象的read方法?
//read()方法,一次讀取一個字符,並且自動往下讀。如果到達末尾則返回-1
int ch = 0;
while ((ch=fr.read())!=-1) {
sop((char)ch);
}
sop('\n');
fr.close();
/*int ch = fr.read();
sop("ch=" + (char)ch);
int ch2 = fr.read();
sop("ch2=" + (char)ch2);
//使用結束注意關閉流
fr.close(); */
}
catch (IOException e) {
sop(e.toString());
}
}
/**********************Println************************/
private static void sop(Object obj) {
System.out.print(obj);
}
}
示例3:對已有文件的數據進行續寫
import java.io.*;
class FileWriterDemo3 {
public static void main(String[] args) {
try {
//傳遞一個參數,代表不覆蓋已有的數據。並在已有數據的末尾進行數據續寫
FileWriter fw = new FileWriter("F:\\java_Demo\\day9_24\\demo.txt",true);
fw.write(" is charactor table?");
fw.close();
}
catch (IOException e) {
sop(e.toString());
}
}
/**********************Println************************/
private static void sop(Object obj)
{
System.out.println(obj);
}
}
練習:
將F盤的一個文件複製到E盤。
思考:
其實就是將F盤下的文件數據存儲到D盤的一個文件中。
步驟:
1.在D盤創建一個文件,存儲F盤中文件的數據。
2.定義讀取流和F:盤文件關聯。
3.通過不斷讀寫完成數據存儲。
4.關閉資源。
源碼:
import java.io.*;
import java.util.Scanner;
class CopyText {
public static void main(String[] args) throws IOException {
sop("請輸入要拷貝的文件的路徑:");
Scanner in = new Scanner(System.in);
String source = in.next();
sop("請輸入需要拷貝到那個位置的路徑以及生成的文件名:");
String destination = in.next();
in.close();
CopyTextDemo(source,destination);
}
/*****************文件Copy*********************/
private static void CopyTextDemo(String source,String destination) {
try {
FileWriter fw = new FileWriter(destination);
FileReader fr = new FileReader(source);
char [] buf = new char[1024];
//將Denmo中的文件讀取到buf數組中。
int num = 0;
while((num = fr.read(buf))!=-1) {
//String(char[] value , int offest,int count) 分配一個新的String,包含從offest開始的count個字符
fw.write(new String(buf,0,num));
}
fr.close();
fw.close();
}
catch (IOException e) {
sop(e.toString());
}
}
/**********************Println************************/
private static void sop(Object obj) {
System.out.println(obj);
}
}
三、緩衝區
1. 字符流的緩衝區:BufferedReader和BufferedWreiter
緩衝區的出現時爲了提高流的操作效率而出現的.
需要被提高效率的流作爲參數傳遞給緩衝區的構造函數
在緩衝區中封裝了一個數組,存入數據後一次取出
BufferedReader示例:
讀取流緩衝區提供了一個一次讀一行的方法readline,方便對文本數據的獲取。
readline()只返回回車符前面的字符,不返回回車符。如果是複製的話,必須加入 newLine(),寫入回車符
newLine()是java提供的多平臺換行符寫入方法。
import java.io.*;
class BufferedReaderDemo {
public static void main(String[] args) throws IOException {
//創建一個字符讀取流流對象,和文件關聯
FileReader rw = new FileReader("buf.txt");
//只要將需要被提高效率的流作爲參數傳遞給緩衝區的構造函數即可
BufferedReader brw = new BufferedReader(rw);
for(;;) {
String s = brw.readLine();
if(s==null) break;
System.out.println(s);
}
brw.close();//關閉輸入流對象
}
}
BufferedWriter示例:
import java.io.*;
class BufferedWriterDemo {
public static void main(String[] args) throws IOException {
//創建一個字符寫入流對象
FileWriter fw = new FileWriter("buf.txt");
//爲了提高字符寫入效率,加入了緩衝技術。
//只要將需要被提高效率的流作爲參數傳遞給緩衝區的構造函數即可
BufferedWriter bfw = new BufferedWriter(fw);
//bfw.write("abc\r\nde");
//bfw.newLine(); 這行代碼等價於bfw.write("\r\n"),相當於一個跨平臺的換行符
//用到緩衝區就必須要刷新
for(int x = 1; x < 5; x++) {
bfw.write("abc");
bfw.newLine(); //java提供了一個跨平臺的換行符newLine();
bfw.flush();
}
bfw.flush(); //刷新緩衝區
bfw.close(); //關閉緩衝區,但是必須要先刷新
//注意,關閉緩衝區就是在關閉緩衝中的流對象
fw.close(); //關閉輸入流對象
}
}
2.裝飾設計模式
裝飾設計模式:
要求:自定義一些Reader類,讀取不同的數據(裝飾和繼承的區別)
MyReader //專門用於讀取數據的類
|–MyTextReader
|–MyBufferTextReader
|–MyMediaReader
|–MyBufferMediaReader
|–MyDataReader
|–MyBufferDataReader
如果將他們抽取出來,設計一個MyBufferReader,可以根據傳入的類型進行增強
ass MyBufferReader {
MyBufferReader (MyTextReader text) { }
MyBufferReader (MyMediaReader media) { }
MyBufferReader (MyDataReader data) { }
}
但是上面的類拓展性很差。找到其參數的共同類型,通過多態的形式,可以提高拓展性
class MyBufferReader extends MyReader{
private MyReader r; //從繼承變爲了組成模式 裝飾設計模式
MyBufferReader(MyReader r) {}
}
優化後的體系:
|–MyTextReader
|–MyMediaReader
|–MyDataReader
|–MyBufferReader //增強上面三個。裝飾模式比繼承靈活,
避免繼承體系的臃腫。降低類與類之間的耦合性
裝飾類只能增強已有的對象,具備的功能是相同的。所以裝飾類和被裝飾類屬於同一個體系
MyBuffereReader類: 自己寫一個MyBuffereReader類,功能與BuffereReader相同
class MyBufferedReader1 extends Reader{
private Reader r;
MyBufferedReader1(Reader r){
this.r = r;
}
//一次讀一行數據的方法
public String myReaderline() throws IOException {
//定義一個臨時容器,原BufferReader封裝的是字符數組。
//爲了演示方便。定義一個StringBuilder容器。最終要將數據變成字符串
StringBuilder sb = new StringBuilder();
int ch = 0;
while((ch = r.read()) != -1)
{
if(ch == '\r')
continue;
if(ch == '\n') //遇到換行符\n,返回字符串
return sb.toString();
else
sb.append((char)ch);
}
if(sb.length()!=0) //當最後一行不是以\n結束時候,這裏需要判斷
return sb.toString();
return null;
}
/*
需要覆蓋Reader中的抽象方法close(),read();
*/
public void close()throws IOException {
r.close();
}
public int read(char[] cbuf,int off, int len)throws IOException { //覆蓋read方法
return r.read(cbuf,off,len);
}
public void myClose() throws IOException{
r.close();
}
}
轉載自:
https://www.cnblogs.com/xll1025/p/6418766.htmlc
https://blog.csdn.net/u010041075/article/details/49007731