Java IO

Java IO整理

參考文獻(xiàn)一http://www.cnblogs.com/lich/tag/java%20IO/
參考文獻(xiàn)二http://blog.sina.com.cn/s/blog_7ba28b6201011vv0.html
上圖

File類

實(shí)例一:創(chuàng)建一個(gè)新文件
import java.io.File;
import java.io.IOException;

public class Test1 {
    public static void main(String[] args) {
        File f=new File("d:"+File.separator+"test.txt");//為增加可移植性腌零,建議使用File.separator
        try {
            f.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
實(shí)例二:刪除一個(gè)指定文件
import java.io.File;

public class Test2 {
    public static void main(String[] args) {
        File f=new File("d:"+File.separator+"test.txt");
        if(f.exists()){//判斷文件存不存在上沐,如不存在就不用刪除了
            f.delete();
        }
    }
}
實(shí)例三:綜合創(chuàng)建,刪除文件的操作
import java.io.File;
import java.io.IOException;
//給定一個(gè)路徑胀溺,如果此文件存在膀藐,則刪除罪既,如果不存在凝果,則創(chuàng)建
public class Test3 {
    public static void main(String[] args) {
        File f=new File("d:"+File.separator+"test.txt");
        if(f.exists()){
            f.delete();
        }else{
            try {
                f.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
實(shí)例四:創(chuàng)建一個(gè)文件夾
import java.io.File;
//使用mkdir()方法創(chuàng)建一個(gè)文件夾
public class Test4 {
    public static void main(String[] args) {
        File f=new File("d:"+File.separator+"test");
        f.mkdir();//創(chuàng)建文件夾
    }
}
實(shí)例五:列出指定目錄的全部文件

如果現(xiàn)在給出了一個(gè)目錄,則可以直接列出目錄中的內(nèi)容姐军。但是列出的方法在File類中存在兩個(gè):

  • 以字符串?dāng)?shù)組的形式返回:public String[] list()
  • 以File數(shù)組的形式返回:public File[] listFiles()
  • 以File數(shù)組的形式列出系統(tǒng)所有的根路徑,這是一個(gè)靜態(tài)方法:static File[] listRoots()
    操作一:使用list()列出全部?jī)?nèi)容
import java.io.File;

public class Test5 {
    public static void main(String[] args) {
        File f=new File("d:"+File.separator);
        String[] str=f.list();
        for(String s:str){
            System.out.println(s);
        }
    }
}

操作二:使用listFiles()列出

import java.io.File;

public class Test6 {
    public static void main(String[] args) {
        File f=new File("d:"+File.separator);
        File[] files=f.listFiles();
        for(File file:files){
            System.out.println(file);
        }
    }
}
實(shí)例六:判斷一個(gè)給定的路徑是否是目錄
import java.io.File;

public class Test7 {
    public static void main(String[] args) {
        File f=new File("d:"+File.separator);
        if(f.isDirectory()){
            System.out.println(f.getPath()+"是目錄");
        }else{
            System.out.println(f.getPath()+"不是目錄");
        }
    }
}
實(shí)例七:列出指定目錄的全部?jī)?nèi)容
import java.io.File;

public class Test8 {
    public static void main(String[] args) {
        File f = new File("d:" + File.separator);
        print(f);
    }
    public static void print(File f) {
        if (f != null) {
            if (f.isDirectory()) {
                File[] files = f.listFiles();
                if (files != null) {
                    for (File file : files) {
                            print(file);
                    }
                }
            } else {
                System.out.println(f);
            }
        }
    }
}

總結(jié):

  • File類是在java.io包中唯一與文件本身有關(guān)的
  • 可以使用File類創(chuàng)建尖淘、刪除等常見的文件操作
  • 在使用File類指定路徑的時(shí)候一定要注意操作系統(tǒng)間的差異奕锌,盡量使用separator進(jìn)行分割

RandomAccessFile類

之前的File類只是針對(duì)文件本身進(jìn)行操作的,而如果相對(duì)文件內(nèi)容進(jìn)行操作德澈,則可以使用RandomAccessFile類歇攻,此類屬于隨機(jī)讀取類,可以隨機(jī)的讀取一個(gè)文件中指定位置的數(shù)據(jù)梆造。
因?yàn)樵谖募薪墒兀械脙?nèi)容都是按照字節(jié)存放的,都有固定的保存位置镇辉。

構(gòu)造函數(shù):
public RandomAccessFile(File file,String mode)throws FileNotFoundException
實(shí)例化此類的時(shí)候需要傳遞File類屡穗。告訴程序應(yīng)該操作的是哪個(gè)文件,之后有個(gè)模式忽肛,文件的打開模式村砂,常用的兩種模式:

  • r:讀
  • w:寫
  • rw:讀寫,如果使用此模式屹逛,如果文件不存在础废,則會(huì)自動(dòng)創(chuàng)建

文件記錄指針

  • long getFilePointer():返回文件記錄指針的當(dāng)前位置
  • void seek(long pos):將文件記錄指針定位到pos位置
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;

public class Test9 {
    public static void main(String[] args) throws IOException {
        File f = new File("d:" + File.separator+"test.txt");
        RandomAccessFile raf=new RandomAccessFile(f,"rw");//讀寫模式,如果該路徑不存在會(huì)自動(dòng)創(chuàng)建
        String name1="jim";
        int age1 =20;
        String name2="Tom";
        int age2=30;
        raf.writeBytes(name1);
        raf.writeInt(age1);
        raf.writeBytes(name2);
        raf.writeInt(age2);
        raf.close();
    }
}
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;

