写在前面:本文章基本覆盖了java IO的所有内容。java新IO没有涉及。文章依然以样例为主,由于解说内容的java书非常多了,我觉的学以致用才是真。代码是写出来的,不是看出来的。

最后欢迎大家提出意见和建议。

【案例1】创建一个新文件




1


2


3


4


5


6


7


8


9


10


11




​import​​ ​​java.io.*;​


​class​​ ​​hello{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args) {​


​File f=​​​​new​​ ​​File(​​​​"D:\\hello.txt"​​​​);​


​try​​​​{​


​f.createNewFile();​


​}​​​​catch​​ ​​(Exception e) {​


​e.printStackTrace();​


​}​


​}​


​}​



【执行结果】:

程序执行之后。在d盘下会有一个名字为hello.txt的文件。

【案例2】File类的两个常量




1


2


3


4


5


6


7




​import​​ ​​java.io.*;​


​class​​ ​​hello{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args) {​


​System.out.println(File.separator);​


​System.out.println(File.pathSeparator);​


​}​


​}​



【执行结果】:

\

;

此处多说几句:有些同学可能觉得。我直接在windows下使用\进行切割不行吗?当然是能够的。

可是在linux下就不是\了。

所以,要想使得我们的代码跨平台。更加健壮,所以,大家都採用这两个常量吧。事实上也多写不了几行。

呵呵、

如今我们使用File类中的常量改写上面的代码:




1


2


3


4


5


6


7


8


9


10


11


12




​import​​ ​​java.io.*;​


​class​​ ​​hello{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args) {​


​String fileName=​​​​"D:"​​​​+File.separator+​​​​"hello.txt"​​​​;​


​File f=​​​​new​​ ​​File(fileName);​


​try​​​​{​


​f.createNewFile();​


​}​​​​catch​​ ​​(Exception e) {​


​e.printStackTrace();​


​}​


​}​


​}​



你看,没有多写多少吧,呵呵。所以建议使用File类中的常量。

 

删除一个文件




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16




​/**​


​* 删除一个文件​


​* */​


​import​​ ​​java.io.*;​


​class​​ ​​hello{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args) {​


​String fileName=​​​​"D:"​​​​+File.separator+​​​​"hello.txt"​​​​;​


​File f=​​​​new​​ ​​File(fileName);​


​if​​​​(f.exists()){​


​f.delete();​


​}​​​​else​​​​{​


​System.out.println(​​​​"文件不存在"​​​​);​


​}​


 


​}​


​}​



创建一个目录




1


2


3


4


5


6


7


8


9


10


11




​/**​


​* 创建一个目录​


​* */​


​import​​ ​​java.io.*;​


​class​​ ​​hello{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args) {​


​String fileName=​​​​"D:"​​​​+File.separator+​​​​"hello"​​​​;​


​File f=​​​​new​​ ​​File(fileName);​


​f.mkdir();​


​}​


​}​



【执行结果】:

D盘下多了一个hello目录

 

列出指定文件夹的所有文件(包含隐藏文件):




1


2


3


4


5


6


7


8


9


10


11


12


13


14




​/**​


​* 使用list列出指定文件夹的所有文件​


​* */​


​import​​ ​​java.io.*;​


​class​​ ​​hello{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args) {​


​String fileName=​​​​"D:"​​​​+File.separator;​


​File f=​​​​new​​ ​​File(fileName);​


​String[] str=f.list();​


​for​​ ​​(​​​​int​​ ​​i =​​​​0​​​​; i < str.length; i++) {​


​System.out.println(str[i]);​


​}​


​}​


​}​



【执行结果】:

$RECYCLE.BIN

360

360Downloads

360Rec

360SoftMove

Config.Msi

da

Downloads

DriversBackup

eclipse

java web整合开发和项目实战

Lenovo

MSOCache

Program

Program Files

python

RECYGLER.{8F92DA15-A229-A4D5-B5CE-5280C8B89C19}

System Volume Information

Tomcat6

var

vod_cache_data

新建目录

(你的执行结果应该和这个不一样的。呵呵)

可是使用list返回的是String数组,。

并且列出的不是完整路径,假设想列出完整路径的话。须要使用listFiles.他返回的是File的数组

列出指定文件夹的所有文件(包含隐藏文件):




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15




​/**​


​* 使用listFiles列出指定文件夹的所有文件​


​* listFiles输出的是完整路径​


​* */​


​import​​ ​​java.io.*;​


​class​​ ​​hello{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args) {​


​String fileName=​​​​"D:"​​​​+File.separator;​


​File f=​​​​new​​ ​​File(fileName);​


​File[] str=f.listFiles();​


​for​​ ​​(​​​​int​​ ​​i =​​​​0​​​​; i < str.length; i++) {​


​System.out.println(str[i]);​


​}​


​}​


​}​



【执行结果】:

D:\$RECYCLE.BIN

D:\360

D:\360Downloads

D:\360Rec

D:\360SoftMove

D:\Config.Msi

D:\da

D:\Downloads

D:\DriversBackup

D:\eclipse

D:\java web整合开发和项目实战

D:\Lenovo

D:\MSOCache

D:\Program

D:\Program Files

D:\python

D:\RECYGLER.{8F92DA15-A229-A4D5-B5CE-5280C8B89C19}

D:\System Volume Information

D:\Tomcat6

D:\var

D:\vod_cache_data

D:\新建目录

通过比較能够指定,使用listFiles更加方便、

 

推断一个指定的路径是否为文件夹




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15




​/**​


​* 使用isDirectory推断一个指定的路径是否为文件夹​


​* */​


​import​​ ​​java.io.*;​


​class​​ ​​hello{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args) {​


​String fileName=​​​​"D:"​​​​+File.separator;​


​File f=​​​​new​​ ​​File(fileName);​


​if​​​​(f.isDirectory()){​


​System.out.println(​​​​"YES"​​​​);​


​}​​​​else​​​​{​


​System.out.println(​​​​"NO"​​​​);​


​}​


​}​


​}​



【执行结果】:YES

 

搜索指定文件夹的所有内容




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16


17


18


19


20


21


22


23


24


25


26


27




​/**​


​* 列出指定文件夹的所有内容​


​* */​


​import​​ ​​java.io.*;​


​class​​ ​​hello{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args) {​


​String fileName=​​​​"D:"​​​​+File.separator;​


​File f=​​​​new​​ ​​File(fileName);​


​print(f);​


​}​


​public​​ ​​static​​ ​​void​​ ​​print(File f){​


​if​​​​(f!=​​​​null​​​​){​


​if​​​​(f.isDirectory()){​


​File[] fileArray=f.listFiles();​


​if​​​​(fileArray!=​​​​null​​​​){​


​for​​ ​​(​​​​int​​ ​​i =​​​​0​​​​; i < fileArray.length; i++) {​


​//递归调用​


​print(fileArray[i]);​


​}​


​}​


​}​


​else​​​​{​


​System.out.println(f);​


​}​


​}​


​}​


​}​



【执行结果】:

D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\framepages\web4welcome_jsp.java

D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\help_005fhome_jsp.class

D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\help_005fhome_jsp.java

D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\home_jsp.class

D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\home_jsp.java

D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\index_jsp.class

D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\index_jsp.java

D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\login_jsp.class

D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\login_jsp.java

D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\modify_005fuser_005finfo_jsp.class

D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\modify_005fuser_005finfo_jsp.java

D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\register_005fnotify_jsp.class

D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\register_005fnotify_jsp.java

D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\sign_005fup_jsp.class

D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\sign_005fup_jsp.java

D:\Tomcat6\work\Catalina\localhost\nevel\org\apache\jsp\transit_jsp.class

……

 

【使用RandomAccessFile写入文件】




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16


17


18




​/**​


​* 使用RandomAccessFile写入文件​


​* */​


​import​​ ​​java.io.*;​


​class​​ ​​hello{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args)​​​​throws​​ ​​IOException {​


​String fileName=​​​​"D:"​​​​+File.separator+​​​​"hello.txt"​​​​;​


​File f=​​​​new​​ ​​File(fileName);​


​RandomAccessFile demo=​​​​new​​ ​​RandomAccessFile(f,​​​​"rw"​​​​);​


​demo.writeBytes(​​​​"asdsad"​​​​);​


​demo.writeInt(​​​​12​​​​);​


​demo.writeBoolean(​​​​true​​​​);​


​demo.writeChar(​​​​'A'​​​​);​


​demo.writeFloat(​​​​1​​​​.21f);​


​demo.writeDouble(​​​​12.123​​​​);​


​demo.close();   ​


​}​


