本篇文章不會(huì)介紹關(guān)于輸入輸出流的任何知識(shí)桑阶。因?yàn)橄胍莆蛰斎胼敵隽鞒┩浚紫纫私庾止?jié)與字符的關(guān)系港华,以及File類的相關(guān)知識(shí)。這也是本篇文章的主要內(nèi)容午衰。
一立宜、字符與字節(jié)
在Java中有輸入、輸出兩種IO流臊岸,每種輸入橙数、輸出流又分為字節(jié)流和字符流兩大類。關(guān)于字節(jié)帅戒,我們?cè)趯W(xué)習(xí)8大基本數(shù)據(jù)類型中都有了解商模,每個(gè)字節(jié)(byte)有8bit組成,每種數(shù)據(jù)類型又幾個(gè)字節(jié)組成等蜘澜。關(guān)于字符,我們可能知道代表一個(gè)漢字或者英文字母响疚。
但是字節(jié)與字符之間的關(guān)系是怎樣的鄙信?
Java采用unicode編碼,2個(gè)字節(jié)來(lái)表示一個(gè)字符忿晕,這點(diǎn)與C語(yǔ)言中不同装诡,C語(yǔ)言中采用ASCII,在大多數(shù)系統(tǒng)中践盼,一個(gè)字符通常占1個(gè)字節(jié)鸦采,但是在0~127整數(shù)之間的字符映射,unicode向下兼容ASCII咕幻。而Java采用unicode來(lái)表示字符渔伯,一個(gè)中文或英文字符的unicode編碼都占2個(gè)字節(jié)。但如果采用其他編碼方式肄程,一個(gè)字符占用的字節(jié)數(shù)則各不相同锣吼。可能有點(diǎn)暈蓝厌,舉個(gè)例子解釋下玄叠。
例如:Java中的String類是按照unicode進(jìn)行編碼的,當(dāng)使用String(byte[] bytes, String encoding)構(gòu)造字符串時(shí)拓提,encoding所指的是bytes中的數(shù)據(jù)是按照那種方式編碼的读恃,而不是最后產(chǎn)生的String是什么編碼方式,換句話說(shuō),是讓系統(tǒng)把bytes中的數(shù)據(jù)由encoding編碼方式轉(zhuǎn)換成unicode編碼寺惫。如果不指明疹吃,bytes的編碼方式將由jdk根據(jù)操作系統(tǒng)決定。
getBytes(String charsetName)
使用指定的編碼方式將此String編碼為 byte 序列肌蜻,并將結(jié)果存儲(chǔ)到一個(gè)新的 byte 數(shù)組中互墓。如果不指定將使用操作系統(tǒng)默認(rèn)的編碼方式,我的電腦默認(rèn)的是GBK編碼蒋搜。
public class Hel {
public static void main(String[] args){
String str = "你好hello";
int byte_len = str.getBytes().length;
int len = str.length();
System.out.println("字節(jié)長(zhǎng)度為:" + byte_len);
System.out.println("字符長(zhǎng)度為:" + len);
System.out.println("系統(tǒng)默認(rèn)編碼方式:" + System.getProperty("file.encoding"));
}
}
輸出結(jié)果
字節(jié)長(zhǎng)度為:9
字符長(zhǎng)度為:7
系統(tǒng)默認(rèn)編碼方式:GBK
這是因?yàn)椋涸?GB 2312 編碼或 GBK 編碼中篡撵,一個(gè)英文字母字符存儲(chǔ)需要1個(gè)字節(jié),一個(gè)漢字字符存儲(chǔ)需要2個(gè)字節(jié)豆挽。 在UTF-8編碼中育谬,一個(gè)英文字母字符存儲(chǔ)需要1個(gè)字節(jié),一個(gè)漢字字符儲(chǔ)存需要3到4個(gè)字節(jié)帮哈。在UTF-16編碼中膛檀,一個(gè)英文字母字符存儲(chǔ)需要2個(gè)字節(jié),一個(gè)漢字字符儲(chǔ)存需要3到4個(gè)字節(jié)(Unicode擴(kuò)展區(qū)的一些漢字存儲(chǔ)需要4個(gè)字節(jié))娘侍。在UTF-32編碼中咖刃,世界上任何字符的存儲(chǔ)都需要4個(gè)字節(jié)。
簡(jiǎn)單來(lái)講憾筏,一個(gè)字符表示一個(gè)漢字或英文字母嚎杨,具體字符與字節(jié)之間的大小比例視編碼情況而定。有時(shí)候讀取的數(shù)據(jù)是亂碼氧腰,就是因?yàn)榫幋a方式不一致枫浙,需要進(jìn)行轉(zhuǎn)換,然后再按照unicode進(jìn)行編碼古拴。
二箩帚、File類
File類是java.io包下代表與平臺(tái)無(wú)關(guān)的文件和目錄,也就是說(shuō)黄痪,如果希望在程序中操作文件和目錄紧帕,都可以通過(guò)File類來(lái)完成。
①構(gòu)造函數(shù)
//構(gòu)造函數(shù)File(String pathname)
File f1 =new File("c:\\abc\\1.txt");
//File(String parent,String child)
File f2 =new File("c:\\abc","2.txt");
//File(File parent,String child)
File f3 =new File("c:"+File.separator+"abc");//separator 跨平臺(tái)分隔符
File f4 =new File(f3,"3.txt");
System.out.println(f1);//c:\abc\1.txt
路徑分隔符:
windows: "/" "" 都可以
linux/unix: "/"
注意:如果windows選擇用""做分割符的話,那么請(qǐng)記得替換成"\",因?yàn)镴ava中""代表轉(zhuǎn)義字符
所以推薦都使用"/"桅打,也可以直接使用代碼File.separator
焕参,表示跨平臺(tái)分隔符。
路徑:
相對(duì)路徑:
./表示當(dāng)前路徑
../表示上一級(jí)路徑
其中當(dāng)前路徑:默認(rèn)情況下油额,java.io 包中的類總是根據(jù)當(dāng)前用戶目錄來(lái)分析相對(duì)路徑名叠纷。此目錄由系統(tǒng)屬性 user.dir 指定,通常是 Java 虛擬機(jī)的調(diào)用目錄潦嘶∩”
絕對(duì)路徑:
絕對(duì)路徑名是完整的路徑名崇众,不需要任何其他信息就可以定位自身表示的文件
②創(chuàng)建與刪除方法
//如果文件存在返回false,否則返回true并且創(chuàng)建文件
boolean createNewFile();
//創(chuàng)建一個(gè)File對(duì)象所對(duì)應(yīng)的目錄航厚,成功返回true顷歌,否則false。且File對(duì)象必須為路徑而不是文件幔睬。只會(huì)創(chuàng)建最后一級(jí)目錄眯漩,如果上級(jí)目錄不存在就拋異常。
boolean mkdir();
//創(chuàng)建一個(gè)File對(duì)象所對(duì)應(yīng)的目錄麻顶,成功返回true赦抖,否則false。且File對(duì)象必須為路徑而不是文件辅肾。創(chuàng)建多級(jí)目錄队萤,創(chuàng)建路徑中所有不存在的目錄
boolean mkdirs() ;
//如果文件存在返回true并且刪除文件,否則返回false
boolean delete();
//在虛擬機(jī)終止時(shí)矫钓,刪除File對(duì)象所表示的文件或目錄要尔。
void deleteOnExit();
③判斷方法
boolean canExecute() ;//判斷文件是否可執(zhí)行
boolean canRead();//判斷文件是否可讀
boolean canWrite();//判斷文件是否可寫
boolean exists();//判斷文件是否存在
boolean isDirectory();//判斷是否是目錄
boolean isFile();//判斷是否是文件
boolean isHidden();//判斷是否是隱藏文件或隱藏目錄
boolean isAbsolute();//判斷是否是絕對(duì)路徑 文件不存在也能判斷
③獲取方法
String getName();//返回文件或者是目錄的名稱
String getPath();//返回路徑
String getAbsolutePath();//返回絕對(duì)路徑
String getParent();//返回父目錄,如果沒(méi)有父目錄則返回null
long lastModified();//返回最后一次修改的時(shí)間
long length();//返回文件的長(zhǎng)度
File[] listRoots();// 列出所有的根目錄(Window中就是所有系統(tǒng)的盤符)
String[] list() ;//返回一個(gè)字符串?dāng)?shù)組新娜,給定路徑下的文件或目錄名稱字符串
String[] list(FilenameFilter filter);//返回滿足過(guò)濾器要求的一個(gè)字符串?dāng)?shù)組
File[] listFiles();//返回一個(gè)文件對(duì)象數(shù)組赵辕,給定路徑下文件或目錄
File[] listFiles(FilenameFilter filter);//返回滿足過(guò)濾器要求的一個(gè)文件對(duì)象數(shù)組
其中包含了一個(gè)重要的接口FileNameFilter,該接口是個(gè)文件過(guò)濾器概龄,包含了一個(gè)accept(File dir,String name)
方法还惠,該方法依次對(duì)指定File的所有子目錄或者文件進(jìn)行迭代,按照指定條件旁钧,進(jìn)行過(guò)濾,過(guò)濾出滿足條件的所有文件互拾。
// 文件過(guò)濾
File[] files = file.listFiles(new FilenameFilter() {
@Override
public boolean accept(File file, String filename) {
return filename.endsWith(".mp3");
}
});
file目錄下的所有子文件如果滿足后綴是.mp3的條件的文件都會(huì)被過(guò)濾出來(lái)歪今。
以上就是IO流的預(yù)備知識(shí),掌握了這些內(nèi)容有助于我們更好地理解IO流颜矿,下篇文章將開始學(xué)習(xí)Java中的IO流的內(nèi)容寄猩。