public class Test10 {
    public static void main(String[] args) throws IOException {
        File f = new File("d:" + File.separator+"test.txt");
        RandomAccessFile raf=new RandomAccessFile(f,"r");//以讀模式打開
        raf.skipBytes(7);//跳過第一個(gè)人的信息
        byte[] bs=new byte[3];
        for(int i=0;i<bs.length;i++){
            bs[i]=raf.readByte();
        }
        String name2=new String(bs);
        int age2=raf.readInt();
        System.out.println(name2+"  "+age2);
        
        raf.seek(0);//指針回到文件開頭罕模,讀取第二個(gè)人的信息
        for(int i=0;i<bs.length;i++){
            bs[i]=raf.readByte();
        }
        String name1=new String(bs);
        int age1=raf.readInt();
        System.out.println(name1+"  "+age1);
    }
}

字節(jié)流和字符流

先來看一下流的概念:
在程序中所有的數(shù)據(jù)都是以流的方式進(jìn)行傳輸或保存的评腺,程序需要數(shù)據(jù)的時(shí)候要使用輸入流讀取數(shù)據(jù),而當(dāng)程序需要將一些數(shù)據(jù)保存起來的時(shí)候淑掌,就要使用輸出流完成蒿讥。

程序中的輸入輸出都是以流的形式保存的,流中保存的實(shí)際上全都是字節(jié)文件抛腕。

字節(jié)流與字符流

在java.io包中操作文件內(nèi)容的主要有兩大類:字節(jié)流芋绸、字符流,兩類都分為輸入和輸出操作担敌。在字節(jié)流中輸出數(shù)據(jù)主要是使用OutputStream完成摔敛,輸入使的是InputStream,在字符流中輸出主要是使用Writer類完成全封,輸入流主要使用Reader類完成舷夺。(這四個(gè)都是抽象類)

操作流程
在Java中IO操作也是有相應(yīng)步驟的苦酱,以文件操作為例,主要的操作流程如下:

  • 使用File類打開一個(gè)文件
  • 通過字節(jié)流或字符流的子類给猾,指定輸出的位置
  • 進(jìn)行讀/寫操作
  • 關(guān)閉輸入/輸出

IO操作屬于資源操作疫萤,一定要記得關(guān)閉

字節(jié)流

字節(jié)流主要是操作byte類型數(shù)據(jù),以byte數(shù)組為準(zhǔn)敢伸,主要操作類就是OutputStream扯饶、InputStream

字節(jié)輸出流:OutputStream
OutputStream是整個(gè)IO包中字節(jié)輸出流的最大父類,此類的定義如下:
public abstract class OutputStream extends Object implements Closeable,Flushable
從以上的定義可以發(fā)現(xiàn)池颈,此類是一個(gè)抽象類尾序,如果想要使用此類的話,則首先必須通過子類實(shí)例化對(duì)象躯砰,那么如果現(xiàn)在要操作的是一個(gè)文件每币,則可以使用:FileOutputStream類。通過向上轉(zhuǎn)型之后琢歇,可以為OutputStream實(shí)例化
Closeable表示可以關(guān)閉的操作兰怠,因?yàn)槌绦蜻\(yùn)行到最后肯定要關(guān)閉
Flushable:表示刷新,清空內(nèi)存中的數(shù)據(jù)
FileOutputStream類的構(gòu)造方法如下:
public FileOutputStream(File file)throws FileNotFoundException

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
//寫數(shù)據(jù)
public class Test11 {
    public static void main(String[] args) throws IOException {
        File f = new File("d:" + File.separator+"test.txt");
        OutputStream out=new FileOutputStream(f);//如果文件不存在會(huì)自動(dòng)創(chuàng)建
        String str="Hello World";
        byte[] b=str.getBytes();
        out.write(b);//因?yàn)槭亲止?jié)流李茫,所以要轉(zhuǎn)化成字節(jié)數(shù)組進(jìn)行輸出
        out.close();
    }
}
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
//也可以一個(gè)字節(jié)一個(gè)字節(jié)進(jìn)行輸出
public class Test11 {
    public static void main(String[] args) throws IOException {
        File f = new File("d:" + File.separator+"test.txt");
        OutputStream out=new FileOutputStream(f);//如果文件不存在會(huì)自動(dòng)創(chuàng)建
        String str="Hello World";
        byte[] b=str.getBytes();
        for(int i=0;i<b.length;i++){
            out.write(b[i]);
        }
        out.close();
    }
}

public FileOutputStream(File file,boolean append)throws FileNotFoundException
在構(gòu)造方法中揭保,如果將append的值設(shè)置為true,則表示在文件的末尾追加內(nèi)容魄宏。

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

public class Test11 {
    public static void main(String[] args) throws IOException {
        File f = new File("d:" + File.separator+"test.txt");
        OutputStream out=new FileOutputStream(f,true);//追加內(nèi)容
        String str="\r\nHello World";
        byte[] b=str.getBytes();
        for(int i=0;i<b.length;i++){
            out.write(b[i]);
        }
        out.close();
    }
}
字節(jié)輸入流:InputStream