​}​



假设你此时打开hello。txt查看的话,会发现那是乱码。

 

字节流

【向文件里写入字符串】




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16




​/**​


​* 字节流​


​* 向文件里写入字符串​


​* */​


​import​​ ​​java.io.*;​


​class​​ ​​hello{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args)​​​​throws​​ ​​IOException {​


​String fileName=​​​​"D:"​​​​+File.separator+​​​​"hello.txt"​​​​;​


​File f=​​​​new​​ ​​File(fileName);​


​OutputStream out =​​​​new​​ ​​FileOutputStream(f);​


​String str=​​​​"你好"​​​​;​


​byte​​​​[] b=str.getBytes();​


​out.write(b);​


​out.close();​


​}​


​}​



查看hello.txt会看到“你好”

当然也能够一个字节一个字节的写。




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16


17


18




​/**​


​* 字节流​


​* 向文件里一个字节一个字节的写入字符串​


​* */​


​import​​ ​​java.io.*;​


​class​​ ​​hello{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args)​​​​throws​​ ​​IOException {​


​String fileName=​​​​"D:"​​​​+File.separator+​​​​"hello.txt"​​​​;​


​File f=​​​​new​​ ​​File(fileName);​


​OutputStream out =​​​​new​​ ​​FileOutputStream(f);​


​String str=​​​​"你好"​​​​;​


​byte​​​​[] b=str.getBytes();​


​for​​ ​​(​​​​int​​ ​​i =​​​​0​​​​; i < b.length; i++) {​


​out.write(b[i]);​


​}​


​out.close();​


​}​


​}​



结果还是:“你好”

 

向文件里追加新内容:




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16


17


18


19




​/**​


​* 字节流​


​* 向文件里追加新内容:​


​* */​


​import​​ ​​java.io.*;​


​class​​ ​​hello{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args)​​​​throws​​ ​​IOException {​


​String fileName=​​​​"D:"​​​​+File.separator+​​​​"hello.txt"​​​​;​


​File f=​​​​new​​ ​​File(fileName);​


​OutputStream out =​​​​new​​ ​​FileOutputStream(f,​​​​true​​​​);​


​String str=​​​​"Rollen"​​​​;​


​//String str="\r\nRollen";  能够换行​


​byte​​​​[] b=str.getBytes();​


​for​​ ​​(​​​​int​​ ​​i =​​​​0​​​​; i < b.length; i++) {​


​out.write(b[i]);​


​}​


​out.close();​


​}​


​}​



【执行结果】:

你好Rollen

 

【读取文件内容】




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16




​/**​


​* 字节流​


​* 读文件内容​


​* */​


​import​​ ​​java.io.*;​


​class​​ ​​hello{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args)​​​​throws​​ ​​IOException {​


​String fileName=​​​​"D:"​​​​+File.separator+​​​​"hello.txt"​​​​;​


​File f=​​​​new​​ ​​File(fileName);​


​InputStream in=​​​​new​​ ​​FileInputStream(f);​


​byte​​​​[] b=​​​​new​​ ​​byte​​​​[​​​​1024​​​​];​


​in.read(b);​


​in.close();​


​System.out.println(​​​​new​​ ​​String(b));​


​}​


​}​



【执行结果】

你好Rollen

Rollen_

可是这个样例读取出来会有大量的空格。我们能够利用in.read(b);的返回值来设计程序。

例如以下:




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16


17




​/**​


​* 字节流​


​* 读文件内容​


​* */​


​import​​ ​​java.io.*;​


​class​​ ​​hello{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args)​​​​throws​​ ​​IOException {​


​String fileName=​​​​"D:"​​​​+File.separator+​​​​"hello.txt"​​​​;​


​File f=​​​​new​​ ​​File(fileName);​


​InputStream in=​​​​new​​ ​​FileInputStream(f);​


​byte​​​​[] b=​​​​new​​ ​​byte​​​​[​​​​1024​​​​];​


​int​​ ​​len=in.read(b);​


​in.close();​


​System.out.println(​​​​"读入长度为:"​​​​+len);​


​System.out.println(​​​​new​​ ​​String(b,​​​​0​​​​,len));​


​}​


​}​



【执行结果】:

读入长度为:18

你好Rollen

Rollen

 

读者观察上面的样例能够看出,我们预先申请了一个指定大小的空间,可是有时候这个空间可能太小。有时候可能太大,我们须要准确的大小,这样节省空间,那么我们能够这样干:




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16


17




​/**​


​* 字节流​


​* 读文件内容,节省空间​


​* */​


​import​​ ​​java.io.*;​


​class​​ ​​hello{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args)​​​​throws​​ ​​IOException {​


​String fileName=​​​​"D:"​​​​+File.separator+​​​​"hello.txt"​​​​;​


​File f=​​​​new​​ ​​File(fileName);​


​InputStream in=​​​​new​​ ​​FileInputStream(f);​


​byte​​​​[] b=​​​​new​​ ​​byte​​​​[(​​​​int​​​​)f.length()];​


​in.read(b);​


​System.out.println(​​​​"文件长度为:"​​​​+f.length());​


​in.close();​


​System.out.println(​​​​new​​ ​​String(b));​


​}​


​}​



文件长度为:18

你好Rollen

Rollen

 

将上面的样例改为一个一个读:




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16


17


18




​/**​


​* 字节流​


​* 读文件内容,节省空间​


​* */​


​import​​ ​​java.io.*;​


​class​​ ​​hello{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args)​​​​throws​​ ​​IOException {​


​String fileName=​​​​"D:"​​​​+File.separator+​​​​"hello.txt"​​​​;​


​File f=​​​​new​​ ​​File(fileName);​


​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));​


​}​


​}​



输出的结果和上面的一样。

 

细心的读者可能会发现。上面的几个样例都是在知道文件的内容多大,然后才展开的。有时候我们不知道文件有多大,这样的情况下,我们须要推断是否独到文件的末尾。




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16


17


18


19


20




​/**​


​* 字节流​


​*读文件​


​* */​


​import​​ ​​java.io.*;​


​class​​ ​​hello{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args)​​​​throws​​ ​​IOException {​


​String fileName=​​​​"D:"​​​​+File.separator+​​​​"hello.txt"​​​​;​


​File f=​​​​new​​ ​​File(fileName);​


​InputStream in=​​​​new​​ ​​FileInputStream(f);​


​byte​​​​[] b=​​​​new​​ ​​byte​​​​[​​​​1024​​​​];​


​int​​ ​​count =​​​​0​​​​;​


​int​​ ​​temp=​​​​0​​​​;​


​while​​​​((temp=in.read())!=(-​​​​1​​​​)){​


​b[count++]=(​​​​byte​​​​)temp;​


​}​


​in.close();​


​System.out.println(​​​​new​​ ​​String(b));​


​}​


​}​



【执行结果】

你好Rollen

Rollen_

提醒一下。当独到文件末尾的时候会返回-1.正常情况下是不会返回-1的

 

字符流

【向文件里写入数据】

如今我们使用字符流




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15




​/**​


​* 字符流​


​* 写入数据​


​* */​


​import​​ ​​java.io.*;​


​class​​ ​​hello{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args)​​​​throws​​ ​​IOException {​


​String fileName=​​​​"D:"​​​​+File.separator+​​​​"hello.txt"​​​​;​


​File f=​​​​new​​ ​​File(fileName);​


​Writer out =​​​​new​​ ​​FileWriter(f);​


​String str=​​​​"hello"​​​​;​


​out.write(str);​


​out.close();​


​}​


​}​



当你打开hello。txt的时候。会看到hello

事实上这个样例上之前的样例没什么差别,仅仅是你能够直接输入字符串。而不须要你将字符串转化为字节数组。

当你假设想问文件里追加内容的时候。能够使用将上面的声明out的哪一行换为:

Writer out =new FileWriter(f,true);

这样,当你执行程序的时候。会发现文件内容变为:

hellohello假设想在文件里换行的话,须要使用“\r\n”

