IO操作深入

字符編碼

??在實(shí)際開發(fā)中,常用的編碼有如下幾種:

  • GBK/GB2312:國標(biāo)編碼私植,可以描述中文信息官边,其中GB2312只描述簡體中文,而GBK包含簡體中文和繁體中文锄贼;
  • ISO8859-1:國際通用編碼:可以用其描述所有的字母信息票灰,如果是象形文字,則需要進(jìn)行編碼處理宅荤;
  • UNICODE編碼:采用十六進(jìn)制的方式屑迂,可以描述所有文字信息;
  • UTF編碼:象形文字部分使用UNICODE編碼冯键,而普通的字母采用 ISO8859-1編碼惹盼,它的優(yōu)勢在于適合快速的傳輸,節(jié)約帶寬惫确,也就成為了開發(fā)中首選的編碼手报,主要使用“UTF-8”編碼。
    ??如果要想知道當(dāng)前系統(tǒng)中支持的編碼規(guī)則改化,則可以采用如下代碼列出全部的本機(jī)屬性掩蛤。
    范例:列出本機(jī)屬性
public class JavaApiDemo {
    public static void main(String[] args) throws Exception {
        System.getProperties().list(System.out);
    }
}
  • 文件的路徑分割符:file.separator=/;
  • 文件默認(rèn)編碼:file.encoding=UTF-8陈肛;
    ??也就是說如果現(xiàn)在什么都不設(shè)置揍鸟,則采用的編碼就是UTF-8;
    范例:編寫程序
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
public class JavaApiDemo {
    public static void main(String[] args) throws Exception {
        OutputStream output=new FileOutputStream(new File("/Users/fzc/Documents/mydir/mldn.txt"));
        output.write("中華人民共和國萬歲".getBytes());
        output.close();
    }
}

范例:強(qiáng)制性設(shè)置編碼

import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
public class JavaApiDemo {
    public static void main(String[] args) throws Exception {
        OutputStream output=new FileOutputStream(new File("/Users/fzc/Documents/mydir/mldn.txt"));
        output.write("中華人民共和國萬歲".getBytes("utf-8"));
//        output.write("中華人民共和國萬歲".getBytes("ISO8859-1"));//亂碼
        output.close();
    }
}

??項(xiàng)目中出現(xiàn)的亂碼問題就是編碼和解碼標(biāo)準(zhǔn)不統(tǒng)一句旱,而解決亂碼最常用的方式就是所有的編碼都采用“utf-8”阳藻。

內(nèi)存操作流

??在之前使用的全部都是文件操作流晰奖,文件操作流的特點(diǎn):程序利用InputStream讀取文件內(nèi)容,而后程序利用OutputStream向文件輸出內(nèi)容腥泥,所有的操作都是以文件為終端的匾南。

文件流

??如果說現(xiàn)在需要實(shí)現(xiàn)IO操作,又不希望產(chǎn)生文件(臨時(shí)文件)道川,則就可以以內(nèi)存為終端進(jìn)行處理午衰,這個(gè)時(shí)候的流程為:

內(nèi)存流

??在Java中提供提供了兩類的內(nèi)存操作流:

ByteArrayOutputStream
ByteArrayInputStream
CharArrayWriter
CharArrayReader

??下面使用ByteArrayOutputStream和ByteArrayInputStream類為主進(jìn)行內(nèi)存的使用分析臊岸,首先分析各自的構(gòu)造方法:

  • ByteArrayInputStream構(gòu)造:public ByteArrayInputStream?(byte[] buf);
  • ByteArrayOutputStream構(gòu)造:public ByteArrayOutputStream()尊流;
    ??在ByteArrayOutputStream類中有兩個(gè)很重要的方法帅戒,這兩個(gè)個(gè)方法可以獲取全部保存在內(nèi)存流中的數(shù)據(jù)信息:
  • 獲取數(shù)據(jù):public byte[] toByteArray();
  • 使用字符串的形式獲妊录肌:public String toString()逻住;
    范例:利用內(nèi)存流實(shí)現(xiàn)一個(gè)小寫字母轉(zhuǎn)大寫字母的操作
import java.io.*;
public class JavaApiDemo {
    public static void main(String[] args) throws Exception {
        String str="www.baidu.com";
        InputStream input=new ByteArrayInputStream(str.getBytes());//將數(shù)據(jù)保存在內(nèi)存流
        OutputStream output=new ByteArrayOutputStream();//讀取內(nèi)存中的數(shù)據(jù)
        int data=0;
        while ((data=input.read())!=-1){//每次讀取一個(gè)字節(jié)
            output.write(Character.toUpperCase((char)data));//保存數(shù)據(jù)
        }
        System.out.println(output.toString());//WWW.BAIDU.COM
        input.close();
        output.close();
    }
}

??如果不希望只是以字符串的形式返回,因?yàn)榭赡艽娣诺氖瞧渌M(jìn)制的數(shù)據(jù)迎献,那么此時(shí)就可以利用OutputStream的子類ByteArrayOutputStream的擴(kuò)展功能獲取全部字節(jié)數(shù)據(jù)瞎访。