既然程序可以向文件中寫入內(nèi)容秸侣,則就可以通過InputStream從文件中把內(nèi)容讀取進(jìn)來,首先來看InputStream類的定義:
public abstract class InputStream extends Object implements Closeable
與OutputStream類一樣宠互,InputStream本身也是一個(gè)抽象類味榛,必須依靠其子類,如果現(xiàn)在是從文件中讀取予跌,就用FileInputStream來實(shí)現(xiàn)励负。
觀察FileInputStream類的構(gòu)造方法:

public FileInputStream(File file)throws FileNotFoundException
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
//讀文件
public class Test12 {
    public static void main(String[] args) throws IOException {
        File f = new File("d:" + File.separator+"test.txt");
        InputStream in=new FileInputStream(f);
        byte[] b=new byte[1024];
        int len=in.read(b);
        in.close();
        System.out.println(new String(b,0,len));
    }

}

但以上方法是有問題的,用不用開辟這么大的一個(gè)字節(jié)數(shù)組匕得,明顯是浪費(fèi)嘛,我們可以根據(jù)文件的大小來定義字節(jié)數(shù)組的大小巾表,F(xiàn)ile類中的方法:public long length()

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

public class Test13 {
    public static void main(String[] args) throws IOException {
        File f = new File("d:" + File.separator+"test.txt");
        InputStream in=new FileInputStream(f);
        byte[] b=new byte[(int) f.length()];
        in.read(b);
        in.close();
        System.out.println(new String(b));
    }
}
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
//我們換種方式汁掠,一個(gè)字節(jié)一個(gè)字節(jié)讀入
public class Test14 {
    public static void main(String[] args) throws IOException {
        File f = new File("d:" + File.separator+"test.txt");
        InputStream in=new FileInputStream(f);
        byte[] b=new byte[(int) f.length()];
        for(int i=0;i<b.length;i++){
            b[i]=(byte) in.read();
        }
        in.close();
        System.out.println(new String(b));
    }
}
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
//但以上情況只適合知道輸入文件的大小,不知道的話用如下方法:
public class Test15 {
    public static void main(String[] args) throws IOException {
        File f = new File("d:" + File.separator+"test.txt");
        InputStream in=new FileInputStream(f);
        byte[] b=new byte[1024];
        int temp=0;
        int len=0;
        while((temp=in.read())!=-1){//-1為文件讀完的標(biāo)志
            b[len]=(byte) temp;
            len++;
        }
        in.close();
        System.out.println(new String(b,0,len));
    }
}
字符流

在程序中一個(gè)字符等于兩個(gè)字節(jié)集币,那么java提供了Reader考阱、Writer兩個(gè)專門操作字符流的類。

字符輸出流:Writer

Writer本身是一個(gè)字符流的輸出類鞠苟,此類的定義如下:
public abstract class Writer extends Object implements Appendable乞榨,Closeable秽之,F(xiàn)lushable
此類本身也是一個(gè)抽象類,如果要使用此類吃既,則肯定要使用其子類考榨,此時(shí)如果是向文件中寫入內(nèi)容,所以應(yīng)該使用FileWriter的子類鹦倚。
FileWriter類的構(gòu)造方法定義如下:
public FileWriter(File file)throws IOException
字符流的操作比字節(jié)流操作好在一點(diǎn)河质,就是可以直接輸出字符串了,不用再像之前那樣進(jìn)行轉(zhuǎn)換操作了震叙。
寫文件:

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;

public class Test16 {
    public static void main(String[] args) throws IOException {
        File f = new File("d:" + File.separator+"test.txt");
        Writer out=new FileWriter(f);
        String str="Hello World";
        out.write(str);
        out.close();
    }
}
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
//在默認(rèn)情況下再次輸出會(huì)覆蓋掀鹅,追加的方法也是在構(gòu)造函數(shù)上加上追加標(biāo)記
public class Test17 {
    public static void main(String[] args) throws IOException {
        File f = new File("d:" + File.separator+"test.txt");
        Writer out=new FileWriter(f,true);//追加
        String str="\r\nHello World";
        out.write(str);
        out.close();
    }
}
字符輸入流:Reader

Reader是使用字符的方式從文件中取出數(shù)據(jù),Reader類的定義如下:
public abstract class Reader extends Objects implements Readable媒楼,Closeable
Reader本身也是抽象類乐尊,如果現(xiàn)在要從文件中讀取內(nèi)容缓升,則可以直接使用FileReader子類械媒。
FileReader的構(gòu)造方法定義如下:
public FileReader(File file)throws FileNotFoundException
以字符數(shù)組的形式讀取出數(shù)據(jù):

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;

public class Test18 {
    public static void main(String[] args) throws IOException {
        File f = new File("d:" + File.separator+"test.txt");
        Reader input=new FileReader(f);
        char[] c=new char[1024];
        int len=input.read(c);
        input.close();
        System.out.println(new String(c,0,len));
    }
}
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
//也可以用循環(huán)方式,判斷是否讀到底
public class Test19 {
    public static void main(String[] args) throws IOException {
        File f = new File("d:" + File.separator+"test.txt");
        Reader input=new FileReader(f);
        char[] c=new char[1024];
        int temp=0;
        int len=0;
        while((temp=input.read())!=-1){
            c[len]=(char) temp;
            len++;
        }
        input.close();
        System.out.println(new String(c,0,len));
    }
}