比方将str变为String str="\r\nhello";

这样文件追加的str的内容就会换行了。

 

从文件里读内容:




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16


17




​/**​


​* 字符流​


​* 从文件里读出内容​


​* */​


​import​​ ​​java.io.*;​


​class​​ ​​hello{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args)​​​​throws​​ ​​IOException {​


​String fileName=​​​​"D:"​​​​+File.separator+​​​​"hello.txt"​​​​;​


​File f=​​​​new​​ ​​File(fileName);​


​char​​​​[] ch=​​​​new​​ ​​char​​​​[​​​​100​​​​];​


​Reader read=​​​​new​​ ​​FileReader(f);​


​int​​ ​​count=read.read(ch);​


​read.close();​


​System.out.println(​​​​"读入的长度为:"​​​​+count);​


​System.out.println(​​​​"内容为"​​​​+​​​​new​​ ​​String(ch,​​​​0​​​​,count));​


​}​


​}​



【执行结果】:

读入的长度为:17

内容为hellohello

hello

 

当然最好採用循环读取的方式。由于我们有时候不知道文件究竟有多大。




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16


17


18


19


20




​/**​


​* 字符流​


​* 从文件里读出内容​


​* */​


​import​​ ​​java.io.*;​


​class​​ ​​hello{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args)​​​​throws​​ ​​IOException {​


​String fileName=​​​​"D:"​​​​+File.separator+​​​​"hello.txt"​​​​;​


​File f=​​​​new​​ ​​File(fileName);​


​char​​​​[] ch=​​​​new​​ ​​char​​​​[​​​​100​​​​];​


​Reader read=​​​​new​​ ​​FileReader(f);​


​int​​ ​​temp=​​​​0​​​​;​


​int​​ ​​count=​​​​0​​​​;​


​while​​​​((temp=read.read())!=(-​​​​1​​​​)){​


​ch[count++]=(​​​​char​​​​)temp;​


​}​


​read.close();​


​System.out.println(​​​​"内容为"​​​​+​​​​new​​ ​​String(ch,​​​​0​​​​,count));​


​}​


​}​



执行结果:

内容为hellohello

hello

 

关于字节流和字符流的差别

实际上字节流在操作的时候本身是不会用到缓冲区的,是文件本身的直接操作的,可是字符流在操作的 时候下后是会用到缓冲区的,是通过缓冲区来操作文件的。

读者能够试着将上面的字节流和字符流的程序的最后一行关闭文件的代码凝视掉,然后执行程序看看。你就会发现使用字节流的话,文件里已经存在内容。可是使用字符流的时候,文件里还是没有内容的。这个时候就要刷新缓冲区。

使用字节流好还是字符流好呢?

答案是字节流。

首先由于硬盘上的全部文件都是以字节的形式进行传输或者保存的。包含图片等内容。可是字符仅仅是在内存中才会形成的。所以在开发中,字节流使用广泛。

文件的复制

事实上DOS下就有一个文件复制功能,比方我们想把d盘以下的hello.txt文件拷贝到d盘以下的rollen.txt文件里,那么我们就能够使用以下的命令:

copy d:\hello.txt d:\rollen.txt


执行之后你会在d盘中看见hello.txt.,而且两个文件的内容是一样的,(这是屁话)

 

以下我们使用程序来拷贝文件吧。

基本思路还是从一个文件里读入内容。边读边写入还有一个文件。就是这么简单。、

首先编写以下的代码:




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16


17


18


19


20


21


22


23


24


25


26


27


28


29




​/**​


​* 文件的复制​


​* */​


​import​​ ​​java.io.*;​


​class​​ ​​hello{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args)​​​​throws​​ ​​IOException {​


​if​​​​(args.length!=​​​​2​​​​){​


​System.out.println(​​​​"命令行參数输入有误,请检查"​​​​);​


​System.exit(​​​​1​​​​);​


​}​


​File file1=​​​​new​​ ​​File(args[​​​​0​​​​]);​


​File file2=​​​​new​​ ​​File(args[​​​​1​​​​]);​


 


​if​​​​(!file1.exists()){​


​System.out.println(​​​​"被复制的文件不存在"​​​​);​


​System.exit(​​​​1​​​​);​


​}​


​InputStream input=​​​​new​​ ​​FileInputStream(file1);​


​OutputStream output=​​​​new​​ ​​FileOutputStream(file2);​


​if​​​​((input!=​​​​null​​​​)&&(output!=​​​​null​​​​)){​


​int​​ ​​temp=​​​​0​​​​;​


​while​​​​((temp=input.read())!=(-​​​​1​​​​)){​


​output.write(temp);​


​}​


​}​


​input.close();​


​output.close(); ​


​}​


​}​



然后在命令行以下

javac hello.java

java hello d:\hello.txt d:\rollen.txt

如今你就会在d盘看到rollen。txt了。


OutputStreramWriter 和InputStreamReader类

整个IO类中除了字节流和字符流还包含字节和字符转换流。

OutputStreramWriter将输出的字符流转化为字节流

InputStreamReader将输入的字节流转换为字符流

可是无论怎样操作。最后都是以字节的形式保存在文件里的。

 

将字节输出流转化为字符输出流




1


2


3


4


5


6


7


8


9


10


11


12


13




​/**​


​* 将字节输出流转化为字符输出流​


​* */​


​import​​ ​​java.io.*;​


​class​​ ​​hello{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args)​​​​throws​​ ​​IOException {​


​String fileName= ​​​​"d:"​​​​+File.separator+​​​​"hello.txt"​​​​;​


​File file=​​​​new​​ ​​File(fileName);​


​Writer out=​​​​new​​ ​​OutputStreamWriter(​​​​new​​ ​​FileOutputStream(file));​


​out.write(​​​​"hello"​​​​);​


​out.close();​


​}​


​}​



执行结果:文件里内容为:hello

将字节输入流变为字符输入流




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15




​/**​


​* 将字节输入流变为字符输入流​


​* */​


​import​​ ​​java.io.*;​


​class​​ ​​hello{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args)​​​​throws​​ ​​IOException {​


​String fileName= ​​​​"d:"​​​​+File.separator+​​​​"hello.txt"​​​​;​


​File file=​​​​new​​ ​​File(fileName);​


​Reader read=​​​​new​​ ​​InputStreamReader(​​​​new​​ ​​FileInputStream(file));​


​char​​​​[] b=​​​​new​​ ​​char​​​​[​​​​100​​​​];​


​int​​ ​​len=read.read(b);​


​System.out.println(​​​​new​​ ​​String(b,​​​​0​​​​,len));​


​read.close();​


​}​


​}​



【执行结果】:hello

前面列举的输出输入都是以文件进行的,如今我们以内容为输出输入目的地,使用内存操作流

ByteArrayInputStream 主要将内容写入内容

ByteArrayOutputStream  主要将内容从内存输出

使用内存操作流将一个大写字母转化为小写字母




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16


17


18


19


20




​/**​


​* 使用内存操作流将一个大写字母转化为小写字母​


​* */​


​import​​ ​​java.io.*;​


​class​​ ​​hello{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args)​​​​throws​​ ​​IOException {​


​String str=​​​​"ROLLENHOLT"​​​​;​


​ByteArrayInputStream input=​​​​new​​ ​​ByteArrayInputStream(str.getBytes());​


​ByteArrayOutputStream output=​​​​new​​ ​​ByteArrayOutputStream();​


​int​​ ​​temp=​​​​0​​​​;​


​while​​​​((temp=input.read())!=-​​​​1​​​​){​


​char​​ ​​ch=(​​​​char​​​​)temp;​


​output.write(Character.toLowerCase(ch));​


​}​


​String outStr=output.toString();​


​input.close();​


​output.close();​


​System.out.println(outStr);​


​}​


​}​



【执行结果】:

rollenholt

内容操作流一般使用来生成一些暂时信息採用的,这样能够避免删除的麻烦。

管道流

管道流主要能够进行两个线程之间的通信。

PipedOutputStream 管道输出流

PipedInputStream 管道输入流

验证管道流




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16


17


18


19


20


21


22


23


24


25


26


27


28


29


30


31


32


33


34


35


36


37


38


39


40


41


42


43


44


45


46


47


48


49


50


51


52


53


54


55


56


57


58


59


60


61


62


63