import java.io.*;
public class JavaApiDemo {
    public static void main(String[] args) throws Exception {
        String str="www.baidu.com";
        InputStream input=new ByteArrayInputStream(str.getBytes());//將數(shù)據(jù)保存在內(nèi)存流
        ByteArrayOutputStream output=new ByteArrayOutputStream();//讀取內(nèi)存中的數(shù)據(jù)
        int data=0;
        while ((data=input.read())!=-1){//每次讀取一個(gè)字節(jié)
            output.write(Character.toUpperCase((char)data));//保存數(shù)據(jù)
        }
        byte[] result=output.toByteArray();//自己處理字節(jié)數(shù)據(jù)
        System.out.println(new String(result));//WWW.BAIDU.COM
        input.close();
        output.close();
    }
}

??在最初的時(shí)候,可以利用ByteArrayOutputStream實(shí)現(xiàn)大規(guī)模文本文件讀取吁恍。

管道流

??管道流主要功能是實(shí)現(xiàn)兩個(gè)線程之間的IO處理操作扒秸。

管道流

??對于管道流也分為兩類

  • 字節(jié)管道流PipedOutputStreamPipedInputStream
    ??- 連接處理:public void connect?(PipedInputStream snk) throws IOException冀瓦;
  • 字符管道流PipedWriter伴奥、PipedReader
    ??- 連接處理:public void connect?(PipedReader snk) throws IOException;
PipedOutputStream
PipedInputStream
PipedWriter
PipedReader

范例:實(shí)現(xiàn)管道操作

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
public class JavaApiDemo {
    public static void main(String[] args) throws Exception {
        SendThread send=new SendThread();
        ReceiveThread receive=new ReceiveThread();
        send.getOutput().connect(receive.getInput());//進(jìn)行管道連接
        new Thread(send,"消息發(fā)送線程").start();
        new Thread(receive,"消息接收線程").start();
        /**
         * 【第1次信息發(fā)送 - 消息發(fā)送線程】www.baidu.com
         * 【第2次信息發(fā)送 - 消息發(fā)送線程】www.baidu.com
         * 【第3次信息發(fā)送 - 消息發(fā)送線程】www.baidu.com
         * 【第4次信息發(fā)送 - 消息發(fā)送線程】www.baidu.com
         * 【第5次信息發(fā)送 - 消息發(fā)送線程】www.baidu.com
         * 【第6次信息發(fā)送 - 消息發(fā)送線程】www.baidu.com
         * 【第7次信息發(fā)送 - 消息發(fā)送線程】www.baidu.com
         * 【第8次信息發(fā)送 - 消息發(fā)送線程】www.baidu.com
         * 【第9次信息發(fā)送 - 消息發(fā)送線程】www.baidu.com
         * 【第10次信息發(fā)送 - 消息發(fā)送線程】www.baidu.com
         */
    }
}
class SendThread implements Runnable{
    private PipedOutputStream output;//管道輸出流

    public SendThread() {
        this.output = new PipedOutputStream();//實(shí)例化管道輸出流
    }
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            try {
                output.write(("【第"+(i+1)+"次信息發(fā)送 - "+Thread.currentThread().getName()+"】www.baidu.com\n").getBytes());
            }catch (IOException e){
                e.printStackTrace();
            }
        }
        try {
            this.output.close();
        }catch (IOException e){
            e.printStackTrace();
        }
    }
    public PipedOutputStream getOutput(){
        return output;
    }
}
class ReceiveThread implements Runnable{
    private PipedInputStream input;

    public ReceiveThread() {
        input=new PipedInputStream();
    }
    @Override
    public void run() {
        byte[] data = new byte[1024];
        int len = 0;
        ByteArrayOutputStream bos = new ByteArrayOutputStream();//所有的數(shù)據(jù)保存到內(nèi)存輸出流
        try {
            while ((len = input.read(data)) != -1) {
                bos.write(data, 0, len);
            }
            System.out.println(new String(bos.toByteArray()));
            bos.close();
            input.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public PipedInputStream getInput() {
        return input;
    }
}

??管道中一個(gè)負(fù)責(zé)發(fā)送翼闽,一個(gè)負(fù)責(zé)接收拾徙,中間靠一個(gè)管道連接。

RandomAccessFile

??對于文件內(nèi)容的處理操作主要通過InputStream(Reader)感局、OutputStream(Writer)來實(shí)現(xiàn)尼啡,但是利用這些類實(shí)現(xiàn)的內(nèi)容讀取,只能夠?qū)?shù)據(jù)部分部分讀取進(jìn)來蓝厌,如果說現(xiàn)在有這樣一種需求玄叠。
??現(xiàn)在有一個(gè)20G大小的文件,如果按照傳統(tǒng)的IO操作進(jìn)行讀取和分析很明顯不能很好的完成拓提,所以這種情況下在java.io包中提供了一個(gè)RandomAccessFile類读恃,這個(gè)類可以實(shí)現(xiàn)文件的跳躍式的讀取,可以只讀取中間的部分內(nèi)容(前提:需要有一個(gè)完善的保存形式),數(shù)據(jù)的保存位數(shù)要確定好寺惫。