字節(jié)流與字符流的區(qū)別
字節(jié)流和字符流使用是非常相似的浑此,那么除了操作代碼的不同之外猴鲫,還有哪些不同呢对人?
字節(jié)流在操作的時(shí)候本身是不會(huì)用到緩沖區(qū)(內(nèi)存)的,是與文件本身直接操作的拂共,而字符流在操作的時(shí)候是使用到緩沖區(qū)的
字節(jié)流在操作文件時(shí)牺弄,即使不關(guān)閉資源(close方法),文件也能輸出宜狐,但是如果字符流不使用close方法的話势告,則不會(huì)輸出任何內(nèi)容,說明字符流用的是緩沖區(qū)抚恒,并且可以使用flush方法強(qiáng)制進(jìn)行刷新緩沖區(qū)咱台,這時(shí)才能在不close的情況下輸出內(nèi)容

那開發(fā)中究竟用字節(jié)流好還是用字符流好呢?
在所有的硬盤上保存文件或進(jìn)行傳輸?shù)臅r(shí)候都是以字節(jié)的方法進(jìn)行的俭驮,包括圖片也是按字節(jié)完成回溺,而字符是只有在內(nèi)存中才會(huì)形成的,所以使用字節(jié)的操作是最多的混萝。

如果要java程序?qū)崿F(xiàn)一個(gè)拷貝功能遗遵,應(yīng)該選用字節(jié)流進(jìn)行操作(可能拷貝的是圖片),并且采用邊讀邊寫的方式(節(jié)省內(nèi)存)逸嘀。

字符-字節(jié)轉(zhuǎn)換流

OutputStreamWriter和InputStreamReader
在整個(gè)IO包中车要,實(shí)際上就是分為字節(jié)流和字符流,但是除了這兩個(gè)流之外崭倘,還存在了一組字節(jié)流-字符流的轉(zhuǎn)換類翼岁。
OutputStreamWriter:是Writer的子類类垫,將輸出的字符流變?yōu)樽止?jié)流,即:將一個(gè)字符流的輸出對(duì)象變成字節(jié)流的輸出對(duì)象琅坡。
InputStreamReader:是Reader的子類悉患,將輸入的字節(jié)流變?yōu)樽址鳎矗簩⒁粋€(gè)字節(jié)流的輸入對(duì)象變成字符流的輸入對(duì)象脑蠕。
一般在操作輸入輸出內(nèi)容就需要使用字節(jié)或字符流购撼,但是有些時(shí)候需要將字符流變成字節(jié)流的形式,或者將字節(jié)流變?yōu)樽址鞯男问角聪桑杂厍螅托枰硗庖唤M轉(zhuǎn)換流的操作類。

看一下OutputStreamWriter的構(gòu)造方法:
public OutputStreamWriter(OutputStream out)

例如晃跺,將字節(jié)的文件輸出流揩局,以字符的形式輸出

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

public class Test20 {
    public static void main(String[] args) throws IOException {
        File f = new File("d:" + File.separator+"test.txt");
        Writer out=new OutputStreamWriter(new FileOutputStream(f));
        out.write("Hello World!!!");
        out.close();
    }
}

讀得時(shí)候也可以用字符流形式讀取字節(jié)流的對(duì)象

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;

public class Test21 {
    public static void main(String[] args) throws IOException {
        File f = new File("d:" + File.separator+"test.txt");
        Reader input=new InputStreamReader(new FileInputStream(f));
        char[] c=new char[1024];
        int len=input.read(c);
        input.close();
        System.out.println(new String(c,0,len));
    }
}

以上操作只是以文件操作為例,OutputStreamWriter中接受的類型是OutputStream掀虎,只要是字節(jié)輸出流都可以以使用字符的形式操作凌盯,InputStreamReader一樣。

FileWriter和FileReader的說明
從JDK文檔中可以知道FileOutputStream是OutputStream的直接子類烹玉。FileInputStream也是InputStream的直接子類驰怎,但是在字符流文件的兩個(gè)操作類卻有一些特殊,F(xiàn)ileWriter并不直接是Writer的子類二打,而是OutputStreamWriter的子類县忌,而FileReader也不直接是Reader的子類,而是InputStreamReader的子類继效,那么從這兩個(gè)類的繼承關(guān)系就可以清楚的發(fā)現(xiàn)症杏,不管是使用字節(jié)流還是字符流實(shí)際上最終都是以字節(jié)的形式操作輸入輸出流的。也就是說瑞信,傳輸或者從文件中讀取數(shù)據(jù)的時(shí)候厉颤,文件里真正保存的數(shù)據(jù)永遠(yuǎn)是字節(jié)。

內(nèi)存操作流

ByteArrayInputStream和ByteArrayOutputStream

之前所講解的程序中凡简,輸出和輸入都是從文件中來得逼友,當(dāng)然,也可以將輸出的位置設(shè)置在內(nèi)存之上秤涩,此時(shí)就要使用ByteArrayInputStream帜乞、ByteArrayOutputStream來完成輸入輸出功能了
ByteArrayInputStream的主要功能將內(nèi)容輸入到內(nèi)存之中
ByteArrayOutputStream的主要功能是將內(nèi)存中的數(shù)據(jù)輸出
此時(shí)應(yīng)該把內(nèi)存作為操作點(diǎn)