64


65


66


67


68


69


70


71


72


73




​/**​


​* 验证管道流​


​* */​


​import​​ ​​java.io.*;​


 


​/**​


​* 消息发送类​


​* */​


​class​​ ​​Send ​​​​implements​​ ​​Runnable{​


​private​​ ​​PipedOutputStream out=​​​​null​​​​;​


​public​​ ​​Send() {​


​out=​​​​new​​ ​​PipedOutputStream();​


​}​


​public​​ ​​PipedOutputStream getOut(){​


​return​​ ​​this​​​​.out;​


​}​


​public​​ ​​void​​ ​​run(){​


​String message=​​​​"hello , Rollen"​​​​;​


​try​​​​{​


​out.write(message.getBytes());​


​}​​​​catch​​ ​​(Exception e) {​


​e.printStackTrace();​


​}​​​​try​​​​{​


​out.close();​


​}​​​​catch​​ ​​(Exception e) {​


​e.printStackTrace();​


​}​


​}​


​}​


 


​/**​


​* 接受消息类​


​* */​


​class​​ ​​Recive ​​​​implements​​ ​​Runnable{​


​private​​ ​​PipedInputStream input=​​​​null​​​​;​


​public​​ ​​Recive(){​


​this​​​​.input=​​​​new​​ ​​PipedInputStream();​


​}​


​public​​ ​​PipedInputStream getInput(){​


​return​​ ​​this​​​​.input;​


​}​


​public​​ ​​void​​ ​​run(){​


​byte​​​​[] b=​​​​new​​ ​​byte​​​​[​​​​1000​​​​];​


​int​​ ​​len=​​​​0​​​​;​


​try​​​​{​


​len=​​​​this​​​​.input.read(b);​


​}​​​​catch​​ ​​(Exception e) {​


​e.printStackTrace();​


​}​​​​try​​​​{​


​input.close();​


​}​​​​catch​​ ​​(Exception e) {​


​e.printStackTrace();​


​}​


​System.out.println(​​​​"接受的内容为 "​​​​+(​​​​new​​ ​​String(b,​​​​0​​​​,len)));​


​}​


​}​


​/**​


​* 測试类​


​* */​


​class​​ ​​hello{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args)​​​​throws​​ ​​IOException {​


​Send send=​​​​new​​ ​​Send();​


​Recive recive=​​​​new​​ ​​Recive();​


​try​​​​{​


​//管道连接​


​send.getOut().connect(recive.getInput());​


​}​​​​catch​​ ​​(Exception e) {​


​e.printStackTrace();​


​}​


​new​​ ​​Thread(send).start();​


​new​​ ​​Thread(recive).start();​


​}​


​}​



【执行结果】:

接受的内容为 hello , Rollen

打印流




1


2


3


4


5


6


7


8


9


10


11


12


13


14




​/**​


​* 使用PrintStream进行输出​


​* */​


​import​​ ​​java.io.*;​


 


​class​​ ​​hello {​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args)​​​​throws​​ ​​IOException {​


​PrintStream print = ​​​​new​​ ​​PrintStream(​​​​new​​ ​​FileOutputStream(​​​​new​​ ​​File(​​​​"d:"​


​+ File.separator + ​​​​"hello.txt"​​​​)));​


​print.println(​​​​true​​​​);​


​print.println(​​​​"Rollen"​​​​);​


​print.close();​


​}​


​}​



【执行结果】:

true

Rollen

当然也能够格式化输出




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15




​/**​


​* 使用PrintStream进行输出​


​* 并进行格式化​


​* */​


​import​​ ​​java.io.*;​


​class​​ ​​hello {​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args)​​​​throws​​ ​​IOException {​


​PrintStream print = ​​​​new​​ ​​PrintStream(​​​​new​​ ​​FileOutputStream(​​​​new​​ ​​File(​​​​"d:"​


​+ File.separator + ​​​​"hello.txt"​​​​)));​


​String name=​​​​"Rollen"​​​​;​


​int​​ ​​age=​​​​20​​​​;​


​print.printf(​​​​"姓名:%s. 年龄:%d."​​​​,name,age);​


​print.close();​


​}​


​}​



【执行结果】:

姓名:Rollen. 年龄:20.

 

使用OutputStream向屏幕上输出内容




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16


17


18


19




​/**​


​* 使用OutputStream向屏幕上输出内容 ​


​* */​


​import​​ ​​java.io.*;​


​class​​ ​​hello {​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args)​​​​throws​​ ​​IOException {​


​OutputStream out=System.out;​


​try​​​​{​


​out.write(​​​​"hello"​​​​.getBytes());​


​}​​​​catch​​ ​​(Exception e) {​


​e.printStackTrace();​


​}​


​try​​​​{​


​out.close();​


​}​​​​catch​​ ​​(Exception e) {​


​e.printStackTrace();​


​}​


​}​


​}​



【执行结果】:

hello

 

输入输出重定向




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16


17


18


19


20


21




​import​​ ​​java.io.File;​


​import​​ ​​java.io.FileNotFoundException;​


​import​​ ​​java.io.FileOutputStream;​


​import​​ ​​java.io.PrintStream;​


 


​/**​


​* 为System.out.println()重定向输出​


​* */​


​public​​ ​​class​​ ​​systemDemo{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args){​


​// 此刻直接输出到屏幕​


​System.out.println(​​​​"hello"​​​​);​


​File file = ​​​​new​​ ​​File(​​​​"d:"​​ ​​+ File.separator +​​​​"hello.txt"​​​​);​


​try​​​​{​


​System.setOut(​​​​new​​ ​​PrintStream(​​​​new​​ ​​FileOutputStream(file)));​


​}​​​​catch​​​​(FileNotFoundException e){​


​e.printStackTrace();​


​}​


​System.out.println(​​​​"这些内容在文件里才干看到哦!"​​​​);​


​}​


​}​



【执行结果】:

eclipse的控制台输出的是hello。然后当我们查看d盘以下的hello.txt文件的时候,会在里面看到:这些内容在文件里才干看到哦!




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16


17


18


19


20




​import​​ ​​java.io.File;​


​import​​ ​​java.io.FileNotFoundException;​


​import​​ ​​java.io.FileOutputStream;​


​import​​ ​​java.io.PrintStream;​


 


​/**​


​* System.err重定向 这个样例也提示我们能够使用这样的方法保存错误信息​


​* */​


​public​​ ​​class​​ ​​systemErr{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args){​


​File file = ​​​​new​​ ​​File(​​​​"d:"​​ ​​+ File.separator +​​​​"hello.txt"​​​​);​


​System.err.println(​​​​"这些在控制台输出"​​​​);​


​try​​​​{​


​System.setErr(​​​​new​​ ​​PrintStream(​​​​new​​ ​​FileOutputStream(file)));​


​}​​​​catch​​​​(FileNotFoundException e){​


​e.printStackTrace();​


​}​


​System.err.println(​​​​"这些在文件里才干看到哦!"​​​​);​


​}​


​}​



【执行结果】:

你会在eclipse的控制台看到红色的输出:“这些在控制台输出”,然后在d盘以下的hello.txt中会看到:这些在文件里才干看到哦!




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16


17


18


19


20


21


22


23


24


25


26


27


28


29


30




​import​​ ​​java.io.File;​


​import​​ ​​java.io.FileInputStream;​


​import​​ ​​java.io.FileNotFoundException;​


​import​​ ​​java.io.IOException;​


 


​/**​


​* System.in重定向​


​* */​


​public​​ ​​class​​ ​​systemIn{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args){​


​File file = ​​​​new​​ ​​File(​​​​"d:"​​ ​​+ File.separator +​​​​"hello.txt"​​​​);​


​if​​​​(!file.exists()){​


​return​​​​;​


​}​​​​else​​​​{​


​try​​​​{​


​System.setIn(​​​​new​​ ​​FileInputStream(file));​


​}​​​​catch​​​​(FileNotFoundException e){​


​e.printStackTrace();​


​}​


​byte​​​​[] bytes =​​​​new​​ ​​byte​​​​[​​​​1024​​​​];​


​int​​ ​​len =​​​​0​​​​;​


​try​​​​{​


​len = System.in.read(bytes);​


​}​​​​catch​​​​(IOException e){​


​e.printStackTrace();​


​}​


​System.out.println(​​​​"读入的内容为:"​​ ​​+​​​​new​​ ​​String(bytes, ​​​​0​​​​, len));​


​}​


​}​


