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