-------android培訓(xùn)java培訓(xùn)期待與您交流!----------
介紹
- IO流用來處理設(shè)備之間的數(shù)據(jù)傳輸仁连。
- Java對數(shù)據(jù)的操作時通過流的方式饭冬。
- Java用于操作流的對象都在IO包中昌抠。
- 流按操作數(shù)據(jù)分為兩種:字節(jié)流(通用炊苫。二進(jìn)制)與字符流(一般用于文本)姐直。
- 流按流向分為:輸入流與輸出流声畏。
IO流常用基類
- 字節(jié)流的抽象基類:
InputStream插龄、OuputStream
- 字符流的抽象基類:
Reader、Writer
注意:這四個抽象類派生出來的子類名稱都是以其父類名作為子類名的后綴徘跪。 如:InputStream的子類FileInputStrream垮庐、Reader的子類FileReader哨查;名稱前半部分代表功能,后半部分代表父類名剧辐。
IO字符流寫的基本流程
package com.sergio.IO;
import java.io.FileWriter;
import java.io.IOException;
/**
* IO字符流中文件寫的基本流程
* Created by Sergio on 2015-03-01.
*/
public class FileWriterDemo {
public static void main(String[] args) throws IOException {
//創(chuàng)建FileWriter對象寒亥,必要有初始化的一個文件
//該文件會被創(chuàng)建到指定目錄下邮府,如果有同名文件,就會被覆蓋
FileWriter fw = new FileWriter("demo.txt'");
//將字符串寫入到流當(dāng)中溉奕,
fw.write("abcdef");
//刷新流對象中的緩沖中的數(shù)據(jù)挟纱,將數(shù)據(jù)刷到目的地中
fw.flush();
//關(guān)閉流資源,但是關(guān)閉之前會刷新一次內(nèi)部的緩存中的數(shù)據(jù)腐宋,將數(shù)據(jù)刷到目的地中
//和flush區(qū)別:此刷新后胸竞,流可以繼續(xù)使用校赤;close刷新后怜奖,會將流關(guān)閉
fw.close();
}
}
IO流的異常處理方式
package com.sergio.IO;
import java.io.FileWriter;
import java.io.IOException;
/**
*IO異常的處理方式
* Created by Sergio on 2015-03-01.
*/
public class IOExceptionProcess {
public static void main(String[] args) {
//定義在try塊里面后面的finally找不到此變量岖圈,又因為全部定義在try外面又因為要撲捉異常崇摄,
// 所以定義在外邊并定義為null厕氨,需要用的時候進(jìn)行對象變量創(chuàng)建国葬。
FileWriter fw = null;
try {
fw = new FileWriter("demo.txt");
fw.write("abcdef");
fw.close();
}catch (IOException o)
{
System.out.println(o.toString());
}finally {
if (fw != null) //判斷不為null非常需要{
try {
fw.close();//最后必須執(zhí)行的步驟
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
IO字符流文件的寫入和續(xù)寫
fw = new FileWriter("demo.txt", true);//在當(dāng)前路徑的文件中添加新內(nèi)容序宦,不抹除舊內(nèi)容,追加在舊內(nèi)容之后
fw.write("ni\r\nhao!");//在windows平臺上換行的操作\r\n
IO字符流文件的讀取
- 第一種讀取方式。文件讀取方式。每次讀取文件是讀取一個字符打印一次,直到讀取打印完畢。
package com.sergio.IO;
import java.io.FileReader;
import java.io.IOException;
/**
* 文件讀取方式测垛。每次讀取文件是讀取一個字符打印一次链快,直到讀取打印完畢筑累。
* Created by Sergio on 2015-03-09.
*/
public class FileReaderDemo {
public static void main(String[] args) throws IOException {
//創(chuàng)建一個文件讀取對象迅细,和指定名稱的文件相關(guān)聯(lián)
//需要保證文件是已經(jīng)存在的彩倚,如果不存在,會發(fā)生異常:FileNotFoundException
FileReader fr = new FileReader("demo.txt");
int ch = 0;
//每次讀取一個字符们妥。文件讀到末尾會有個一個結(jié)束標(biāo)志鲜漩,平臺不同標(biāo)志不同,而調(diào)用java的會返回 -1這個值告訴文件讀取完畢了蔽氨。
while ((ch = fr.read()) != -1)
{
System.out.println((char)ch);
}
fr.close();
}
}
- 第二種方式绍妨。定義一個數(shù)組用來存儲讀取字符行施,讀取一次存一次,直到讀取完成后在一次性打印埂软。
package com.sergio.IO;
import java.io.FileReader;
import java.io.IOException;
/**
* 文件讀取的第二種方式。定義一個數(shù)組用來讀取一個字符存一次伍绳,讀取一次存一次辐啄,知道讀取完成后在一次性打印
* Created by Sergio on 2015-03-22.
*/
public class FileReaderDemo2 {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("demo.txt");
//定義一個字符數(shù)組,用于存儲獨(dú)到的字符一般建議為1024的倍數(shù)
//讀read(char[])返回的是讀到的字符個數(shù)
char[] buf = new char[1024];
int num = 0;
while ((num = fr.read(buf)) != -1)
{
System.out.print(new String(buf, 0 ,num));//打印字符串從0角標(biāo)開始打印num個,也就是讀取到的字符串的長度
}
fr.close();
}
}
文件的復(fù)制
- 原理:將需要復(fù)制的文件存儲到目標(biāo)存儲路徑下。
- 步驟為:在將要存儲的路徑下創(chuàng)建一個文件,用來存儲需要復(fù)制的文件;定義讀取流和需要復(fù)制的文件關(guān)聯(lián)贿肩;通過不斷的讀寫完成數(shù)據(jù)存儲;關(guān)閉資源。
package com.sergio.IO;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/**
* 文件復(fù)制的基本流程步驟
* Created by Sergio on 2015-03-22.
*/
public class FileCopyDemo {
public static void main(String[] args) throws IOException {
fileCopyByOneChar();
fileCopyByCharArray();
}
//讀取一個字符寫一次的方式
public static void fileCopyByOneChar() throws IOException {
FileWriter fw = new FileWriter("ImageHelper.txt");
FileReader fr = new FileReader("ImageHelper.java");
int ch = 0;
//循環(huán)讀取單個字符
while ((ch = fr.read()) != -1) {
fw.write(ch);
}
//關(guān)閉寫入讀出流
fw.close();
fr.close();
}
//讀取完文件再一次性寫入文件中
public static void fileCopyByCharArray() {
FileWriter fw = null;
FileReader fr = null;
try {
fw = new FileWriter("copfile2.txt");
fr = new FileReader("ImageHelper.java");
//聲明讀取文件的數(shù)組大小
char[] buf = new char[1024];
//定義讀取文件的長度變量
int len = 0;
//讀取文件并一次性寫入目標(biāo)文件中
while ((len = fr.read(buf)) != -1) {
//按讀取到的文件大小寫入目標(biāo)文件中
fw.write(buf, 0, len);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fr != null) {
try {
fr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fw != null) {
try {
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
緩沖區(qū)字符流
- 按設(shè)定的大小來讀取或者寫入文件良蒸,這些動作都是一次性的晰搀,而不是讀一次寫一次比較浪費(fèi)資源腺毫。出現(xiàn)是為了數(shù)據(jù)的讀寫效率叁熔。
- 字符流對應(yīng)的緩存類為:BufferedWriter和BufferedReader。
- 緩沖區(qū)的出現(xiàn)視為了提高流的操作效率而出現(xiàn)的删铃,必須要和流對象使用。
- 底層原理還是數(shù)組來存儲數(shù)據(jù)兔毒,最后封裝成數(shù)組對象來使用。
- 寫入流緩沖區(qū):
FileWriter fw = new FileWriter("abc.txt");
//將流對象作為參數(shù)傳遞給緩沖區(qū)的構(gòu)造函數(shù)即可
BufferedWriter bufw = new BufferedWriter(fw);
bufw.write("afsdfsd");
//跨平臺的換行方法,
bufw.newLine();
//緩沖區(qū)讀取時一定要有刷新動作
bufw.flush();
//關(guān)閉緩沖區(qū)就是關(guān)閉緩沖區(qū)中的流對象
bufw.close();
- 讀取流緩沖區(qū):
FileReader fr = new FileReader("demo1.txt");
//緩沖區(qū)讀取流
BufferedReader bufr = new BufferedReader(fr);
//創(chuàng)建文件讀取到末尾標(biāo)志值變量
String line = null;
//按行讀取數(shù)據(jù)福贞。讀到文件末尾返回null表示撩嚼。readline方法返回的時候只返回回車符之前的數(shù)據(jù)內(nèi)容,并不返回回車符挖帘。
while ((line = bufr.readLine()) != null) {
System.out.println(line);
}
bufr.close();
- 緩沖區(qū)復(fù)制數(shù)據(jù):
package com.sergio.IO;
import java.io.*;
/**
* 緩沖區(qū)復(fù)制數(shù)據(jù)
* Created by Sergio on 2015-03-24.
*/
public class CopyTextByBuffered {
public static void main(String[] args) {
BufferedReader bufr = null;
BufferedWriter bufw = null;
try {
bufr = new BufferedReader(new FileReader("ImageHelper.java"));
bufw = new BufferedWriter(new FileWriter("abcd.txt"));
String line = null;
while ((line = bufr.readLine()) != null) {
bufw.write(line);
//按行寫入數(shù)據(jù)
bufw.newLine();
bufw.flush();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
//關(guān)閉資源流
finally {
if (bufr != null) {
try {
bufr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (bufw != null) {
try {
bufw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
readLine()方法原理:底層還是
raed()
方法一個字符一個字符來讀取數(shù)據(jù)完丽,只不過讀取到的數(shù)據(jù)都緩沖到緩沖區(qū)中,碰到\r\n
這個轉(zhuǎn)義字符不存入拇舀,確定為換行符后逻族,將讀取到的字符串?dāng)?shù)據(jù)一次性讀取出來。模擬BufferedReader的功能:
package com.sergio.IO;
import java.io.FileReader;
import java.io.IOException;
/**
* Created by Sergio on 2015-03-24.
*/
public class MyBufferedDemo {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("abc.txt");
MyBuffered mf = new MyBuffered(fr);
String line = null;
while ((line = mf.myReaderLine()) != null) {
System.out.println(line);
}
mf.myClose();
}
}
//模仿BufferedReader中的功能
class MyBuffered {
//底層使用到的還是FileReader的讀取方法
private FileReader r;
MyBuffered(FileReader r) {
this.r = r;
}
//按行讀取數(shù)據(jù)
public String myReaderLine() throws IOException {
//定義臨時容器骄崩,原BufferRead封裝的是字符數(shù)組聘鳞。在此定義個StringBuilder
StringBuilder sb = new StringBuilder();
int ch = 0;
while ((ch = r.read()) != -1) {
//讀取到回車符就繼續(xù)讀取文件數(shù)據(jù)
if (ch == '\r') {
continue;
}
//碰到換行符就返回數(shù)據(jù)結(jié)果
if (ch == '\n')
return sb.toString();
else
sb.append((char) ch);
}
//處理最后一行數(shù)據(jù)結(jié)尾沒有換行標(biāo)識的處理方法。也即是緩沖區(qū)中還有數(shù)據(jù)就返回數(shù)據(jù)結(jié)果
if (sb.length() != 0)
return sb.toString();
//讀取完返回null即可刁赖。
return null;
}
public void myClose() throws IOException {
r.close();
}
}
裝飾設(shè)計模式
- 當(dāng)想要對已有的對象進(jìn)行功能增強(qiáng)時搁痛,可以定義類长搀,將已有對象傳入宇弛,基于已有的功能,并提供加強(qiáng)功能源请,那么自定義的該類稱為裝飾類枪芒。
- 裝飾類特點:通常會通過構(gòu)造方法接受被裝飾的對象彻况,并基于被裝飾的對象的功能,提供更強(qiáng)的功能舅踪。
package com.sergio.io;
/**裝飾設(shè)計模式
* Created by Administrator on 2015/4/6.
*/
public class PersonDemo {
public static void main(String[] args) {
Person p = new Person();
SuperPerson su = new SuperPerson(p);
su.superEat();
}
}
//被裝飾類
class Person
{
public void eat()
{
System.out.println("吃飯");
}
}
//裝飾類
class SuperPerson
{
private Person p;
SuperPerson(Person p)
{
this.p = p;
}
//裝飾增強(qiáng)方法
public void superEat()
{
System.out.println("kaiweijiu");
p.eat();
System.out.println("hetan");
}
}
裝飾設(shè)計模式和繼承的區(qū)別
- 裝飾設(shè)計模式比繼承要靈活纽甘,避免了繼承體系臃腫。而且降低了類與類之間的關(guān)系抽碌。
- 裝飾類因為增強(qiáng)已有對象悍赢,具備的功能和已有的是相同的,只不過提供了更強(qiáng)的功能货徙,所以裝飾類和被裝飾類通常都屬于一個體系中左权。
- 通常情況下裝飾類和被裝飾類同屬于一個接口或者同一個類。
* MyReader//專門用于讀取數(shù)據(jù)的類痴颊。這種結(jié)構(gòu)是繼承結(jié)構(gòu)
* |--MyTextReader//用于擴(kuò)展的功能類
* |--MyBufferTextReader//用于對Text讀取的類擴(kuò)展類
* |--MyMediaReader
* |--MyBufferMediaReader
* |--MyDataReader
* |--MyBufferDataReader
*繼承關(guān)系的類的擴(kuò)展寫法赏迟。擴(kuò)展性較差
*class MyBufferReader
*{
* MyBufferReader(MyTextReader text)
* {}
* MyBufferReader(MyMediaReader text)
* {}
* MyBufferReader(MyDataReader text)
* {}
*}
*
* MyReader//專門用于讀取數(shù)據(jù)的類。這種結(jié)構(gòu)是裝飾設(shè)計模式
* |--MyTextReader//用于擴(kuò)展的功能類
* |--MyMediaReader
* |--MyDataReader
* |--MyBufferReader//用于增強(qiáng)讀取各種數(shù)據(jù)功能類的方法類
*
* 設(shè)計模式的寫法
* class MyBufferReader extends MyReader//增強(qiáng)類還是用于讀取數(shù)據(jù)蠢棱,繼承自這個接口锌杀,對原有方法進(jìn)行增強(qiáng)
* {
* private MyReader r;
//需要進(jìn)行增強(qiáng)的功能方法,傳入對象參數(shù)
* MyBufferReader(MyReader r)
* {}
* }
LineNumberReader
- 跟蹤行號的緩沖區(qū)字符輸入流泻仙。默認(rèn)情況下從0開始糕再。帶行號的裝飾類。
package com.sergio.io;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
/**
* LineNumberReader類介紹
* Created by Administrator on 2015/4/6.
*/
public class LineNumberReaderDemo {
public static void main(String[] args) throws IOException{
FileReader fr = new FileReader("PersonDemo.java");
LineNumberReader lnr = new LineNumberReader(fr);
String line = null;
//設(shè)置行號從50開始計數(shù)
lnr.setLineNumber(50);
while ((line = lnr.readLine()) != null)
{
//帶行號打印
System.out.println(lnr.getLineNumber() + line);
}
lnr.close();
}
}
- 自定義實現(xiàn)帶行號的MyLineNumberReader的功能
package com.sergio.IO;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
/**
* 自定義實現(xiàn)帶行號讀取文本的功能
* Created by Sergio on 2015-04-12.
*/
public class MyLineNumberReaderDemo {
public static void main(String[] args) throws IOException{
FileReader fr = new FileReader("abc.txt");
MyLineNumberReader mlnr = new MyLineNumberReader(fr);
String line = null;
while ((line = mlnr.myReadLine()) != null)
{
System.out.println(mlnr.getLineNumber() + line);
}
mlnr.myClose();
}
}
//有一些功能在MyBufferedReader中有實現(xiàn)玉转,可以繼承自它亿鲜,減少代碼量
class MyLineNumberReader extends MyBufferedReader
{
private int LineNumber;
MyLineNumberReader(Reader r) {
super(r);
}
public String myReadLine()throws IOException
{
LineNumber++;
return super.myReaderLine();
}
public int getLineNumber() {
return LineNumber;
}
public void setLineNumber(int lineNumber) {
LineNumber = lineNumber;
}
}
字節(jié)流IO讀寫操作
- 以字節(jié)的方式來讀取操作文件,常操作的文件為媒體性文件冤吨。
package com.sergio.IO;
import javax.print.DocFlavor;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 字節(jié)流的文件的讀取方式
* Created by Sergio on 2015-04-12.
*/
public class FileStream {
public static void main(String[] args) {
}
//字節(jié)流寫入文件
public static void writeFile() throws IOException {
FileOutputStream fos = new FileOutputStream("abc.txt");
fos.write("abdr".getBytes());//轉(zhuǎn)換成字節(jié)
fos.close();
}
//單個讀取文件
public static void readFile_1() throws IOException {
FileInputStream fis = new FileInputStream("abc.txt");
int ch = 0;
while ((ch = fis.read()) != -1) {
System.out.println((char) ch);
}
fis.close();
}
//按定義的數(shù)組的大小來讀取文件蒿柳,推薦的讀取方式
public static void readFile_2() throws IOException {
FileInputStream fis = new FileInputStream("abc.txt");
byte[] buf = new byte[1024];
int len = 0;
while ((len = fis.read(buf)) != -1) {
System.out.println(new String(buf, 0, len));
}
fis.close();
}
//按剛好文件的大小的數(shù)組來讀取文件
public static void readFile_3() throws IOException {
FileInputStream fis = new FileInputStream("abc.txt");
//定義的數(shù)組剛好為文件的大小數(shù)值.但是一般不推薦使用,容易造成內(nèi)存溢出
byte[] buf = new byte[fis.available()];
fis.read(buf);
System.out.println(new String(buf));
fis.close();
}
}
字節(jié)流拷貝圖片
package com.sergio.IO;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* 字節(jié)流拷貝圖片文件
* Created by Sergio on 2015-04-13.
*/
public class CopyPic {
public static void main(String[] args) {
FileOutputStream fos = null;
FileInputStream fis = null;
try {
fos = new FileOutputStream("git-1.jpg");
fis = new FileInputStream("git.jpg");
byte[] buf = new byte[1024];
int len = 0;
while ((len = fis.read(buf)) != -1) {
fos.write(buf, 0, len);
}
} catch (IOException e) {
throw new RuntimeException("復(fù)制文件失敗");
} finally {
try {
if (fis != null) {
fis.close();
}
} catch (IOException e) {
throw new RuntimeException("讀取關(guān)閉失敗");
}
try {
if (fos != null) {
fos.close();
}
} catch (IOException e) {
throw new RuntimeException("寫入關(guān)閉失敗");
}
}
}
}
讀取鍵盤錄入
- System.in:標(biāo)準(zhǔn)的輸入流漩蟆,默認(rèn)為鍵盤垒探。
package com.sergio.IO;
import java.io.IOException;
import java.io.InputStream;
/**
* 讀取鍵盤錄入
* Created by Sergio on 2015-04-14.
*/
public class ReadIn {
public static void main(String[] args) {
InputStream in = System.in;//讀取鍵盤錄入流
//裝在容器
StringBuilder sb = new StringBuilder();
while (true) {
int ch = 0;
try {
ch = in.read();
//度讀取錄入的數(shù)據(jù)進(jìn)行判斷
if (ch == '\r')
continue;
if (ch == '\n') {
String s = sb.toString();
//碰到quit就結(jié)束錄入
if ("quit".equals(s))
break;
//轉(zhuǎn)換成大寫
System.out.println(s.toUpperCase());
//清空緩沖區(qū)
sb.delete(0, sb.length());
} else
sb.append((char) ch);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
讀取轉(zhuǎn)換流(字節(jié)流轉(zhuǎn)換成字符流)
- 將字節(jié)流轉(zhuǎn)換成字符流,可以使用字符流的功能怠李。轉(zhuǎn)換流的方法定義在字符流的體系當(dāng)中圾叼。
package com.sergio.IO;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
/**
* 轉(zhuǎn)換流,字節(jié)流轉(zhuǎn)換成字符流
* Created by Sergio on 2015-04-14.
*/
public class TransStreamDemo {
public static void main(String[] args) {
//獲取鍵盤錄入對象
InputStream in = System.in;
//字節(jié)流轉(zhuǎn)換成字符流
InputStreamReader isr = new InputStreamReader(in);
//提高效率將字符串進(jìn)行緩沖區(qū)技術(shù)搞笑操作捺癞,使用BufferedReader
BufferedReader bufr = new BufferedReader(isr);
String line = null;
try {
while ((line = bufr.readLine()) != null) {
//判斷結(jié)束標(biāo)記
if ("quit".equals(line))
break;
System.out.println(line.toUpperCase());
}
} catch (IOException e) {
e.printStackTrace();
}
try {
bufr.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
字符流轉(zhuǎn)換成字節(jié)流
package com.sergio.IO;
import java.io.*;
/**
* 字符流轉(zhuǎn)換成字節(jié)流
* Created by Sergio on 2015-04-14.
*/
public class TransStringDemo {
public static void main(String[] args) {
// InputStream in = System.in;
// InputStreamReader isr = new InputStreamReader(in);
// BufferedReader bufr = new BufferedReader(isr);三聚簡化成一句
BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
OutputStream out = System.out;
OutputStreamWriter osw = new OutputStreamWriter(out);
//使用BufferedWriter功能中的換行方法
BufferedWriter bufw = new BufferedWriter(osw);
//BufferedWriter bufw = new BufferedWriter(new OutputStreamWriter(System.out));
String line = null;
try {
while ((line = bufr.readLine()) != null) {
if ("quit".equals(line))
break;
bufw.write(line.toUpperCase());
bufw.newLine();
bufw.flush();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
bufr.close();
bufw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
流操作規(guī)律
三個要點規(guī)律:
- 明確源和目的夷蚊。(源:輸入流。目的:輸出流)
- 操作的數(shù)據(jù)是否是文本髓介。(是:字符流惕鼓。不是:字節(jié)流)
- 當(dāng)體系明確后,在明確要使用那個具體的對象唐础。(通過設(shè)備來進(jìn)行區(qū)分箱歧。源設(shè)備:內(nèi)存矾飞、硬盤、鍵盤呀邢。目的設(shè)備:內(nèi)存洒沦、硬盤、控制臺)
改變標(biāo)準(zhǔn)輸入輸出設(shè)備
- 改變標(biāo)準(zhǔn)輸入流:
System.setIn(InputStream in)
价淌。 - 改變數(shù)準(zhǔn)輸出流:
System.setOut(PrintStream out)
申眼。