​}​



【执行结果】:

前提是我的d盘以下的hello.txt中的内容是:“这些文件里的内容哦!”,然后执行程序,输出的结果为:读入的内容为:这些文件里的内容哦!

 

BufferedReader的小样例

注意: BufferedReader仅仅能接受字符流的缓冲区。由于每个中文须要占领两个字节。所以须要将System.in这个字节输入流变为字符输入流。採用:





​BufferedReader buf = ​​​​new​​ ​​BufferedReader(​


​new​​ ​​InputStreamReader(System.in));​



以下给一个实例:




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16


17


18


19


20


21




​import​​ ​​java.io.BufferedReader;​


​import​​ ​​java.io.IOException;​


​import​​ ​​java.io.InputStreamReader;​


 


​/**​


​* 使用缓冲区从键盘上读入内容​


​* */​


​public​​ ​​class​​ ​​BufferedReaderDemo{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args){​


​BufferedReader buf = ​​​​new​​ ​​BufferedReader(​


​new​​ ​​InputStreamReader(System.in));​


​String str = ​​​​null​​​​;​


​System.out.println(​​​​"请输入内容"​​​​);​


​try​​​​{​


​str = buf.readLine();​


​}​​​​catch​​​​(IOException e){​


​e.printStackTrace();​


​}​


​System.out.println(​​​​"你输入的内容是:"​​ ​​+ str);​


​}​


​}​



执行结果:

请输入内容

dasdas

你输入的内容是:dasdas

 

Scanner类

事实上我们比較经常使用的是採用Scanner类来进行数据输入,以下来给一个Scanner的样例吧




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16


17


18




​import​​ ​​java.util.Scanner;​


 


​/**​


​* Scanner的小样例,从键盘读数据​


​* */​


​public​​ ​​class​​ ​​ScannerDemo{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args){​


​Scanner sca = ​​​​new​​ ​​Scanner(System.in);​


​// 读一个整数​


​int​​ ​​temp = sca.nextInt();​


​System.out.println(temp);​


​//读取浮点数​


​float​​ ​​flo=sca.nextFloat();​


​System.out.println(flo);​


​//读取字符​


​//...等等的,都是一些太基础的,就不师范了。​


​}​


​}​



事实上Scanner能够接受不论什么的输入流

以下给一个使用Scanner类从文件里读出内容




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16


17


18


19


20


21




​import​​ ​​java.io.File;​


​import​​ ​​java.io.FileNotFoundException;​


​import​​ ​​java.util.Scanner;​


 


​/**​


​* Scanner的小样例,从文件里读内容​


​* */​


​public​​ ​​class​​ ​​ScannerDemo{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args){​


 


​File file = ​​​​new​​ ​​File(​​​​"d:"​​ ​​+ File.separator +​​​​"hello.txt"​​​​);​


​Scanner sca = ​​​​null​​​​;​


​try​​​​{​


​sca = ​​​​new​​ ​​Scanner(file);​


​}​​​​catch​​​​(FileNotFoundException e){​


​e.printStackTrace();​


​}​


​String str = sca.next();​


​System.out.println(​​​​"从文件里读取的内容是:"​​ ​​+ str);​


​}​


​}​



【执行结果】:

从文件里读取的内容是:这些文件里的内容哦。

数据操作流DataOutputStream、DataInputStream类




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16


17




​import​​ ​​java.io.DataOutputStream;​


​import​​ ​​java.io.File;​


​import​​ ​​java.io.FileOutputStream;​


​import​​ ​​java.io.IOException;​


 


​public​​ ​​class​​ ​​DataOutputStreamDemo{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args)​​​​throws​​ ​​IOException{​


​File file = ​​​​new​​ ​​File(​​​​"d:"​​ ​​+ File.separator +​​​​"hello.txt"​​​​);​


​char​​​​[] ch = {​​​​'A'​​​​, ​​​​'B'​​​​,​​​​'C'​​ ​​};​


​DataOutputStream out = ​​​​null​​​​;​


​out = ​​​​new​​ ​​DataOutputStream(​​​​new​​ ​​FileOutputStream(file));​


​for​​​​(​​​​char​​ ​​temp : ch){​


​out.writeChar(temp);​


​}​


​out.close();​


​}​


​}​



A B C

如今我们在上面样例的基础上,使用DataInputStream读出内容




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16


17


18




​import​​ ​​java.io.DataInputStream;​


​import​​ ​​java.io.File;​


​import​​ ​​java.io.FileInputStream;​


​import​​ ​​java.io.IOException;​


 


​public​​ ​​class​​ ​​DataOutputStreamDemo{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args)​​​​throws​​ ​​IOException{​


​File file = ​​​​new​​ ​​File(​​​​"d:"​​ ​​+ File.separator +​​​​"hello.txt"​​​​);​


​DataInputStream input = ​​​​new​​ ​​DataInputStream(​​​​new​​ ​​FileInputStream(file));​


​char​​​​[] ch =​​​​new​​ ​​char​​​​[​​​​10​​​​];​


​int​​ ​​count =​​​​0​​​​;​


​char​​ ​​temp;​


​while​​​​((temp = input.readChar()) !=​​​​'C'​​​​){​


​ch[count++] = temp;​


​}​


​System.out.println(ch);​


​}​


​}​



【执行结果】:

AB

合并流 SequenceInputStream

SequenceInputStream主要用来将2个流合并在一起,比方将两个txt中的内容合并为另外一个txt。

以下给出一个实例:




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16


17


18


19


20


21


22


23


24


25


26


27


28


29


30


31




​import​​ ​​java.io.File;​


​import​​ ​​java.io.FileInputStream;​


​import​​ ​​java.io.FileOutputStream;​


​import​​ ​​java.io.IOException;​


​import​​ ​​java.io.InputStream;​


​import​​ ​​java.io.OutputStream;​


​import​​ ​​java.io.SequenceInputStream;​


 


​/**​


​* 将两个文本文件合并为另外一个文本文件​


​* */​


​public​​ ​​class​​ ​​SequenceInputStreamDemo{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args)​​​​throws​​ ​​IOException{​


​File file1 = ​​​​new​​ ​​File(​​​​"d:"​​ ​​+ File.separator +​​​​"hello1.txt"​​​​);​


​File file2 = ​​​​new​​ ​​File(​​​​"d:"​​ ​​+ File.separator +​​​​"hello2.txt"​​​​);​


​File file3 = ​​​​new​​ ​​File(​​​​"d:"​​ ​​+ File.separator +​​​​"hello.txt"​​​​);​


​InputStream input1 = ​​​​new​​ ​​FileInputStream(file1);​


​InputStream input2 = ​​​​new​​ ​​FileInputStream(file2);​


​OutputStream output = ​​​​new​​ ​​FileOutputStream(file3);​


​// 合并流​


​SequenceInputStream sis = ​​​​new​​ ​​SequenceInputStream(input1, input2);​


​int​​ ​​temp =​​​​0​​​​;​


​while​​​​((temp = sis.read()) != -​​​​1​​​​){​


​output.write(temp);​


​}​


​input1.close();​


​input2.close();​


​output.close();​


​sis.close();​


​}​


​}​



【执行结果】

结果会在hello.txt文件里包括hello1.txt和hello2.txt文件里的内容。

文件压缩 ZipOutputStream类

先举一个压缩单个文件的样例吧:




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16


17


18


19


20


21


22


23


24


25


26




​import​​ ​​java.io.File;​


​import​​ ​​java.io.FileInputStream;​


​import​​ ​​java.io.FileOutputStream;​


​import​​ ​​java.io.IOException;​


​import​​ ​​java.io.InputStream;​


​import​​ ​​java.util.zip.ZipEntry;​


​import​​ ​​java.util.zip.ZipOutputStream;​


 