ByteArrayInputStream類的定義:
public class ByteArrayInputStream extends InputStream
構(gòu)造方法:
public ByteArrayInputStream(byte[] buf)
接受一個(gè)byte數(shù)組,實(shí)際上內(nèi)存的輸入就是在構(gòu)造方法上將數(shù)據(jù)傳入到內(nèi)存中溉仑。
ByteArrayOutputStream:輸出就是從內(nèi)存中寫出數(shù)據(jù)
public void write(int b)

以下是以內(nèi)存操作流完成的一個(gè)大小寫字母轉(zhuǎn)換的程序:

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

public class Test22 {
    public static void main(String[] args) throws IOException {
        String str="HELLO WORlD!!!";
        InputStream input=new ByteArrayInputStream(str.getBytes());
        OutputStream output=new ByteArrayOutputStream();
        int temp=0;
        while((temp=input.read())!=-1){
            output.write(Character.toLowerCase(temp));
        }
        input.close();
        output.close();
        System.out.println(output.toString());
    }
}

管道流

管道流(線程通信流)
管道流的主要作用是可以進(jìn)行兩個(gè)線程間的通訊,分為管道輸出流(PipedOutputStream)状植、管道輸入流(PipedInputStream)浊竟,如果想要進(jìn)行管道輸出怨喘,則必須要把輸出流連在輸入流之上,在PipedOutputStream類上有如下的一個(gè)方法用于連接管道:
public void connect(PipedInputStream snk)throws IOException

例子:線程之間用管道流進(jìn)行通訊

import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;

class Send implements Runnable{