??RandomAccessFile類中定義有如下的操作方法:

  • 構(gòu)造方法:
    ??public RandomAccessFile?(File file, String mode) throws FileNotFoundException
    ??- 文件處理模式:r疹吃、rw;
    范例:實(shí)現(xiàn)文件的保存
import java.io.File;
import java.io.RandomAccessFile;
public class JavaApiDemo {
    public static void main(String[] args) throws Exception {
        String dirPath = "/Users/fzc/Documents/mydir/mldn_save.txt";//定義操作的文件
        File file = new File(dirPath);
        RandomAccessFile raf=new RandomAccessFile(file,"rw");//讀寫模式
        String[] names=new String[]{"zhangsan","wangwu  ","lisi    "};
        int[] ages=new int[]{30,20,16};
        for (int i = 0; i < names.length; i++) {
            raf.write(names[i].getBytes());
            raf.writeInt(ages[i]);
        }
        raf.close();
    }
}

??RandomAccessFile最大的特點(diǎn)是在于數(shù)據(jù)的讀取處理上西雀,因?yàn)樗械臄?shù)據(jù)是按照固定的長度進(jìn)行保存的萨驶,所以讀取時(shí)就可以進(jìn)行跳字節(jié)讀取:
??向下跳:public int skipBytes?(int n) throws IOException艇肴;腔呜;
??向上跳:public void seek?(long pos) throws IOException;再悼;
范例:讀取數(shù)據(jù)

import java.io.File;
import java.io.RandomAccessFile;
public class JavaApiDemo {
    public static void main(String[] args) throws Exception {
        String dirPath = "/Users/fzc/Documents/mydir/mldn_save.txt";//定義操作的文件
        File file = new File(dirPath);
        RandomAccessFile raf=new RandomAccessFile(file,"rw");//讀寫模式
       //讀取"lisi"數(shù)據(jù)核畴,跳過24位
        raf.skipBytes(24);
        byte[] data=new byte[8];
        int len=raf.read(data);
        System.out.println("姓名:"+new String(data,0,len)+"、年齡:"+raf.readInt());//姓名:lisi    冲九、年齡:16
        //讀取"wangwu"數(shù)據(jù)谤草,回跳到12位
        raf.seek(12);
         data=new byte[8];
         len=raf.read(data);
        System.out.println("姓名:"+new String(data,0,len)+"、年齡:"+raf.readInt());//姓名:wangwu  莺奸、年齡:20
        //讀取"zhangsan"數(shù)據(jù)丑孩,回跳到0位
        raf.seek(0);
        data=new byte[8];
        len=raf.read(data);
        System.out.println("姓名:"+new String(data,0,len)+"、年齡:"+raf.readInt());//姓名:zhangsan灭贷、年齡:30
    }
}

??整體的使用之中由用戶自行定義要讀取的位置温学,而后按照指定的結(jié)構(gòu)進(jìn)行數(shù)據(jù)的讀取。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末甚疟,一起剝皮案震驚了整個(gè)濱河市枫浙,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌古拴,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件真友,死亡現(xiàn)場離奇詭異黄痪,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)盔然,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進(jìn)店門桅打,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人愈案,你說我怎么就攤上這事挺尾。” “怎么了站绪?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵遭铺,是天一觀的道長。 經(jīng)常有香客問我,道長魂挂,這世上最難降的妖魔是什么甫题? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮涂召,結(jié)果婚禮上坠非,老公的妹妹穿的比我還像新娘。我一直安慰自己果正,他們只是感情好炎码,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著秋泳,像睡著了一般潦闲。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上轮锥,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天矫钓,我揣著相機(jī)與錄音,去河邊找鬼舍杜。 笑死新娜,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的既绩。 我是一名探鬼主播概龄,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼饲握!你這毒婦竟也來了私杜?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤救欧,失蹤者是張志新(化名)和其女友劉穎衰粹,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體笆怠,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡铝耻,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了蹬刷。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片瓢捉。...
    茶點(diǎn)故事閱讀 38,622評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖办成,靈堂內(nèi)的尸體忽然破棺而出泡态,到底是詐尸還是另有隱情,我是刑警寧澤迂卢,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布某弦,位于F島的核電站桐汤,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏刀崖。R本人自食惡果不足惜惊科,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望亮钦。 院中可真熱鬧馆截,春花似錦、人聲如沸蜂莉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽映穗。三九已至窖张,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蚁滋,已是汗流浹背宿接。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留辕录,地道東北人睦霎。 一個(gè)月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像走诞,于是被迫代替她去往敵國和親副女。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評論 2 348