​public​​ ​​class​​ ​​ZipOutputStreamDemo1{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args)​​​​throws​​ ​​IOException{​


​File file = ​​​​new​​ ​​File(​​​​"d:"​​ ​​+ File.separator +​​​​"hello.txt"​​​​);​


​File zipFile = ​​​​new​​ ​​File(​​​​"d:"​​ ​​+ File.separator +​​​​"hello.zip"​​​​);​


​InputStream input = ​​​​new​​ ​​FileInputStream(file);​


​ZipOutputStream zipOut = ​​​​new​​ ​​ZipOutputStream(​​​​new​​ ​​FileOutputStream(​


​zipFile));​


​zipOut.putNextEntry(​​​​new​​ ​​ZipEntry(file.getName()));​


​// 设置凝视​


​zipOut.setComment(​​​​"hello"​​​​);​


​int​​ ​​temp =​​​​0​​​​;​


​while​​​​((temp = input.read()) != -​​​​1​​​​){​


​zipOut.write(temp);​


​}​


​input.close();​


​zipOut.close();​


​}​


​}​



【执行结果】

执行结果之前,我创建了一个hello.txt的文件,原本大小56个字节。可是压缩之后产生hello.zip之后,竟然变成了175个字节,有点搞不懂。

只是结果肯定是正确的,我仅仅是提出我的一个疑问而已。


上面的这个样例測试的是压缩单个文件,以下的们来看看怎样压缩多个文件。




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16


17


18


19


20


21


22


23


24


25


26


27


28


29


30


31


32


33


34


35


36




​import​​ ​​java.io.File;​


​import​​ ​​java.io.FileInputStream;​


​import​​ ​​java.io.FileOutputStream;​


​import​​ ​​java.io.IOException;​


​import​​ ​​java.io.InputStream;​


​import​​ ​​java.util.zip.ZipEntry;​


​import​​ ​​java.util.zip.ZipOutputStream;​


 


​/**​


​* 一次性压缩多个文件​


​* */​


​public​​ ​​class​​ ​​ZipOutputStreamDemo2{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args)​​​​throws​​ ​​IOException{​


​// 要被压缩的目录​


​File file = ​​​​new​​ ​​File(​​​​"d:"​​ ​​+ File.separator +​​​​"temp"​​​​);​


​File zipFile = ​​​​new​​ ​​File(​​​​"d:"​​ ​​+ File.separator +​​​​"zipFile.zip"​​​​);​


​InputStream input = ​​​​null​​​​;​


​ZipOutputStream zipOut = ​​​​new​​ ​​ZipOutputStream(​​​​new​​ ​​FileOutputStream(​


​zipFile));​


​zipOut.setComment(​​​​"hello"​​​​);​


​if​​​​(file.isDirectory()){​


​File[] files = file.listFiles();​


​for​​​​(​​​​int​​ ​​i =​​​​0​​​​; i < files.length; ++i){​


​input = ​​​​new​​ ​​FileInputStream(files[i]);​


​zipOut.putNextEntry(​​​​new​​ ​​ZipEntry(file.getName()​


​+ File.separator + files[i].getName()));​


​int​​ ​​temp =​​​​0​​​​;​


​while​​​​((temp = input.read()) != -​​​​1​​​​){​


​zipOut.write(temp);​


​}​


​input.close();​


​}​


​}​


​zipOut.close();​


​}​


​}​



【执行结果】

先看看要被压缩的文件吧:


接下来看看压缩之后的:


大家自然想到,既然能压缩。自然能解压缩,在谈解压缩之前。我们会用到一个ZipFile类,先给一个这个样例吧。

java中的每个压缩文件都是能够使用ZipFile来进行表示的




1


2


3


4


5


6


7


8


9


10


11


12


13


14




​import​​ ​​java.io.File;​


​import​​ ​​java.io.IOException;​


​import​​ ​​java.util.zip.ZipFile;​


 


​/**​


​* ZipFile演示​


​* */​


​public​​ ​​class​​ ​​ZipFileDemo{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args)​​​​throws​​ ​​IOException{​


​File file = ​​​​new​​ ​​File(​​​​"d:"​​ ​​+ File.separator +​​​​"hello.zip"​​​​);​


​ZipFile zipFile = ​​​​new​​ ​​ZipFile(file);​


​System.out.println(​​​​"压缩文件的名称为:"​​ ​​+ zipFile.getName());​


​}​


​}​



【执行结果】:

压缩文件的名称为:d:\hello.zip

 

如今我们呢是时候来看看怎样加压缩文件了,和之前一样,先让我们来解压单个压缩文件(也就是压缩文件里仅仅有一个文件的情况)。我们採用前面的样例产生的压缩文件hello.zip




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16


17


18


19


20


21


22


23


24


25


26


27




​import​​ ​​java.io.File;​


​import​​ ​​java.io.FileOutputStream;​


​import​​ ​​java.io.IOException;​


​import​​ ​​java.io.InputStream;​


​import​​ ​​java.io.OutputStream;​


​import​​ ​​java.util.zip.ZipEntry;​


​import​​ ​​java.util.zip.ZipFile;​


 


​/**​


​* 解压缩文件(压缩文件里仅仅有一个文件的情况)​


​* */​


​public​​ ​​class​​ ​​ZipFileDemo2{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args)​​​​throws​​ ​​IOException{​


​File file = ​​​​new​​ ​​File(​​​​"d:"​​ ​​+ File.separator +​​​​"hello.zip"​​​​);​


​File outFile = ​​​​new​​ ​​File(​​​​"d:"​​ ​​+ File.separator +​​​​"unZipFile.txt"​​​​);​


​ZipFile zipFile = ​​​​new​​ ​​ZipFile(file);​


​ZipEntry entry = zipFile.getEntry(​​​​"hello.txt"​​​​);​


​InputStream input = zipFile.getInputStream(entry);​


​OutputStream output = ​​​​new​​ ​​FileOutputStream(outFile);​


​int​​ ​​temp =​​​​0​​​​;​


​while​​​​((temp = input.read()) != -​​​​1​​​​){​


​output.write(temp);​


​}​


​input.close();​


​output.close();​


​}​


​}​



【执行结果】:

解压缩之前:


这个压缩文件还是175字节

解压之后产生:


又回到了56字节。表示郁闷。

 

如今让我们来解压一个压缩文件里包括多个文件的情况吧

ZipInputStream类

当我们须要解压缩多个文件的时候,ZipEntry就无法使用了。假设想操作更加复杂的压缩文件。我们就必须使用ZipInputStream类




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16


17


18


19


20


21


22


23


24


25


26


27


28


29


30


31


32


33


34


35


36


37


38


39


40


41


42




​import​​ ​​java.io.File;​


​import​​ ​​java.io.FileInputStream;​


​import​​ ​​java.io.FileOutputStream;​


​import​​ ​​java.io.IOException;​


​import​​ ​​java.io.InputStream;​


​import​​ ​​java.io.OutputStream;​


​import​​ ​​java.util.zip.ZipEntry;​


​import​​ ​​java.util.zip.ZipFile;​


​import​​ ​​java.util.zip.ZipInputStream;​


 


​/**​


​* 解压缩一个压缩文件里包括多个文件的情况​


​* */​


​public​​ ​​class​​ ​​ZipFileDemo3{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args)​​​​throws​​ ​​IOException{​


​File file = ​​​​new​​ ​​File(​​​​"d:"​​ ​​+ File.separator +​​​​"zipFile.zip"​​​​);​


​File outFile = ​​​​null​​​​;​


​ZipFile zipFile = ​​​​new​​ ​​ZipFile(file);​


​ZipInputStream zipInput = ​​​​new​​ ​​ZipInputStream(​​​​new​​ ​​FileInputStream(file));​


​ZipEntry entry = ​​​​null​​​​;​


​InputStream input = ​​​​null​​​​;​


​OutputStream output = ​​​​null​​​​;​


​while​​​​((entry = zipInput.getNextEntry()) !=​​​​null​​​​){​


​System.out.println(​​​​"解压缩"​​ ​​+ entry.getName() +​​​​"文件"​​​​);​


​outFile = ​​​​new​​ ​​File(​​​​"d:"​​ ​​+ File.separator + entry.getName());​


​if​​​​(!outFile.getParentFile().exists()){​


​outFile.getParentFile().mkdir();​


​}​


​if​​​​(!outFile.exists()){​


​outFile.createNewFile();​


​}​


​input = zipFile.getInputStream(entry);​


​output = ​​​​new​​ ​​FileOutputStream(outFile);​


​int​​ ​​temp =​​​​0​​​​;​


​while​​​​((temp = input.read()) != -​​​​1​​​​){​


​output.write(temp);​


​}​


​input.close();​


​output.close();​


​}​


​}​