    private PipedOutputStream pos;//管道輸出流
    public Send(){
        pos=new PipedOutputStream();
    }
    @Override
    public void run() {
        String str="Hello World!";
        try {
            pos.write(str.getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            pos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public PipedOutputStream getPos() {
        return pos;
    }
}

class Receive implements Runnable{

    private PipedInputStream pis;//管道輸入流
    public Receive(){
        pis=new PipedInputStream();
    }
    @Override
    public void run() {
        byte[] b=new byte[1024];
        int len=0;
        try {
            len=pis.read(b);
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            pis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println(new String(b,0,len));
    }
    public PipedInputStream getPis() {
        return pis;
    }
}

public class Test23 {
    public static void main(String[] args) {
        Send send=new Send();
        Receive receive=new Receive();
        try {
            send.getPos().connect(receive.getPis());//連接管道
        } catch (IOException e) {
            e.printStackTrace();
        }
        new Thread(send).start();//啟動(dòng)線程
        new Thread(receive).start();//啟動(dòng)線程
    }
}

打印流

在整個(gè)IO包中振定,打印流是輸出信息最方便的類必怜,主要包含字節(jié)打印流(PrintStream)和字符打印流(PrintWrite)。打印流提供了非常方便的打印功能后频,可以打印任何的數(shù)據(jù)類型梳庆,例如:小數(shù)、整數(shù)卑惜、字符串等等膏执。

看一下PrintStream的構(gòu)造方法:
public PrintStream(OutputStream out)
在PrintStream中定義的構(gòu)造方法中可以清楚的發(fā)現(xiàn)有一個(gè)構(gòu)造方法可以直接接收OutputStream類的實(shí)例,這是因?yàn)榕cOutputStream相比起來露久,PrintStream可以更加方便的輸出數(shù)據(jù)更米,這就好比將OutputStream類重新包裝了一下,使之輸出更加方便毫痕。

使用PrintStream輸出信息

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

public class Test24 {
    public static void main(String[] args) throws IOException {
        File f = new File("d:" + File.separator+"test.txt");
        PrintStream output=new PrintStream(new FileOutputStream(f));
        output.println("Hello World!");
        output.print("1+1="+2);
        output.close();
    }
}

也就是說此時(shí)征峦,實(shí)際上是將FileOutputStream類的功能包裝了一下,這樣的設(shè)計(jì)在java中稱為裝飾設(shè)計(jì)消请。

類似c語(yǔ)言的printf:

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

public class Test25 {
    public static void main(String[] args) throws IOException {
        File f = new File("d:" + File.separator+"test.txt");
        PrintStream output=new PrintStream(new FileOutputStream(f));
        String name="Jim";
        int age=20;
        float score=90.5f;
        char sex='M';
        output.printf("姓名:%s 年齡:%d 成績(jī):%f 性別:%c", name,age,score,sex);
        output.close();
    }
}

System對(duì)IO的支持

System表示系統(tǒng)類栏笆,此類也對(duì)IO給予了一定的支持。
public static final PrintStream out 對(duì)應(yīng)系統(tǒng)標(biāo)準(zhǔn)輸出臊泰,一般是顯示器
public static final PrintStream err 錯(cuò)誤信息輸出
public static final InputStream in 對(duì)應(yīng)著標(biāo)準(zhǔn)輸入蛉加,一般是鍵盤

又是由于歷史遺留問題 全局變量沒有大寫~

System.out

使用System.out輸出的時(shí)候就是將輸出的位置定義在了顯示器之中。
FileOutputStream是定位在文件里因宇,而System.out是定位在屏幕上七婴。
使用OutputStream完成屏幕上輸出(PrintStream是OutputStream的子類)

import java.io.IOException; 
import java.io.OutputStream; 
public class Test26 { 
            public static void main(String[] args) throws IOException { 
     
          OutputStream out=System.out;
          out.write("Hello World!".getBytes()); 
          out.close();  
       }
}
System.err

System.err表示的錯(cuò)誤的標(biāo)準(zhǔn)輸出,如果程序中出現(xiàn)了錯(cuò)誤的話察滑,則直接使用System.err進(jìn)行打印輸出即可打厘。

public class Test27 {
    public static void main(String[] args) {
        String str="Hello World";
        try{
        int a=Integer.parseInt(str);
        }catch(Exception e){
            System.err.println(e);
        }
    }
}
System.out與System.err的區(qū)別
  • System.out和System.err都是PrintStream的實(shí)例化對(duì)象,而且通過實(shí)例代碼可以發(fā)現(xiàn)贺辰,兩者都可以輸出錯(cuò)誤信息户盯,但是一般來講System.out是將信息顯示給用戶看,是正常的信息顯示饲化,而System.err的信息正好相反是不希望用戶看到莽鸭,會(huì)直接在后臺(tái)打印,是專門顯示錯(cuò)誤的
  • 一般來講吃靠,如果要想輸出錯(cuò)誤信息的時(shí)候最好不要使用System.out而是直接使用System.err硫眨,這一點(diǎn)只能從其概念上劃分。
System.in

System.in實(shí)際上是一個(gè)鍵盤的輸入流巢块,其本身是InputStream類型的對(duì)象礁阁。那么巧号,此時(shí)就可以利用此方式完成從鍵盤讀取數(shù)據(jù)的功能。

InputStream對(duì)應(yīng)的是輸入流姥闭,輸入流的話肯定可以從指定位置上讀取丹鸿,之前使用的是FileInputStream是從文件中讀取的

import java.io.IOException;
import java.io.InputStream;

public class Test28 {
    public static void main(String[] args) throws IOException {
        InputStream in=System.in;
        byte[] b=new byte[1024];
        int len=in.read(b);
        System.out.println(new String(b,0,len));
    }
}

如果不使用byte數(shù)組指定長(zhǎng)度呢:

import java.io.IOException;
import java.io.InputStream;

public class Test29 {
    public static void main(String[] args) throws IOException {
        InputStream in=System.in;
        StringBuilder buf=new StringBuilder();
        int temp=0;
        while((temp=in.read())!=-1){
            char c=(char) temp;
            if(c=='\n')break;
            buf.append(c);
        }
        in.close();
        System.out.println(buf.toString());
    }
}

但以上代碼還是有很大問題的,輸入中文的話~棚品,所以最好的方法還是一次性把數(shù)據(jù)都放在內(nèi)存了靠欢,再一次性全部拿出來,要實(shí)現(xiàn)這個(gè)功能的話铜跑,要用到BufferedReader類

輸入輸出重定向

System.out门怪、System.err、System.in都有重定向功能疼进,分別是setOut薪缆、setErr、setIn方法
System.out重定向

import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintStream;

public class Test30 {
    public static void main(String[] args) throws FileNotFoundException {
        File f = new File("d:" + File.separator+"test.txt");
        System.setOut(new PrintStream(f));
        String str="This is a test!";
        System.out.println(str);
    }
}

****System.err重定向****

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;

public class Test31 {
    public static void main(String[] args) {
        ByteArrayOutputStream out=new ByteArrayOutputStream();
        System.setErr(new PrintStream(out));
        System.err.println("Test---------------");
        System.out.println(out.toString());
    }
}

一般不建議修改err的重定向伞广,因?yàn)檫@些信息都不太希望用戶看到
System.in重定向

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

public class Test32 {
    public static void main(String[] args) throws IOException {
        File f = new File("d:" + File.separator+"test.txt");
        System.setIn(new FileInputStream(f));
        InputStream in=System.in;
        byte[] b=new byte[1024];
        int len=in.read(b);
        in.close();
        System.out.println(new String(b,0,len));
    }
}

BufferReader和Scanner

如果想要接收任意長(zhǎng)度的數(shù)據(jù)拣帽,而且避免亂碼產(chǎn)生,就可以使用BufferedReader
public class BufferedReader extends Reader
因?yàn)檩斎氲臄?shù)據(jù)有可能出現(xiàn)中文嚼锄,所以减拭,此處使用字符流完成。BufferedReader是從緩沖區(qū)之中讀取內(nèi)容区丑,所有的輸入的字節(jié)數(shù)據(jù)都將放在緩沖區(qū)之中拧粪。
System.in本身表示的是InputStream(字節(jié)流),現(xiàn)在要求接收的是一個(gè)字符流沧侥,需要將字節(jié)流變成字符流才可以可霎,所以要用InputStreamReader

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class Test33 {
    public static void main(String[] args) throws IOException {
        BufferedReader reader=new BufferedReader(new InputStreamReader(System.in));
        String str=reader.readLine();
        System.out.println(str);
    }
}

在JDK1.5之后Java提供了專門的輸入數(shù)據(jù)類,此類可以完成BufferedReader類的功能宴杀,也可以方便的對(duì)輸入數(shù)據(jù)進(jìn)行驗(yàn)證癣朗,此類存放在java.util包中
使用Scanner接收鍵盤的輸入數(shù)據(jù):

import java.util.Scanner;

