package?com.imooc;
import?java.io.File;
import?java.io.IOException;
import?java.io.RandomAccessFile;
import?java.util.Arrays;
import?java.util.Random;
public?class?RafDemo?{
?public?static?void?main(String[]?args)?throws?IOException{
??//?TODO?Auto-generated?method?stub
??File?demo?=?new?File("demo");//如果沒有寫絕對(duì)路徑的話他就是一個(gè)相對(duì)路徑目錄就是在我們的項(xiàng)目下
??if(!demo.exists()){
???demo.mkdir();
??}
??File?file?=?new?File(demo,"Raf.dat");//以demo作為父目錄后面跟一個(gè)文件
??if(!file.exists()){
???file.createNewFile();
??}
??RandomAccessFile?raf?=?new?RandomAccessFile(file,"rw");
??System.out.println("文件中沒有寫任何數(shù)據(jù)時(shí)指針的位置"?+?raf.getFilePointer());//得到指針的位置
??
??raf.write('A');//只寫了一個(gè)字節(jié)一個(gè)char是兩個(gè)字節(jié)所以他會(huì)把'A'的后八位寫進(jìn)去,也有可能后八位已經(jīng)能表示這個(gè)'A'前面的高八位可能是00000000
??System.out.println("寫完一個(gè)字節(jié)之后指針的位置"?+?raf.getFilePointer());
??raf.write('B');
??System.out.println("寫完第二個(gè)字節(jié)之后指針的位置"?+?raf.getFilePointer());
??
??int?i?=?0X7fffffff;//Java最大的整數(shù)
//??用write()每次只能寫一個(gè)字節(jié)如果要把i寫進(jìn)去就得寫四次
??raf.write(i?>>>?24);//高八位
??raf.write(i?>>>?16);//第二個(gè)高八位
??raf.write(i?>>>?8);//第三個(gè)高八位
??raf.write(i);//只寫后八位自動(dòng)寫最低的八位
??System.out.println("寫完一個(gè)int類型的數(shù)據(jù)之后指針的位置"?+?raf.getFilePointer());
??
//??可以直接寫一個(gè)int因?yàn)镽andomAccessFile提供了writeInt()
??raf.writeInt(i);//writeInt()的底層就是做了上述四個(gè)write()
??System.out.println("再次寫完一個(gè)int類型的數(shù)據(jù)之后指針的位置"?+?raf.getFilePointer());
??/*writeInt()的底層源碼
??public?final?void?writeInt(int?v)?throws?IOException?{
????????write((v?>>>?24)?&?0xFF);//0xFF的作用把前面的0去掉因?yàn)橛乙浦笄懊娑佳a(bǔ)0了
????????write((v?>>>?16)?&?0xFF);
????????write((v?>>>??8)?&?0xFF);
????????write((v?>>>??0)?&?0xFF);
????????//written?+=?4;
????????}
????????
?????????與上述的四行write()比較
?????????raf.write(i?>>>?24);把i右移24位只寫后八位前面的0都不寫了
???*/
??String?s?=?"中";//中文占兩個(gè)字節(jié)
??byte[]?gbk?=?s.getBytes("gbk");
??raf.write(gbk);//直接寫一個(gè)字節(jié)數(shù)組
??System.out.println("寫完一個(gè)Stirng類型的中文字符的數(shù)據(jù)之后指針的位置"?+?raf.getFilePointer());
??
??System.out.println("從頭到尾寫入到文件中的字節(jié)的總長(zhǎng)度?"?+?raf.length());//文件的長(zhǎng)度
??
//??讀文件必須把指針移到文件頭部
??raf.seek(0);//指針移到文件的開始
??
??//一次性讀取,把文件中的內(nèi)容都讀到字節(jié)數(shù)組中
??byte[]?buf?=?new?byte[(int)raf.length()];
??
//??raf.read();//只能讀一個(gè)字節(jié)
??raf.read(buf);//能夠把文件中的內(nèi)容讀到字節(jié)數(shù)組里面
??System.out.println(Arrays.toString(buf));//讀取之后把字節(jié)數(shù)組輸出
??/*
???*?從輸出結(jié)果中看[65,?66,?127,?-1,?-1,?-1,?127,?-1,?-1,?-1,?-42,?-48]65,66也就是A和B了原因即使他的后八位已經(jīng)能表示了
???*/
??
??/**
???*?把整個(gè)字節(jié)數(shù)組構(gòu)造成字符串
???*/
??String?s1?=?new?String(buf,"gbk");
??System.out.println(s1);
??/*
???*?從輸出結(jié)果來(lái)看AB??????中
???*?因?yàn)檎麄€(gè)自己數(shù)組和我們想的是不一樣的最后一個(gè)String類型的中文字符"中"在Java的字符串中是utf-16be的編碼
???*?即使在寫入的時(shí)候轉(zhuǎn)換成了gbk但是在重新構(gòu)成的時(shí)候前后還有其他字節(jié)你在寫的時(shí)候是一個(gè)字節(jié)數(shù)組除非你單獨(dú)包裝寫入中文字符"中"的情況因?yàn)榍懊孢€有字節(jié)
???*?除非你只讀兩個(gè)字節(jié)把他包裝
???*?正好定位到它的位置讀兩個(gè)字節(jié)包裝起來(lái)就正好是一個(gè)中文反則就會(huì)有亂碼
???*/
??/**
???*?以16進(jìn)制輸出
???*/
??for?(byte?b?:?buf)?{
???System.out.print(Integer.toHexString(b?&?0xff)?+?"?");
??}
//??關(guān)閉文件
??raf.close();
??
??/**
???*?以上的read()方法不是讀一個(gè)字節(jié)是一下全部讀取其實(shí)也可以一次讀一個(gè)字節(jié)
???*?或者定位到某個(gè)位置比如定位到第10個(gè)位置讀兩個(gè)字節(jié)就讀到了一個(gè)中文用gbk轉(zhuǎn)化就正好是一個(gè)字符串
???*/
?}
}
輸出結(jié)果
文件中沒有寫任何數(shù)據(jù)時(shí)指針的位置0
寫完一個(gè)字節(jié)之后指針的位置1
寫完第二個(gè)字節(jié)之后指針的位置2
寫完一個(gè)int類型的數(shù)據(jù)之后指針的位置6
再次寫完一個(gè)int類型的數(shù)據(jù)之后指針的位置10
寫完一個(gè)Stirng類型的中文字符的數(shù)據(jù)之后指針的位置12
從頭到尾寫入到文件中的字節(jié)的總長(zhǎng)度?12
[65,?66,?127,?-1,?-1,?-1,?127,?-1,?-1,?-1,?-42,?-48]
AB??????中
41?42?7f?ff?ff?ff?7f?ff?ff?ff?d6?d0
2017-10-19
那為什么中間會(huì)出現(xiàn)亂碼,怎么樣能顯示中間的int
2017-03-16
因?yàn)楸幌到y(tǒng)識(shí)別了編碼方式,同時(shí)正確解碼了。你可以把51行的換成byte[] gbk = s.getBytes("utf-8");在不更改74行的gbk解碼方式下,就會(huì)出現(xiàn)亂碼,如果也改成了utf-8就會(huì)成功解碼。