​}​



【执行结果】:

被解压的文件:


解压之后再D盘下会出现一个temp目录,里面内容:


PushBackInputStream回退流




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16


17


18


19


20


21


22


23


24


25


26




​import​​ ​​java.io.ByteArrayInputStream;​


​import​​ ​​java.io.IOException;​


​import​​ ​​java.io.PushbackInputStream;​


 


​/**​


​* 回退流操作​


​* */​


​public​​ ​​class​​ ​​PushBackInputStreamDemo{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args)​​​​throws​​ ​​IOException{​


​String str = ​​​​"hello,rollenholt"​​​​;​


​PushbackInputStream push = ​​​​null​​​​;​


​ByteArrayInputStream bat = ​​​​null​​​​;​


​bat = ​​​​new​​ ​​ByteArrayInputStream(str.getBytes());​


​push = ​​​​new​​ ​​PushbackInputStream(bat);​


​int​​ ​​temp =​​​​0​​​​;​


​while​​​​((temp = push.read()) != -​​​​1​​​​){​


​if​​​​(temp ==​​​​','​​​​){​


​push.unread(temp);​


​temp = push.read();​


​System.out.print(​​​​"(回退"​​ ​​+ (​​​​char​​​​) temp +​​​​") "​​​​);​


​}​​​​else​​​​{​


​System.out.print((​​​​char​​​​) temp);​


​}​


​}​


​}​


​}​



【执行结果】:

hello(回退,) rollenholt




1


2


3


4


5


6


7


8




​/**​


​* 取得本地的默认编码​


​* */​


​public​​ ​​class​​ ​​CharSetDemo{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args){​


​System.out.println(​​​​"系统默认编码为:"​​ ​​+ System.getProperty(​​​​"file.encoding"​​​​));​


​}​


​}​



【执行结果】:

系统默认编码为:GBK

 

乱码的产生:





​import​​ ​​java.io.File;​


​import​​ ​​java.io.FileOutputStream;​


​import​​ ​​java.io.IOException;​


​import​​ ​​java.io.OutputStream;​


 


​/**​


​* 乱码的产生​


​* */​


​public​​ ​​class​​ ​​CharSetDemo2{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args)​​​​throws​​ ​​IOException{​


​File file = ​​​​new​​ ​​File(​​​​"d:"​​ ​​+ File.separator +​​​​"hello.txt"​​​​);​


​OutputStream out = ​​​​new​​ ​​FileOutputStream(file);​


​byte​​​​[] bytes =​​​​"你好"​​​​.getBytes(​​​​"ISO8859-1"​​​​);​


​out.write(bytes);​


​out.close();​


​}​


​}​



【执行结果】:

?

?

 

普通情况下产生乱码,都是因为编码不一致的问题。

对象的序列化

对象序列化就是把一个对象变为二进制数据流的一种方法。

一个类要想被序列化,即可必须实现java.io.Serializable接口。尽管这个接口中没有不论什么方法,就如同之前的cloneable接口一样。实现了这个接口之后。就表示这个类具有被序列化的能力。

先让我们实现一个具有序列化能力的类吧:




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16


17


18


19




​import​​ ​​java.io.*;​


​/**​


​* 实现具有序列化能力的类​


​* */​


​public​​ ​​class​​ ​​SerializableDemo​​​​implements​​ ​​Serializable{​


​public​​ ​​SerializableDemo(){​


 


​}​


​public​​ ​​SerializableDemo(String name,​​​​int​​ ​​age){​


​this​​​​.name=name;​


​this​​​​.age=age;​


​}​


​@Override​


​public​​ ​​String toString(){​


​return​​ ​​"姓名:"​​​​+name+​​​​"  年龄:"​​​​+age;​


​}​


​private​​ ​​String name;​


​private​​ ​​int​​ ​​age;​


​}​



这个类就具有实现序列化能力。

在继续将序列化之前,先将一下ObjectInputStream和ObjectOutputStream这两个类

先给一个ObjectOutputStream的样例吧:




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16


17


18


19


20


21


22


23


24


25


26


27


28


29


30


31


32


33


34


35


36


37


38


39




​import​​ ​​java.io.Serializable;​


​import​​ ​​java.io.File;​


​import​​ ​​java.io.FileOutputStream;​


​import​​ ​​java.io.IOException;​


​import​​ ​​java.io.ObjectOutputStream;​


 


​/**​


​* 实现具有序列化能力的类​


​* */​


​public​​ ​​class​​ ​​Person​​​​implements​​ ​​Serializable{​


​public​​ ​​Person(){​


 


​}​


 


​public​​ ​​Person(String name,​​​​int​​ ​​age){​


​this​​​​.name = name;​


​this​​​​.age = age;​


​}​


 


​@Override​


​public​​ ​​String toString(){​


​return​​ ​​"姓名:"​​ ​​+ name +​​​​"  年龄:"​​ ​​+ age;​


​}​


 


​private​​ ​​String name;​


​private​​ ​​int​​ ​​age;​


​}​


​/**​


​* 示范ObjectOutputStream​


​* */​


​public​​ ​​class​​ ​​ObjectOutputStreamDemo{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args)​​​​throws​​ ​​IOException{​


​File file = ​​​​new​​ ​​File(​​​​"d:"​​ ​​+ File.separator +​​​​"hello.txt"​​​​);​


​ObjectOutputStream oos = ​​​​new​​ ​​ObjectOutputStream(​​​​new​​ ​​FileOutputStream(​


​file));​


​oos.writeObject(​​​​new​​ ​​Person(​​​​"rollen"​​​​,​​​​20​​​​));​


​oos.close();​


​}​


​}​



【执行结果】:

当我们查看产生的hello.txt的时候。看到的是乱码,呵呵。由于是二进制文件。

尽管我们不能直接查看里面的内容。可是我们能够使用ObjectInputStream类查看:




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16


17




​import​​ ​​java.io.File;​


​import​​ ​​java.io.FileInputStream;​


​import​​ ​​java.io.ObjectInputStream;​


 


​/**​


​* ObjectInputStream示范​


​* */​


​public​​ ​​class​​ ​​ObjectInputStreamDemo{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args)​​​​throws​​ ​​Exception{​


​File file = ​​​​new​​ ​​File(​​​​"d:"​​ ​​+ File.separator +​​​​"hello.txt"​​​​);​


​ObjectInputStream input = ​​​​new​​ ​​ObjectInputStream(​​​​new​​ ​​FileInputStream(​


​file));​


​Object obj = input.readObject();​


​input.close();​


​System.out.println(obj);​


​}​


​}​



【执行结果】

姓名:rollen  年龄:20

 

究竟序列化什么内容呢?

事实上仅仅有属性会被序列化。

Externalizable接口

被Serializable接口声明的类的对象的属性都将被序列化,可是假设想自己定义序列化的内容的时候,就须要实现Externalizable接口。

当一个类要使用Externalizable这个接口的时候,这个类中必需要有一个无參的构造函数,假设没有的话,在构造的时候会产生异常。这是由于在反序列话的时候会默认调用无參的构造函数。

如今我们来演示一下序列化和反序列话:




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16


17


18


19


20


21


22


23


24


25


26


27


28


29


30


31


32


33


34


35


36


37


38


39


40


41


42


43


44


45


46


47


48


49


50


51


52


53


54


55


56


57


58


59


60


61


62


63


64


65


66


67


68


69


70


71


72




​package​​ ​​IO;​


 


​import​​ ​​java.io.Externalizable;​


​import​​ ​​java.io.File;​


​import​​ ​​java.io.FileInputStream;​


​import​​ ​​java.io.FileOutputStream;​


​import​​ ​​java.io.IOException;​


​import​​ ​​java.io.ObjectInput;​


​import​​ ​​java.io.ObjectInputStream;​


​import​​ ​​java.io.ObjectOutput;​


​import​​ ​​java.io.ObjectOutputStream;​


 


​/**​


​* 序列化和反序列化的操作​


​* */​


​public​​ ​​class​​ ​​ExternalizableDemo{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args)​​​​throws​​ ​​Exception{​


​ser(); ​​​​// 序列化​


​dser(); ​​​​// 反序列话​


​}​


 