public class Test34 {
    public static void main(String[] args) {
        Scanner s=new Scanner(System.in);
        String str=s.next();
        System.out.println(str);
    }
}

比直接使用BufferedReader更加方便,但是這個(gè)程序是有問題的旺罢,如果輸入的字符串中存在空格旷余,那么就會(huì)截止,如果我們要接收空格的下扁达,將分隔符變成“\n”正卧。

import java.util.Scanner;

public class Test34 {
    public static void main(String[] args) {
        Scanner s=new Scanner(System.in);
        s.useDelimiter("\n");//使用分隔符
        String str=s.next();
        System.out.println(str);
    }
}

對(duì)象序列化和反序列化

所謂的對(duì)象序列化就是將一個(gè)對(duì)象轉(zhuǎn)換為二進(jìn)制流,如果一個(gè)類的對(duì)象要想實(shí)現(xiàn)序列化跪解,則該對(duì)象所在的類必須實(shí)現(xiàn)Serializable接口炉旷,在此接口中沒有任何的方法,此接口只是作為一個(gè)標(biāo)識(shí),表示本類的對(duì)象具備了序列化的能力窘行。

序列化的思想是“凍結(jié)”對(duì)象狀態(tài)骏啰,傳輸對(duì)象狀態(tài)(寫到磁盤、通過網(wǎng)絡(luò)傳輸?shù)鹊龋┏楦撸缓蟆敖鈨觥睜顟B(tài),重新獲得可用的Java對(duì)象透绩,所有這些事情的發(fā)生有點(diǎn)像魔術(shù)翘骂,這要?dú)w功于ObjectInputStream/ObjectOutputStream類,完全保真的元數(shù)據(jù)以及程序員愿意用Serializable標(biāo)識(shí)接口標(biāo)記他們的類帚豪,從而“參與”這個(gè)過程碳竟。

序列化分為兩大部分:
序列化和反序列化。序列化是這個(gè)過程的第一部分狸臣,將數(shù)據(jù)分解成字節(jié)流莹桅,以便存儲(chǔ)在文件中或在網(wǎng)絡(luò)上傳輸。反序列化就是打開字節(jié)流并重構(gòu)對(duì)象烛亦。對(duì)象序列化不僅要將基本數(shù)據(jù)類型轉(zhuǎn)換成字節(jié)表示诈泼,有時(shí)還要恢復(fù)數(shù)據(jù)∶呵荩恢復(fù)數(shù)據(jù)要求有恢復(fù)數(shù)據(jù)的對(duì)象實(shí)例铐达,如果某個(gè)類能夠被序列化,其子類也可以被序列化檬果。聲明為static和transient類型的成員數(shù)據(jù)不能被序列化瓮孙。因此static代表類的狀態(tài),transient代表對(duì)象的臨時(shí)數(shù)據(jù)选脊。
對(duì)象序列化在一下場(chǎng)景使用比較合適:

  • 當(dāng)你想把的內(nèi)存中的對(duì)象狀態(tài)保存到一個(gè)文件中或者數(shù)據(jù)庫(kù)中時(shí)候杭抠;
  • 當(dāng)你想用套接字在網(wǎng)絡(luò)上傳送對(duì)象的時(shí)候;
  • 當(dāng)你想通過RMI(Remote Method Invocation 遠(yuǎn)程方法調(diào)用)傳輸對(duì)象的時(shí)候恳啥;

如果要想實(shí)現(xiàn)對(duì)象的序列化偏灿,則還要依靠ObjectOutputStream類和ObjectInputStream類,前者屬于序列化操作角寸,而或者屬于反序列化操作菩混。

public class Person implements Serializable {   
    private String name;   
    private int age;   
  
    public Person(String name, int age) {   
        super();   
        this.name = name;   
        this.age = age;   
    }   
  
    public String toString() {   
        return "姓名:" + this.name + ",年齡:" + this.age;   
    }   
  
    public int getAge() {   
        return age;   
    }   
  
    public void setAge(int age) {   
        this.age = age;   
    }   
  
    public String getName() {   
        return name;   
    }   
  
    public void setName(String name) {   
        this.name = name;   
    }   
  
}  

下面通過ObjectOutputStream完成序列化操作:

public class ObjectOutputStreamDemo {   
    public static void main(String args[]) throws Exception {   
        File file = new File("d:" + File.separator + "demo.txt");   
        ObjectOutputStream oos = null;   
        oos = new ObjectOutputStream(new FileOutputStream(file));   
        Person per = new Person("王旭東", 21);   
        oos.writeObject(per);   
        oos.close();   
    }   
  
}  

對(duì)象被實(shí)例化之后,就可以通過ObjectInputStream進(jìn)行反序列化的操作

public class ObjectInputStreamDemo {   
    public static void main(String args[]) throws Exception {   
        File file = new File("d:" + File.separator + "demo.txt");   
        ObjectInputStream ois = null;   
        ois = new ObjectInputStream(new FileInputStream(file));   
        Object obj = ois.readObject();   
        Person per = (Person) obj;   
        System.out.println(per);   
    }   
  
}  

以上操作實(shí)際上是整個(gè)對(duì)象進(jìn)行的序列化操作扁藕,如果現(xiàn)在假設(shè)類中的某個(gè)屬性不希望被序列化的話沮峡,則使用transient關(guān)鍵字進(jìn)行聲明;

