java中的IO整理
2015-04-28 08:42
399 查看
【案例1】创建一个新文件
【运行结果】:
程序运行之后,在d盘下会有一个名字为hello.txt的文件。
【案例2】File类的两个常量
【运行结果】:
\
;
此处多说几句:有些同学可能认为,我直接在windows下使用\进行分割不行吗?当然是可以的。但是在linux下就不是\了。所以,要想使得我们的代码跨平台,更加健壮,所以,大家都采用这两个常量吧,其实也多写不了几行。呵呵、
现在我们使用File类中的常量改写上面的代码:
你看,没有多写多少吧,呵呵。所以建议使用File类中的常量。
删除一个文件
创建一个文件夹
【运行结果】:
D盘下多了一个hello文件夹
列出指定目录的全部文件(包括隐藏文件):
【运行结果】:
$RECYCLE.BIN
360
360Downloads
360Rec
360SoftMove
Config.Msi
da
Downloads
DriversBackup
eclipse
javaweb整合开发和项目实战
Lenovo
MSOCache
Program
ProgramFiles
python
RECYGLER.{8F92DA15-A229-A4D5-B5CE-5280C8B89C19}
SystemVolumeInformation
Tomcat6
var
vod_cache_data
新建文件夹
(你的运行结果应该和这个不一样的,呵呵)
但是使用list返回的是String数组,。而且列出的不是完整路径,如果想列出完整路径的话,需要使用listFiles.他返回的是File的数组
列出指定目录的全部文件(包括隐藏文件):
【运行结果】:
D:\$RECYCLE.BIN
D:\360
D:\360Downloads
D:\360Rec
D:\360SoftMove
D:\Config.Msi
D:\da
D:\Downloads
D:\DriversBackup
D:\eclipse
D:\javaweb整合开发和项目实战
D:\Lenovo
D:\MSOCache
D:\Program
D:\ProgramFiles
D:\python
D:\RECYGLER.{8F92DA15-A229-A4D5-B5CE-5280C8B89C19}
D:\SystemVolumeInformation
D:\Tomcat6
D:\var
D:\vod_cache_data
D:\新建文件夹
通过比较可以指定,使用listFiles更加方便、
判断一个指定的路径是否为目录
【运行结果】:YES
搜索指定目录的全部内容
【运行结果】:
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写入文件】
如果你此时打开hello。txt查看的话,会发现那是乱码。
查看hello.txt会看到“你好”
当然也可以一个字节一个字节的写。
结果还是:“你好”
向文件中追加新内容:
【运行结果】:
你好Rollen
【读取文件内容】
【运行结果】
你好Rollen
Rollen_
但是这个例子读取出来会有大量的空格,我们可以利用in.read(b);的返回值来设计程序。如下:
【运行结果】:
读入长度为:18
你好Rollen
Rollen
读者观察上面的例子可以看出,我们预先申请了一个指定大小的空间,但是有时候这个空间可能太小,有时候可能太大,我们需要准确的大小,这样节省空间,那么我们可以这样干:
文件长度为:18
你好Rollen
Rollen
将上面的例子改为一个一个读:
输出的结果和上面的一样。
细心的读者可能会发现,上面的几个例子都是在知道文件的内容多大,然后才展开的,有时候我们不知道文件有多大,这种情况下,我们需要判断是否独到文件的末尾。
【运行结果】
你好Rollen
Rollen_
提醒一下,当独到文件末尾的时候会返回-1.正常情况下是不会返回-1的
现在我们使用字符流
当你打开hello。txt的时候,会看到hello
其实这个例子上之前的例子没什么区别,只是你可以直接输入字符串,而不需要你将字符串转化为字节数组。
当你如果想问文件中追加内容的时候,可以使用将上面的声明out的哪一行换为:
Writerout=newFileWriter(f,true);
这样,当你运行程序的时候,会发现文件内容变为:
hellohello如果想在文件中换行的话,需要使用“\r\n”
比如将str变为Stringstr="\r\nhello";
这样文件追加的str的内容就会换行了。
从文件中读内容:
【运行结果】:
读入的长度为:17
内容为hellohello
hello
当然最好采用循环读取的方式,因为我们有时候不知道文件到底有多大。
运行结果:
内容为hellohello
hello
读者可以试着将上面的字节流和字符流的程序的最后一行关闭文件的代码注释掉,然后运行程序看看。你就会发现使用字节流的话,文件中已经存在内容,但是使用字符流的时候,文件中还是没有内容的,这个时候就要刷新缓冲区。
copyd:\hello.txtd:\rollen.txt
运行之后你会在d盘中看见hello.txt.,并且两个文件的内容是一样的,(这是屁话)
下面我们使用程序来复制文件吧。
基本思路还是从一个文件中读入内容,边读边写入另一个文件,就是这么简单。、
首先编写下面的代码:
然后在命令行下面
javachello.java
javahellod:\hello.txtd:\rollen.txt
现在你就会在d盘看到rollen。txt了,
OutputStreramWriter将输出的字符流转化为字节流
InputStreamReader将输入的字节流转换为字符流
但是不管如何操作,最后都是以字节的形式保存在文件中的。
运行结果:文件中内容为:hello
【运行结果】:hello
前面列举的输出输入都是以文件进行的,现在我们以内容为输出输入目的地,使用内存操作流
ByteArrayInputStream主要将内容写入内容
ByteArrayOutputStream主要将内容从内存输出
【运行结果】:
rollenholt
内容操作流一般使用来生成一些临时信息采用的,这样可以避免删除的麻烦。
PipedOutputStream管道输出流
PipedInputStream管道输入流
验证管道流
【运行结果】:
接受的内容为hello,Rollen
【运行结果】:
true
Rollen
当然也可以格式化输出
【运行结果】:
姓名:Rollen.年龄:20.
使用OutputStream向屏幕上输出内容
【运行结果】:
hello
【运行结果】:
eclipse的控制台输出的是hello。然后当我们查看d盘下面的hello.txt文件的时候,会在里面看到:这些内容在文件中才能看到哦!
【运行结果】:
你会在eclipse的控制台看到红色的输出:“这些在控制台输出”,然后在d盘下面的hello.txt中会看到:这些在文件中才能看到哦!
【运行结果】:
前提是我的d盘下面的hello.txt中的内容是:“这些文件中的内容哦!”,然后运行程序,输出的结果为:读入的内容为:这些文件中的内容哦!
下面给一个实例:
运行结果:
请输入内容
dasdas
你输入的内容是:dasdas
其实Scanner可以接受任何的输入流
下面给一个使用Scanner类从文件中读出内容
【运行结果】:
从文件中读取的内容是:这些文件中的内容哦!
ABC
现在我们在上面例子的基础上,使用DataInputStream读出内容
【运行结果】:
AB
【运行结果】
结果会在hello.txt文件中包含hello1.txt和hello2.txt文件中的内容。
【运行结果】
运行结果之前,我创建了一个hello.txt的文件,原本大小56个字节,但是压缩之后产生hello.zip之后,居然变成了175个字节,有点搞不懂。
不过结果肯定是正确的,我只是提出我的一个疑问而已。
上面的这个例子测试的是压缩单个文件,下面的们来看看如何压缩多个文件。
【运行结果】
先看看要被压缩的文件吧:
接下来看看压缩之后的:
大家自然想到,既然能压缩,自然能解压缩,在谈解压缩之前,我们会用到一个ZipFile类,先给一个这个例子吧。java中的每一个压缩文件都是可以使用ZipFile来进行表示的
【运行结果】:
压缩文件的名称为:d:\hello.zip
现在我们呢是时候来看看如何加压缩文件了,和之前一样,先让我们来解压单个压缩文件(也就是压缩文件中只有一个文件的情况),我们采用前面的例子产生的压缩文件hello.zip
【运行结果】:
解压缩之前:
这个压缩文件还是175字节
解压之后产生:
又回到了56字节,表示郁闷。
现在让我们来解压一个压缩文件中包含多个文件的情况吧
【运行结果】:
被解压的文件:
解压之后再D盘下会出现一个temp文件夹,里面内容:
【运行结果】:
hello(回退,)rollenholt
【运行结果】:
系统默认编码为:GBK
乱码的产生:
【运行结果】:
??
一般情况下产生乱码,都是由于编码不一致的问题。
一个类要想被序列化,就行必须实现java.io.Serializable接口。虽然这个接口中没有任何方法,就如同之前的cloneable接口一样。实现了这个接口之后,就表示这个类具有被序列化的能力。
先让我们实现一个具有序列化能力的类吧:
这个类就具有实现序列化能力,
【运行结果】:
当我们查看产生的hello.txt的时候,看到的是乱码,呵呵。因为是二进制文件。
虽然我们不能直接查看里面的内容,但是我们可以使用ObjectInputStream类查看:
【运行结果】
姓名:rollen年龄:20
到底序列化什么内容呢?
其实只有属性会被序列化。
当一个类要使用Externalizable这个接口的时候,这个类中必须要有一个无参的构造函数,如果没有的话,在构造的时候会产生异常,这是因为在反序列话的时候会默认调用无参的构造函数。
现在我们来演示一下序列化和反序列话:
【运行结果】:
姓名:rollen年龄:20
本例中,我们将全部的属性都保留了下来,
Serializable接口实现的操作其实是吧一个对象中的全部属性进行序列化,当然也可以使用我们上使用是Externalizable接口以实现部分属性的序列化,但是这样的操作比较麻烦,
当我们使用Serializable接口实现序列化操作的时候,如果一个对象的某一个属性不想被序列化保存下来,那么我们可以使用transient关键字进行说明:
下面举一个例子:
【运行结果】:
姓名:null年龄:20
最后在给一个序列化一组对象的例子吧:
【运行结果】:
姓名:hello年龄:20
姓名:world年龄:30
姓名:rollen年龄:40
1 2 3 4 5 6 7 8 9 10 11 | import java.io.*; class hello{ public static void main(String[]args){ Filef= new File( "D:\\hello.txt" ); try { f.createNewFile(); } catch (Exceptione){ 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){ StringfileName= "D:" +File.separator+ "hello.txt" ; Filef= new File(fileName); try { f.createNewFile(); } catch (Exceptione){ e.printStackTrace(); } } } |
删除一个文件
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){ StringfileName= "D:" +File.separator+ "hello.txt" ; Filef= 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){ StringfileName= "D:" +File.separator+ "hello" ; Filef= 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){ StringfileName= "D:" +File.separator; Filef= 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
javaweb整合开发和项目实战
Lenovo
MSOCache
Program
ProgramFiles
python
RECYGLER.{8F92DA15-A229-A4D5-B5CE-5280C8B89C19}
SystemVolumeInformation
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){ StringfileName= "D:" +File.separator; Filef= 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:\javaweb整合开发和项目实战
D:\Lenovo
D:\MSOCache
D:\Program
D:\ProgramFiles
D:\python
D:\RECYGLER.{8F92DA15-A229-A4D5-B5CE-5280C8B89C19}
D:\SystemVolumeInformation
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){ StringfileName= "D:" +File.separator; Filef= new File(fileName); if (f.isDirectory()){ System.out.println( "YES" ); } else { System.out.println( "NO" ); } } } |
搜索指定目录的全部内容
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){ StringfileName= "D:" +File.separator; Filef= new File(fileName); print(f); } public static void print(Filef){ if (f!= null ){ if (f.isDirectory()){ File[]fileArray=f.listFiles(); if (fileArray!= null ){ for ( int i= 0 ;i<fileArray.length; //递归调用 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 { StringfileName= "D:" +File.separator+ "hello.txt" ; Filef= new File(fileName); RandomAccessFiledemo= 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(); } } |
字节流
【向文件中写入字符串】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 { StringfileName= "D:" +File.separator+ "hello.txt" ; Filef= new File(fileName); OutputStreamout= new FileOutputStream(f); Stringstr= "你好" ; byte []b=str.getBytes(); out.write(b); out.close(); } } |
当然也可以一个字节一个字节的写。
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 { StringfileName= "D:" +File.separator+ "hello.txt" ; Filef= new File(fileName); OutputStreamout= new FileOutputStream(f); Stringstr= "你好" ; 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 { StringfileName= "D:" +File.separator+ "hello.txt" ; Filef= new File(fileName); OutputStreamout= new FileOutputStream(f, true ); Stringstr= "Rollen" ; //Stringstr="\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 { StringfileName= "D:" +File.separator+ "hello.txt" ; Filef= new File(fileName); InputStreamin= 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 { StringfileName= "D:" +File.separator+ "hello.txt" ; Filef= new File(fileName); InputStreamin= 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 { StringfileName= "D:" +File.separator+ "hello.txt" ; Filef= new File(fileName); InputStreamin= 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)); } } |
你好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 { StringfileName= "D:" +File.separator+ "hello.txt" ; Filef= new File(fileName); InputStreamin= 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 { StringfileName= "D:" +File.separator+ "hello.txt" ; Filef= new File(fileName); InputStreamin= 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 { StringfileName= "D:" +File.separator+ "hello.txt" ; Filef= new File(fileName); Writerout= new FileWriter(f); Stringstr= "hello" ; out.write(str); out.close(); } } |
其实这个例子上之前的例子没什么区别,只是你可以直接输入字符串,而不需要你将字符串转化为字节数组。
当你如果想问文件中追加内容的时候,可以使用将上面的声明out的哪一行换为:
Writerout=newFileWriter(f,true);
这样,当你运行程序的时候,会发现文件内容变为:
hellohello如果想在文件中换行的话,需要使用“\r\n”
比如将str变为Stringstr="\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 { StringfileName= "D:" +File.separator+ "hello.txt" ; Filef= new File(fileName); char []ch= new char [ 100 ]; Readerread= 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 { StringfileName= "D:" +File.separator+ "hello.txt" ; Filef= new File(fileName); char []ch= new char [ 100 ]; Readerread= 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文件中,那么我们就可以使用下面的命令:copyd:\hello.txtd:\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 ); } Filefile1= new File(args[ 0 ]); Filefile2= new File(args[ 1 ]); if (!file1.exists()){ System.out.println( "被复制的文件不存在" ); System.exit( 1 ); } InputStreaminput= new FileInputStream(file1); OutputStreamoutput= new FileOutputStream(file2); if ((input!= null )&&(output!= null )){ int temp= 0 ; while ((temp=input.read())!=(- 1 )){ output.write(temp); } } input.close(); output.close(); } } |
javachello.java
javahellod:\hello.txtd:\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 { StringfileName= "d:" +File.separator+ "hello.txt" ; Filefile= new File(fileName); Writerout= new OutputStreamWriter( new FileOutputStream(file)); out.write( "hello" ); out.close(); } } |
将字节输入流变为字符输入流
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 { StringfileName= "d:" +File.separator+ "hello.txt" ; Filefile= new File(fileName); Readerread= 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(); } } |
前面列举的输出输入都是以文件进行的,现在我们以内容为输出输入目的地,使用内存操作流
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 { Stringstr= "ROLLENHOLT" ; ByteArrayInputStreaminput= new ByteArrayInputStream(str.getBytes()); ByteArrayOutputStreamoutput= new ByteArrayOutputStream(); int temp= 0 ; while ((temp=input.read())!=- 1 ){ char ch=( char )temp; output.write(Character.toLowerCase(ch)); } StringoutStr=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 PipedOutputStreamout= null ; public Send(){ out= new PipedOutputStream(); } public PipedOutputStreamgetOut(){ return this .out; } public void run(){ Stringmessage= "hello,Rollen" ; try { out.write(message.getBytes()); } catch (Exceptione){ e.printStackTrace(); } try { out.close(); } catch (Exceptione){ e.printStackTrace(); } } } /** *接受消息类 **/ class Recive implements Runnable{ private PipedInputStreaminput= null ; public Recive(){ this .input= new PipedInputStream(); } public PipedInputStreamgetInput(){ return this .input; } public void run(){ byte []b= new byte [ 1000 ]; int len= 0 ; try { len= this .input.read(b); } catch (Exceptione){ e.printStackTrace(); } try { input.close(); } catch (Exceptione){ e.printStackTrace(); } System.out.println( "接受的内容为" +( new String(b, 0 ,len))); } } /** *测试类 **/ class hello{ public static void main(String[]args) throws IOException { Sendsend= new Send(); Reciverecive= new Recive(); try { //管道连接 send.getOut().connect(recive.getInput()); } catch (Exceptione){ 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 { PrintStreamprint= 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 { PrintStreamprint= new PrintStream( new FileOutputStream( new File( "d:" +File.separator+ "hello.txt" ))); Stringname= "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 { OutputStreamout=System.out; try { out.write( "hello" .getBytes()); } catch (Exceptione){ e.printStackTrace(); } try { out.close(); } catch (Exceptione){ 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" ); Filefile= new File( "d:" +File.separator+ "hello.txt" ); try { System.setOut( new PrintStream( new FileOutputStream(file))); } catch (FileNotFoundExceptione){ 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){ Filefile= new File( "d:" +File.separator+ "hello.txt" ); System.err.println( "这些在控制台输出" ); try { System.setErr( new PrintStream( new FileOutputStream(file))); } catch (FileNotFoundExceptione){ 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){ Filefile= new File( "d:" +File.separator+ "hello.txt" ); if (!file.exists()){ return ; } else { try { System.setIn( new FileInputStream(file)); } catch (FileNotFoundExceptione){ e.printStackTrace(); } byte []bytes= new byte [ 1024 ]; int len= 0 ; try { len=System.in.read(bytes); } catch (IOExceptione){ e.printStackTrace(); } System.out.println( "读入的内容为:" + new String(bytes, 0 , len)); } } } |
前提是我的d盘下面的hello.txt中的内容是:“这些文件中的内容哦!”,然后运行程序,输出的结果为:读入的内容为:这些文件中的内容哦!
BufferedReader的小例子
注意:BufferedReader只能接受字符流的缓冲区,因为每一个中文需要占据两个字节,所以需要将System.in这个字节输入流变为字符输入流,采用:BufferedReaderbuf= 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){ BufferedReaderbuf= new BufferedReader( new InputStreamReader(System.in)); Stringstr= null ; System.out.println( "请输入内容" ); try { str=buf.readLine(); } catch (IOExceptione){ 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){ Scannersca= new Scanner(System.in); //读一个整数 int temp=sca.nextInt(); System.out.println(temp); //读取浮点数 float flo=sca.nextFloat(); System.out.println(flo); //读取字符 //...等等的,都是一些太基础的,就不师范了。 } } |
下面给一个使用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){ Filefile= new File( "d:" +File.separator+ "hello.txt" ); Scannersca= null ; try { sca= new Scanner(file); } catch (FileNotFoundExceptione){ e.printStackTrace(); } Stringstr=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{ Filefile= new File( "d:" +File.separator+ "hello.txt" ); char []ch={ 'A' , 'B' , 'C' }; DataOutputStreamout= null ; out= new DataOutputStream( new FileOutputStream(file)); for ( char temp:ch){ out.writeChar(temp); } out.close(); } } |
现在我们在上面例子的基础上,使用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{ Filefile= new File( "d:" +File.separator+ "hello.txt" ); DataInputStreaminput= 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{ Filefile1= new File( "d:" +File.separator+ "hello1.txt" ); Filefile2= new File( "d:" +File.separator+ "hello2.txt" ); Filefile3= new File( "d:" +File.separator+ "hello.txt" ); InputStreaminput1= new FileInputStream(file1); InputStreaminput2= new FileInputStream(file2); OutputStreamoutput= new FileOutputStream(file3); //合并流 SequenceInputStreamsis= 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{ Filefile= new File( "d:" +File.separator+ "hello.txt" ); FilezipFile= new File( "d:" +File.separator+ "hello.zip" ); InputStreaminput= new FileInputStream(file); ZipOutputStreamzipOut= 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{ //要被压缩的文件夹 Filefile= new File( "d:" +File.separator+ "temp" ); FilezipFile= new File( "d:" +File.separator+ "zipFile.zip" ); InputStreaminput= null ; ZipOutputStreamzipOut= 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{ Filefile= new File( "d:" +File.separator+ "hello.zip" ); ZipFilezipFile= 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{ Filefile= new File( "d:" +File.separator+ "hello.zip" ); FileoutFile= new File( "d:" +File.separator+ "unZipFile.txt" ); ZipFilezipFile= new ZipFile(file); ZipEntryentry=zipFile.getEntry( "hello.txt" ); InputStreaminput=zipFile.getInputStream(entry); OutputStreamoutput= 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{ Filefile= new File( "d:" +File.separator+ "zipFile.zip" ); FileoutFile= null ; ZipFilezipFile= new ZipFile(file); ZipInputStreamzipInput= new ZipInputStream( new FileInputStream(file)); ZipEntryentry= null ; InputStreaminput= null ; OutputStreamoutput= 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{ Stringstr= "hello,rollenholt" ; PushbackInputStreampush= null ; ByteArrayInputStreambat= 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{ Filefile= new File( "d:" +File.separator+ "hello.txt" ); OutputStreamout= 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(Stringname, int age){ this .name=name; this .age=age; } @Override public StringtoString(){ return "姓名:" +name+ "年龄:" +age; } private Stringname; 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(Stringname, int age){ this .name=name; this .age=age; } @Override public StringtoString(){ return "姓名:" +name+ "年龄:" +age; } private Stringname; private int age; } /** *示范ObjectOutputStream **/ public class ObjectOutputStreamDemo{ public static void main(String[]args) throws IOException{ Filefile= new File( "d:" +File.separator+ "hello.txt" ); ObjectOutputStreamoos= 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{ Filefile= new File( "d:" +File.separator+ "hello.txt" ); ObjectInputStreaminput= new ObjectInputStream( new FileInputStream( file)); Objectobj=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{ Filefile= new File( "d:" +File.separator+ "hello.txt" ); ObjectOutputStreamout= new ObjectOutputStream( new FileOutputStream( file)); out.writeObject( new Person( "rollen" , 20 )); out.close(); } public static void dser() throws Exception{ Filefile= new File( "d:" +File.separator+ "hello.txt" ); ObjectInputStreaminput= new ObjectInputStream( new FileInputStream( file)); Objectobj=input.readObject(); input.close(); System.out.println(obj); } } class Person implements Externalizable{ public Person(){ } public Person(Stringname, int age){ this .name=name; this .age=age; } @Override public StringtoString(){ return "姓名:" +name+ "年龄:" +age; } //复写这个方法,根据需要可以保存的属性或者具体内容,在序列化的时候使用 @Override public void writeExternal(ObjectOutputout) throws IOException{ out.writeObject( this .name); out.writeInt(age); } //复写这个方法,根据需要读取内容反序列话的时候需要 @Override public void readExternal(ObjectInputin) throws IOException, ClassNotFoundException{ this .name=(String)in.readObject(); this .age=in.readInt(); } private Stringname; private int age; } |
姓名:rollen年龄:20
本例中,我们将全部的属性都保留了下来,
Serializable接口实现的操作其实是吧一个对象中的全部属性进行序列化,当然也可以使用我们上使用是Externalizable接口以实现部分属性的序列化,但是这样的操作比较麻烦,
当我们使用Serializable接口实现序列化操作的时候,如果一个对象的某一个属性不想被序列化保存下来,那么我们可以使用transient关键字进行说明:
下面举一个例子:
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{ Filefile= new File( "d:" +File.separator+ "hello.txt" ); ObjectOutputStreamout= new ObjectOutputStream( new FileOutputStream( file)); out.writeObject( new Person1( "rollen" , 20 )); out.close(); } public static void dser() throws Exception{ Filefile= new File( "d:" +File.separator+ "hello.txt" ); ObjectInputStreaminput= new ObjectInputStream( new FileInputStream( file)); Objectobj=input.readObject(); input.close(); System.out.println(obj); } } class Person1 implements Serializable{ public Person1(){ } public Person1(Stringname, int age){ this .name=name; this .age=age; } @Override public StringtoString(){ return "姓名:" +name+ "年龄:" +age; } //注意这里 private transient Stringname; 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){ Students=(Student)obj[i]; System.out.println(s); } } //序列化 public static void ser(Object[]obj) throws Exception{ Filefile= new File( "d:" +File.separator+ "hello.txt" ); ObjectOutputStreamout= new ObjectOutputStream( new FileOutputStream( file)); out.writeObject(obj); out.close(); } //反序列化 public static Object[]dser() throws Exception{ Filefile= new File( "d:" +File.separator+ "hello.txt" ); ObjectInputStreaminput= new ObjectInputStream( new FileInputStream( file)); Object[]obj=(Object[])input.readObject(); input.close(); return obj; } } class Student implements Serializable{ public Student(){ } public Student(Stringname, int age){ this .name=name; this .age=age; } @Override public StringtoString(){ return "姓名:" +name+ "年龄:" +age; } private Stringname; private int age; } |
姓名:hello年龄:20
姓名:world年龄:30
姓名:rollen年龄:40
相关文章推荐
- Java 持久化之 -- IO 全面整理(看了绝不后悔)
- java中的IO整理
- Java中的IO整理
- Java中的IO整理完整版(一)
- Java IO整理
- Java IO 框架整理
- JAVAIO整理
- Java中的IO整理完整版
- Android java.io.IOException异常情况整理
- 关于Java IO InputStream 的一点整理!
- java中的IO整理
- Java整理(六)IO
- java中的IO整理
- java中的IO整理(转)
- java中的IO整理
- Java中的IO整理
- Java基础整理之JavaIO
- java中的IO整理
- java中的IO整理
- Java中的IO整理完整版(一)