​public​​ ​​static​​ ​​void​​ ​​ser()​​​​throws​​ ​​Exception{​


​File file = ​​​​new​​ ​​File(​​​​"d:"​​ ​​+ File.separator +​​​​"hello.txt"​​​​);​


​ObjectOutputStream out = ​​​​new​​ ​​ObjectOutputStream(​​​​new​​ ​​FileOutputStream(​


​file));​


​out.writeObject(​​​​new​​ ​​Person(​​​​"rollen"​​​​,​​​​20​​​​));​


​out.close();​


​}​


 


​public​​ ​​static​​ ​​void​​ ​​dser()​​​​throws​​ ​​Exception{​


​File file = ​​​​new​​ ​​File(​​​​"d:"​​ ​​+ File.separator +​​​​"hello.txt"​​​​);​


​ObjectInputStream input = ​​​​new​​ ​​ObjectInputStream(​​​​new​​ ​​FileInputStream(​


​file));​


​Object obj = input.readObject();​


​input.close();​


​System.out.println(obj);​


​}​


​}​


 


​class​​ ​​Person ​​​​implements​​ ​​Externalizable{​


​public​​ ​​Person(){​


 


​}​


 


​public​​ ​​Person(String name,​​​​int​​ ​​age){​


​this​​​​.name = name;​


​this​​​​.age = age;​


​}​


 


​@Override​


​public​​ ​​String toString(){​


​return​​ ​​"姓名:"​​ ​​+ name +​​​​"  年龄:"​​ ​​+ age;​


​}​


 


​// 复写这种方法,依据须要能够保存的属性或者详细内容,在序列化的时候使用​


​@Override​


​public​​ ​​void​​ ​​writeExternal(ObjectOutput out)​​​​throws​​ ​​IOException{​


​out.writeObject(​​​​this​​​​.name);​


​out.writeInt(age);​


​}​


 


​// 复写这种方法。依据须要读取内容 反序列话的时候须要​


​@Override​


​public​​ ​​void​​ ​​readExternal(ObjectInput in)​​​​throws​​ ​​IOException,​


​ClassNotFoundException{​


​this​​​​.name = (String) in.readObject();​


​this​​​​.age = in.readInt();​


​}​


 


​private​​ ​​String name;​


​private​​ ​​int​​ ​​age;​


​}​



【执行结果】:

姓名:rollen  年龄:20

本例中,我们将所有的属性都保留了下来,

Serializable接口实现的操作事实上是吧一个对象中的所有属性进行序列化,当然也能够使用我们上使用是Externalizable接口以实现部分属性的序列化。可是这种操作比較麻烦,

当我们使用Serializable接口实现序列化操作的时候,假设一个对象的某一个属性不想被序列化保存下来,那么我们能够使用transientkeyword进行说明:

以下举一个样例:




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16


17


18


19


20


21


22


23


24


25


26


27


28


29


30


31


32


33


34


35


36


37


38


39


40


41


42


43


44


45


46


47


48


49


50


51


52


53


54


55




​package​​ ​​IO;​


 


​import​​ ​​java.io.File;​


​import​​ ​​java.io.FileInputStream;​


​import​​ ​​java.io.FileOutputStream;​


​import​​ ​​java.io.ObjectInputStream;​


​import​​ ​​java.io.ObjectOutputStream;​


​import​​ ​​java.io.Serializable;​


 


​/**​


​* 序列化和反序列化的操作​


​* */​


​public​​ ​​class​​ ​​serDemo{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args)​​​​throws​​ ​​Exception{​


​ser(); ​​​​// 序列化​


​dser(); ​​​​// 反序列话​


​}​


 


​public​​ ​​static​​ ​​void​​ ​​ser()​​​​throws​​ ​​Exception{​


​File file = ​​​​new​​ ​​File(​​​​"d:"​​ ​​+ File.separator +​​​​"hello.txt"​​​​);​


​ObjectOutputStream out = ​​​​new​​ ​​ObjectOutputStream(​​​​new​​ ​​FileOutputStream(​


​file));​


​out.writeObject(​​​​new​​ ​​Person1(​​​​"rollen"​​​​,​​​​20​​​​));​


​out.close();​


​}​


 


​public​​ ​​static​​ ​​void​​ ​​dser()​​​​throws​​ ​​Exception{​


​File file = ​​​​new​​ ​​File(​​​​"d:"​​ ​​+ File.separator +​​​​"hello.txt"​​​​);​


​ObjectInputStream input = ​​​​new​​ ​​ObjectInputStream(​​​​new​​ ​​FileInputStream(​


​file));​


​Object obj = input.readObject();​


​input.close();​


​System.out.println(obj);​


​}​


​}​


 


​class​​ ​​Person1 ​​​​implements​​ ​​Serializable{​


​public​​ ​​Person1(){​


 


​}​


 


​public​​ ​​Person1(String name,​​​​int​​ ​​age){​


​this​​​​.name = name;​


​this​​​​.age = age;​


​}​


 


​@Override​


​public​​ ​​String toString(){​


​return​​ ​​"姓名:"​​ ​​+ name +​​​​"  年龄:"​​ ​​+ age;​


​}​


 


​// 注意这里​


​private​​ ​​transient​​ ​​String name;​


​private​​ ​​int​​ ​​age;​


​}​



【执行结果】:

姓名:null  年龄:20

最后在给一个序列化一组对象的样例吧:




1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16


17


18


19


20


21


22


23


24


25


26


27


28


29


30


31


32


33


34


35


36


37


38


39


40


41


42


43


44


45


46


47


48


49


50


51


52


53


54


55


56


57


58


59


60




​import​​ ​​java.io.File;​


​import​​ ​​java.io.FileInputStream;​


​import​​ ​​java.io.FileOutputStream;​


​import​​ ​​java.io.ObjectInputStream;​


​import​​ ​​java.io.ObjectOutputStream;​


​import​​ ​​java.io.Serializable;​


 


​/**​


​* 序列化一组对象​


​* */​


​public​​ ​​class​​ ​​SerDemo1{​


​public​​ ​​static​​ ​​void​​ ​​main(String[] args)​​​​throws​​ ​​Exception{​


​Student[] stu = { ​​​​new​​ ​​Student(​​​​"hello"​​​​,​​​​20​​​​), ​​​​new​​ ​​Student(​​​​"world"​​​​,​​​​30​​​​),​


​new​​ ​​Student(​​​​"rollen"​​​​,​​​​40​​​​) };​


​ser(stu);​


​Object[] obj = dser();​


​for​​​​(​​​​int​​ ​​i =​​​​0​​​​; i < obj.length; ++i){​


​Student s = (Student) obj[i];​


​System.out.println(s);​


​}​


​}​


 


​// 序列化​


​public​​ ​​static​​ ​​void​​ ​​ser(Object[] obj)​​​​throws​​ ​​Exception{​


​File file = ​​​​new​​ ​​File(​​​​"d:"​​ ​​+ File.separator +​​​​"hello.txt"​​​​);​


​ObjectOutputStream out = ​​​​new​​ ​​ObjectOutputStream(​​​​new​​ ​​FileOutputStream(​


​file));​


​out.writeObject(obj);​


​out.close();​


​}​


 


​// 反序列化​


​public​​ ​​static​​ ​​Object[] dser()​​​​throws​​ ​​Exception{​


​File file = ​​​​new​​ ​​File(​​​​"d:"​​ ​​+ File.separator +​​​​"hello.txt"​​​​);​


​ObjectInputStream input = ​​​​new​​ ​​ObjectInputStream(​​​​new​​ ​​FileInputStream(​


​file));​


​Object[] obj = (Object[]) input.readObject();​


​input.close();​


​return​​ ​​obj;​


​}​


​}​


 


​class​​ ​​Student ​​​​implements​​ ​​Serializable{​


​public​​ ​​Student(){​


 


​}​


 


​public​​ ​​Student(String name,​​​​int​​ ​​age){​


​this​​​​.name = name;​


​this​​​​.age = age;​


​}​


 


​@Override​


​public​​ ​​String toString(){​


​return​​ ​​"姓名:  "​​ ​​+ name +​​​​"  年龄:"​​ ​​+ age;​


​}​


 


​private​​ ​​String name;​


​private​​ ​​int​​ ​​age;​


​}​