private transient String name;  

由上面可知可以對(duì)一個(gè)對(duì)象序列化亿柑,那么因?yàn)镺bject可以接受任意的引用數(shù)據(jù)類型邢疙,所以也可以同時(shí)對(duì)多個(gè)對(duì)象一起進(jìn)行序列化操作,包括數(shù)組;

public class SerializableDemo {   
    public static void main(String args[]) throws Exception {   
        Person per[] = { new Person("張三", 30), new Person("李四", 40),new Person("王五", 50) };   
        serializable(per);   
        Person p[] = (Person[]) delSerializable();   
        print(p);   
    }   
    public static void serializable(Object obj) throws Exception {   
        File file = new File("d:" + File.separator + "demo.txt");   
        ObjectOutputStream oos = null;   
        oos = new ObjectOutputStream(new FileOutputStream(file));   
        oos.writeObject(obj);   
        oos.close();   
    }   
    public static Object delSerializable() throws Exception {   
        Object temp = null;   
        File file = new File("d:" + File.separator + "demo.txt");   
        ObjectInputStream ois = null;   
        ois = new ObjectInputStream(new FileInputStream(file));   
        temp = ois.readObject();   
        return temp;   
    }   
    public static void print(Person per[]) {   
        for (Person p : per) {   
            System.out.println(p);   
        }   
    }   
  
}  
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末疟游,一起剝皮案震驚了整個(gè)濱河市呼畸,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌颁虐,老刑警劉巖蛮原,帶你破解...
    沈念sama閱讀 216,544評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異另绩,居然都是意外死亡儒陨,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門笋籽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蹦漠,“玉大人,你說我怎么就攤上這事车海〉言埃” “怎么了?”我有些...
    開封第一講書人閱讀 162,764評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵侍芝,是天一觀的道長(zhǎng)研铆。 經(jīng)常有香客問我,道長(zhǎng)州叠,這世上最難降的妖魔是什么蚜印? 我笑而不...
    開封第一講書人閱讀 58,193評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮留量,結(jié)果婚禮上窄赋,老公的妹妹穿的比我還像新娘。我一直安慰自己楼熄,他們只是感情好忆绰,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著可岂,像睡著了一般错敢。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上缕粹,一...
    開封第一講書人閱讀 51,182評(píng)論 1 299
  • 那天稚茅,我揣著相機(jī)與錄音,去河邊找鬼平斩。 笑死亚享,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的绘面。 我是一名探鬼主播欺税,決...
    沈念sama閱讀 40,063評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼侈沪,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了晚凿?” 一聲冷哼從身側(cè)響起亭罪,我...
    開封第一講書人閱讀 38,917評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎歼秽,沒想到半個(gè)月后应役,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,329評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡燥筷,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評(píng)論 2 332
  • 正文 我和宋清朗相戀三年扛吞,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片荆责。...
    茶點(diǎn)故事閱讀 39,722評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖亚脆,靈堂內(nèi)的尸體忽然破棺而出做院,到底是詐尸還是另有隱情,我是刑警寧澤濒持,帶...
    沈念sama閱讀 35,425評(píng)論 5 343
  • 正文 年R本政府宣布键耕,位于F島的核電站,受9級(jí)特大地震影響柑营,放射性物質(zhì)發(fā)生泄漏屈雄。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評(píng)論 3 326
  • 文/蒙蒙 一官套、第九天 我趴在偏房一處隱蔽的房頂上張望酒奶。 院中可真熱鬧,春花似錦奶赔、人聲如沸惋嚎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)另伍。三九已至,卻和暖如春绞旅,著一層夾襖步出監(jiān)牢的瞬間摆尝,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工因悲, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留堕汞,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,729評(píng)論 2 368
  • 正文 我出身青樓晃琳,卻偏偏與公主長(zhǎng)得像臼朗,于是被迫代替她去往敵國(guó)和親邻寿。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容

  • tags:io categories:總結(jié) date: 2017-03-28 22:49:50 不僅僅在JAVA領(lǐng)...
    行徑行閱讀 2,174評(píng)論 0 3
  • 標(biāo)準(zhǔn)輸入輸出视哑,文件的操作绣否,網(wǎng)絡(luò)上的數(shù)據(jù)流,字符串流挡毅,對(duì)象流蒜撮,zip文件流等等,java中將輸入輸出抽象稱為流跪呈,就好...
    navy_legend閱讀 713評(píng)論 0 0
  • 本文對(duì) Java 中的 IO 流的概念和操作進(jìn)行了梳理總結(jié)段磨,并給出了對(duì)中文亂碼問題的解決方法。 1. 什么是流 J...
    Skye_kh閱讀 769評(píng)論 0 2
  • 學(xué)習(xí)Java中的IO耗绿,首先要理解Java中IO的流模型苹支。所謂流,可以假想成河流误阻,流的數(shù)據(jù)源债蜜,就是河流的發(fā)源地,流是...
    GhostStories閱讀 466評(píng)論 0 5
  • 曾經(jīng)以為回家是一張車票的距離狼速,當(dāng)我由原來一年的三四次回家變成兩次一次,甚至零次時(shí)卦停,才發(fā)現(xiàn)原來回家的路最艱難向胡。 1、...
    我不是蝸牛閱讀 364評(píng)論 1 1