java中的io流

来源:互联网 发布:java主要用途 编辑:程序博客网 时间:2024/05/01 21:32

http://my.oschina.net/caiyuan/blog/32093

写在前面:本文章基本覆盖了java IO的全部内容,java新IO没有涉及,因为我想和这个分开,以突出那个的重要性,新IO哪一篇文章还没有开始写,估计很快就能和大家见面。照旧,文章 依旧以例子为主,因为讲解内容的java书很多了,我觉的学以致用才是真。代码是写出来的,不是看出来的。

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

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

01import java.io.*;
02class hello{
03public static void main(String[] args) {
04File f=new File("D:\\hello.txt");
05try{
06f.createNewFile();
07}catch (Exception e) {
08e.printStackTrace();
09}
10}
11}

【运行结果】:

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

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

1import java.io.*;
2class hello{
3public static void main(String[] args) {
4System.out.println(File.separator);
5System.out.println(File.pathSeparator);
6}
7}

【运行结果】:

\

;

此处多说几句:有些同学可能认为,我直接在windows下使用\进行分割不行吗?当然是可以的。但是在linux下就不是\了。所以,要想使得我们的代码跨平台,更加健壮,所以,大家都采用这两个常量吧,其实也多写不了几行。呵呵、

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

01import java.io.*;
02class hello{
03public static void main(String[] args) {
04String fileName="D:"+File.separator+"hello.txt";
05File f=new File(fileName);
06try{
07f.createNewFile();
08}catch (Exception e) {
09e.printStackTrace();
10}
11}
12}

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

删除一个文件

01/**
02* 删除一个文件
03* */
04import java.io.*;
05class hello{
06public static void main(String[] args) {
07String fileName="D:"+File.separator+"hello.txt";
08File f=new File(fileName);
09if(f.exists()){
10f.delete();
11}else{
12System.out.println("文件不存在");
13}
14
15}
16}

创建一个文件夹

01/**
02* 创建一个文件夹
03* */
04import java.io.*;
05class hello{
06public static void main(String[] args) {
07String fileName="D:"+File.separator+"hello";
08File f=new File(fileName);
09f.mkdir();
10}
11}

【运行结果】:

D盘下多了一个hello文件夹

列出指定目录的全部文件(包括隐藏文件):

01/**
02* 使用list列出指定目录的全部文件
03* */
04import java.io.*;
05class hello{
06public static void main(String[] args) {
07String fileName="D:"+File.separator;
08File f=new File(fileName);
09String[] str=f.list();
10for (int i = ; i < str.length; i++) {
11System.out.println(str[i]);
12}
13}
14}

【运行结果】:

$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的数组

列出指定目录的全部文件(包括隐藏文件):

01/**
02* 使用listFiles列出指定目录的全部文件
03* listFiles输出的是完整路径
04* */
05import java.io.*;
06class hello{
07public static void main(String[] args) {
08String fileName="D:"+File.separator;
09File f=new File(fileName);
10File[] str=f.listFiles();
11for (int i = ; i < str.length; i++) {
12System.out.println(str[i]);
13}
14}
15}

【运行结果】:

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更加方便、

判断一个指定的路径是否为目录

01/**
02* 使用isDirectory判断一个指定的路径是否为目录
03* */
04import java.io.*;
05class hello{
06public static void main(String[] args) {
07String fileName="D:"+File.separator;
08File f=new File(fileName);
09if(f.isDirectory()){
10System.out.println("YES");
11}else{
12System.out.println("NO");
13}
14}
15}

【运行结果】:YES

搜索指定目录的全部内容

01/**
02* 列出指定目录的全部内容
03* */
04import java.io.*;
05class hello{
06public static void main(String[] args) {
07String fileName="D:"+File.separator;
08File f=new File(fileName);
09print(f);
10}
11public static void print(File f){
12if(f!=null){
13if(f.isDirectory()){
14File[] fileArray=f.listFiles();
15if(fileArray!=null){
16for (int i = ; i < fileArray.length; i++) {
17//递归调用
18print(fileArray[i]);
19}
20}
21}
22else{
23System.out.println(f);
24}
25}
26}
27}

【运行结果】:

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写入文件

01/**
02* 使用RandomAccessFile写入文件
03* */
04import java.io.*;
05class hello{
06public static void main(String[] args) throws IOException {
07String fileName="D:"+File.separator+"hello.txt";
08File f=new File(fileName);
09RandomAccessFile demo=new RandomAccessFile(f,"rw");
10demo.writeBytes("asdsad");
11demo.writeInt(12);
12demo.writeBoolean(true);
13demo.writeChar('A');
14demo.writeFloat(1.21f);
15demo.writeDouble(12.123);
16demo.close();
17}
18}

如果你此时打开hellotxt查看的话,会发现那是乱码。

字节流

向文件中写入字符串

01/**
02* 字节流
03* 向文件中写入字符串
04* */
05import java.io.*;
06class hello{
07public static void main(String[] args) throws IOException {
08String fileName="D:"+File.separator+"hello.txt";
09File f=new File(fileName);
10OutputStream out =new FileOutputStream(f);
11String str="你好";
12byte[] b=str.getBytes();
13out.write(b);
14out.close();
15}
16}

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

当然也可以一个字节一个字节的写。

01/**
02* 字节流
03* 向文件中一个字节一个字节的写入字符串
04* */
05import java.io.*;
06class hello{
07public static void main(String[] args) throws IOException {
08String fileName="D:"+File.separator+"hello.txt";
09File f=new File(fileName);
10OutputStream out =new FileOutputStream(f);
11String str="你好";
12byte[] b=str.getBytes();
13for (int i = ; i < b.length; i++) {
14out.write(b[i]);
15}
16out.close();
17}
18}

结果还是:“你好”

向文件中追加新内容:

01/**
02* 字节流
03* 向文件中追加新内容:
04* */
05import java.io.*;
06class hello{
07public static void main(String[] args) throws IOException {
08String fileName="D:"+File.separator+"hello.txt";
09File f=new File(fileName);
10OutputStream out =new FileOutputStream(f,true);
11String str="Rollen";
12//String str="\r\nRollen"; 可以换行
13byte[] b=str.getBytes();
14for (int i = ; i < b.length; i++) {
15out.write(b[i]);
16}
17out.close();
18}
19}

【运行结果】:

你好Rollen

【读取文件内容】

01/**
02* 字节流
03* 读文件内容
04* */
05import java.io.*;
06class hello{
07public static void main(String[] args) throws IOException {
08String fileName="D:"+File.separator+"hello.txt";
09File f=new File(fileName);
10InputStream in=new FileInputStream(f);
11byte[] b=new byte[1024];
12in.read(b);
13in.close();
14System.out.println(new String(b));
15}
16}

【运行结果】

你好Rollen

Rollen_

但是这个例子读取出来会有大量的空格,我们可以利用in.read(b);的返回值来设计程序。如下:

01/**
02* 字节流
03* 读文件内容
04* */
05import java.io.*;
06class hello{
07public static void main(String[] args) throws IOException {
08String fileName="D:"+File.separator+"hello.txt";
09File f=new File(fileName);
10InputStream in=new FileInputStream(f);
11byte[] b=new byte[1024];
12int len=in.read(b);
13in.close();
14System.out.println("读入长度为:"+len);
15System.out.println(new String(b,,len));
16}
17}

【运行结果】:

读入长度为:18

你好Rollen

Rollen

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

01/**
02* 字节流
03* 读文件内容,节省空间
04* */
05import java.io.*;
06class hello{
07public static void main(String[] args) throws IOException {
08String fileName="D:"+File.separator+"hello.txt";
09File f=new File(fileName);
10InputStream in=new FileInputStream(f);
11byte[] b=new byte[(int)f.length()];
12in.read(b);
13System.out.println("文件长度为:"+f.length());
14in.close();
15System.out.println(new String(b));
16}
17}

文件长度为:18

你好Rollen

Rollen

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

01/**
02* 字节流
03* 读文件内容,节省空间
04* */
05import java.io.*;
06class hello{
07public static void main(String[] args) throws IOException {
08String fileName="D:"+File.separator+"hello.txt";
09File f=new File(fileName);
10InputStream in=new FileInputStream(f);
11byte[] b=new byte[(int)f.length()];
12for (int i = ; i < b.length; i++) {
13b[i]=(byte)in.read();
14}
15in.close();
16System.out.println(new String(b));
17}
18}

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

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

01/**
02* 字节流
03*读文件
04* */
05import java.io.*;
06class hello{
07public static void main(String[] args) throws IOException {
08String fileName="D:"+File.separator+"hello.txt";
09File f=new File(fileName);
10InputStream in=new FileInputStream(f);
11byte[] b=new byte[1024];
12int count =;
13int temp=;
14while((temp=in.read())!=(-1)){
15b[count++]=(byte)temp;
16}
17in.close();
18System.out.println(new String(b));
19}
20}

【运行结果】

你好Rollen

Rollen_

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

字符流

【向文件中写入数据】

现在我们使用字符流

01/**
02* 字符流
03* 写入数据
04* */
05import java.io.*;
06class hello{
07public static void main(String[] args) throws IOException {
08String fileName="D:"+File.separator+"hello.txt";
09File f=new File(fileName);
10Writer out =new FileWriter(f);
11String str="hello";
12out.write(str);
13out.close();
14}
15}

当你打开hellotxt的时候,会看到hello

其实这个例子上之前的例子没什么区别,只是你可以直接输入字符串,而不需要你将字符串转化为字节数组。

当你如果想问文件中追加内容的时候,可以使用将上面的声明out的哪一行换为:

Writer out =new FileWriter(f,true);

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

hellohello如果想在文件中换行的话,需要使用“\r\n

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

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

从文件中读内容:

01/**
02* 字符流
03* 从文件中读出内容
04* */
05import java.io.*;
06class hello{
07public static void main(String[] args) throws IOException {
08String fileName="D:"+File.separator+"hello.txt";
09File f=new File(fileName);
10char[] ch=new char[100];
11Reader read=new FileReader(f);
12int count=read.read(ch);
13read.close();
14System.out.println("读入的长度为:"+count);
15System.out.println("内容为"+newString(ch,,count));
16}
17}

【运行结果】:

读入的长度为:17

内容为hellohello

hello

当然最好采用循环读取的方式,因为我们有时候不知道文件到底有多大。

01/**
02* 字符流
03* 从文件中读出内容
04* */
05import java.io.*;
06class hello{
07public static void main(String[] args) throws IOException {
08String fileName="D:"+File.separator+"hello.txt";
09File f=new File(fileName);
10char[] ch=new char[100];
11Reader read=new FileReader(f);
12int temp=;
13int count=;
14while((temp=read.read())!=(-1)){
15ch[count++]=(char)temp;
16}
17read.close();
18System.out.println("内容为"+newString(ch,,count));
19}
20}

运行结果:

内容为hellohello

hello

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

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

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

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

答案是字节流。首先因为硬盘上的所有文件都是以字节的形式进行传输或者保存的,包括图片等内容。但是字符只是在内存中才会形成的,所以在开发中,字节流使用广泛。

文件的复制

其实DOS下就有一个文件复制功能,比如我们想把d盘下面的hello.txt文件复制到d盘下面的rollen.txt文件中,那么我们就可以使用下面的命令:

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

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

下面我们使用程序来复制文件吧。

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

首先编写下面的代码:

01/**
02* 文件的复制
03* */
04import java.io.*;
05class hello{
06public static void main(String[] args) throws IOException {
07if(args.length!=2){
08System.out.println("命令行参数输入有误,请检查");
09System.exit(1);
10}
11File file1=new File(args[]);
12File file2=new File(args[1]);
13
14if(!file1.exists()){
15System.out.println("被复制的文件不存在");
16System.exit(1);
17}
18InputStream input=new FileInputStream(file1);
19OutputStream output=new FileOutputStream(file2);
20if((input!=null)&&(output!=null)){
21int temp=;
22while((temp=input.read())!=(-1)){
23output.write(temp);
24}
25}
26input.close();
27output.close();
28}
29}

然后在命令行下面

javac hello.java

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

现在你就会在d盘看到rollentxt了,

OutputStreramWriter InputStreamReader

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

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

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

但是不管如何操作,最后都是以字节的形式保存在文件中的。

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

01/**
02* 将字节输出流转化为字符输出流
03* */
04import java.io.*;
05class hello{
06public static void main(String[] args) throws IOException {
07String fileName= "d:"+File.separator+"hello.txt";
08File file=new File(fileName);
09Writer out=new OutputStreamWriter(newFileOutputStream(file));
10out.write("hello");
11out.close();
12}
13}

运行结果:文件中内容为:hello

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

01/**
02* 将字节输入流变为字符输入流
03* */
04import java.io.*;
05class hello{
06public static void main(String[] args) throws IOException {
07String fileName= "d:"+File.separator+"hello.txt";
08File file=new File(fileName);
09Reader read=new InputStreamReader(newFileInputStream(file));
10char[] b=new char[100];
11int len=read.read(b);
12System.out.println(new String(b,,len));
13read.close();
14}
15}

【运行结果】:hello

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

ByteArrayInputStream 主要将内容写入内容

ByteArrayOutputStream 主要将内容从内存输出

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

01/**
02* 使用内存操作流将一个大写字母转化为小写字母
03* */
04import java.io.*;
05class hello{
06public static void main(String[] args) throws IOException {
07String str="ROLLENHOLT";
08ByteArrayInputStream input=new ByteArrayInputStream(str.getBytes());
09ByteArrayOutputStream output=new ByteArrayOutputStream();
10int temp=;
11while((temp=input.read())!=-1){
12char ch=(char)temp;
13output.write(Character.toLowerCase(ch));
14}
15String outStr=output.toString();
16input.close();
17output.close();
18System.out.println(outStr);
19}
20}

【运行结果】:

rollenholt

内容操作流一般使用来生成一些临时信息采用的,这样可以避免删除的麻烦。

管道流

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

PipedOutputStream 管道输出流

PipedInputStream 管道输入流

验证管道流
01/**
02* 验证管道流
03* */
04import java.io.*;
05 
06/**
07* 消息发送类
08* */
09class Send implements Runnable{
10private PipedOutputStream out=null;
11public Send() {
12out=new PipedOutputStream();
13}
14public PipedOutputStream getOut(){
15return this.out;
16}
17public void run(){
18String message="hello , Rollen";
19try{
20out.write(message.getBytes());
21}catch (Exception e) {
22e.printStackTrace();
23}try{
24out.close();
25}catch (Exception e) {
26e.printStackTrace();
27}
28}
29}
30 
31/**
32* 接受消息类
33* */
34class Recive implements Runnable{
35private PipedInputStream input=null;
36public Recive(){
37this.input=new PipedInputStream();
38}
39public PipedInputStream getInput(){
40return this.input;
41}
42public void run(){
43byte[] b=new byte[1000];
44int len=;
45try{
46len=this.input.read(b);
47}catch (Exception e) {
48e.printStackTrace();
49}try{
50input.close();
51}catch (Exception e) {
52e.printStackTrace();
53}
54System.out.println("接受的内容为 "+(newString(b,,len)));
55}
56}
57/**
58* 测试类
59* */
60class hello{
61public static void main(String[] args) throws IOException {
62Send send=new Send();
63Recive recive=new Recive();
64try{
65//管道连接
66send.getOut().connect(recive.getInput());
67}catch (Exception e) {
68e.printStackTrace();
69}
70new Thread(send).start();
71new Thread(recive).start();
72}
73}

【运行结果】:

接受的内容为 hello , Rollen

打印流

01/**
02* 使用PrintStream进行输出
03* */
04import java.io.*;
05 
06class hello {
07public static void main(String[] args) throws IOException {
08PrintStream print = new PrintStream(newFileOutputStream(newFile("d:"
09+ File.separator + "hello.txt")));
10print.println(true);
11print.println("Rollen");
12print.close();
13}
14}

【运行结果】:

true

Rollen

当然也可以格式化输出

01/**
02* 使用PrintStream进行输出
03* 并进行格式化
04* */
05import java.io.*;
06class hello {
07public static void main(String[] args) throws IOException {
08PrintStream print = new PrintStream(newFileOutputStream(newFile("d:"
09+ File.separator + "hello.txt")));
10String name="Rollen";
11int age=20;
12print.printf("姓名:%s. 年龄:%d.",name,age);
13print.close();
14}
15}

【运行结果】:

姓名:Rollen. 年龄:20.

使用OutputStream向屏幕上输出内容

01/**
02* 使用OutputStream向屏幕上输出内容
03* */
04import java.io.*;
05class hello {
06public static void main(String[] args) throws IOException {
07OutputStream out=System.out;
08try{
09out.write("hello".getBytes());
10}catch (Exception e) {
11e.printStackTrace();
12}
13try{
14out.close();
15}catch (Exception e) {
16e.printStackTrace();
17}
18}
19}

【运行结果】:

hello

输入输出重定向

01import java.io.File;
02import java.io.FileNotFoundException;
03import java.io.FileOutputStream;
04import java.io.PrintStream;
05 
06/**
07* 为System.out.println()重定向输出
08* */
09public class systemDemo{
10public static void main(String[] args){
11// 此刻直接输出到屏幕
12System.out.println("hello");
13File file = new File("d:"+ File.separator +"hello.txt");
14try{
15System.setOut(new PrintStream(newFileOutputStream(file)));
16}catch(FileNotFoundException e){
17e.printStackTrace();
18}
19System.out.println("这些内容在文件中才能看到哦!");
20}
21}

【运行结果】:

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

01import java.io.File;
02import java.io.FileNotFoundException;
03import java.io.FileOutputStream;
04import java.io.PrintStream;
05 
06/**
07* System.err重定向 这个例子也提示我们可以使用这种方法保存错误信息
08* */
09public class systemErr{
10public static void main(String[] args){
11File file = new File("d:"+ File.separator +"hello.txt");
12System.err.println("这些在控制台输出");
13try{
14System.setErr(new PrintStream(newFileOutputStream(file)));
15}catch(FileNotFoundException e){
16e.printStackTrace();
17}
18System.err.println("这些在文件中才能看到哦!");
19}
20}

【运行结果】:

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

01import java.io.File;
02import java.io.FileInputStream;
03import java.io.FileNotFoundException;
04import java.io.IOException;
05 
06/**
07* System.in重定向
08* */
09public class systemIn{
10public static void main(String[] args){
11File file = new File("d:"+ File.separator +"hello.txt");
12if(!file.exists()){
13return;
14}else{
15try{
16System.setIn(new FileInputStream(file));
17}catch(FileNotFoundException e){
18e.printStackTrace();
19}
20byte[] bytes = new byte[1024];
21int len = ;
22try{
23len = System.in.read(bytes);
24}catch(IOException e){
25e.printStackTrace();
26}
27System.out.println("读入的内容为:" + new String(bytes, , len));
28}
29}
30}

【运行结果】:

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

BufferedReader的小例子

注意: BufferedReader只能接受字符流的缓冲区,因为每一个中文需要占据两个字节,所以需要将System.in这个字节输入流变为字符输入流,采用:

BufferedReader buf = new BufferedReader(
new InputStreamReader(System.in));

下面给一个实例:

01import java.io.BufferedReader;
02import java.io.IOException;
03import java.io.InputStreamReader;
04 
05/**
06* 使用缓冲区从键盘上读入内容
07* */
08public class BufferedReaderDemo{
09public static void main(String[] args){
10BufferedReader buf = new BufferedReader(
11new InputStreamReader(System.in));
12String str = null;
13System.out.println("请输入内容");
14try{
15str = buf.readLine();
16}catch(IOException e){
17e.printStackTrace();
18}
19System.out.println("你输入的内容是:" + str);
20}
21}

运行结果:

请输入内容

dasdas

你输入的内容是:dasdas

Scanner

其实我们比较常用的是采用Scanner类来进行数据输入,下面来给一个Scanner的例子吧

01import java.util.Scanner;
02 
03/**
04* Scanner的小例子,从键盘读数据
05* */
06public class ScannerDemo{
07public static void main(String[] args){
08Scanner sca = new Scanner(System.in);
09// 读一个整数
10int temp = sca.nextInt();
11System.out.println(temp);
12//读取浮点数
13float flo=sca.nextFloat();
14System.out.println(flo);
15//读取字符
16//...等等的,都是一些太基础的,就不师范了。
17}
18}

其实Scanner可以接受任何的输入流

下面给一个使用Scanner类从文件中读出内容

01import java.io.File;
02import java.io.FileNotFoundException;
03import java.util.Scanner;
04 
05/**
06* Scanner的小例子,从文件中读内容
07* */
08public class ScannerDemo{
09public static void main(String[] args){
10 
11File file = new File("d:"+ File.separator +"hello.txt");
12Scanner sca = null;
13try{
14sca = new Scanner(file);
15}catch(FileNotFoundException e){
16e.printStackTrace();
17}
18String str = sca.next();
19System.out.println("从文件中读取的内容是:" + str);
20}
21}

【运行结果】:

从文件中读取的内容是:这些文件中的内容哦!

数据操作流DataOutputStreamDataInputStream

01import java.io.DataOutputStream;
02import java.io.File;
03import java.io.FileOutputStream;
04import java.io.IOException;
05 
06public class DataOutputStreamDemo{
07public static void main(String[] args) throws IOException{
08File file = new File("d:"+ File.separator +"hello.txt");
09char[] ch = { 'A', 'B', 'C' };
10DataOutputStream out = null;
11out = new DataOutputStream(newFileOutputStream(file));
12for(char temp : ch){
13out.writeChar(temp);
14}
15out.close();
16}
17}

A B C

现在我们在上面例子的基础上,使用DataInputStream读出内容

01import java.io.DataInputStream;
02import java.io.File;
03import java.io.FileInputStream;
04import java.io.IOException;
05 
06public class DataOutputStreamDemo{
07public static void main(String[] args) throws IOException{
08File file = new File("d:"+ File.separator +"hello.txt");
09DataInputStream input = new DataInputStream(newFileInputStream(file));
10char[] ch = new char[10];
11int count = ;
12char temp;
13while((temp = input.readChar()) != 'C'){
14ch[count++] = temp;
15}
16System.out.println(ch);
17}
18}

【运行结果】:

AB

合并流 SequenceInputStream

SequenceInputStream主要用来将2个流合并在一起,比如将两个txt中的内容合并为另外一个txt。下面给出一个实例:

01import java.io.File;
02import java.io.FileInputStream;
03import java.io.FileOutputStream;
04import java.io.IOException;
05import java.io.InputStream;
06import java.io.OutputStream;
07import java.io.SequenceInputStream;
08 
09/**
10* 将两个文本文件合并为另外一个文本文件
11* */
12public class SequenceInputStreamDemo{
13public static void main(String[] args) throws IOException{
14File file1 = new File("d:"+ File.separator +"hello1.txt");
15File file2 = new File("d:"+ File.separator +"hello2.txt");
16File file3 = new File("d:"+ File.separator +"hello.txt");
17InputStream input1 = new FileInputStream(file1);
18InputStream input2 = new FileInputStream(file2);
19OutputStream output = new FileOutputStream(file3);
20// 合并流
21SequenceInputStream sis = new SequenceInputStream(input1, input2);
22int temp = ;
23while((temp = sis.read()) != -1){
24output.write(temp);
25}
26input1.close();
27input2.close();
28output.close();
29sis.close();
30}
31}

【运行结果】

结果会在hello.txt文件中包含hello1.txthello2.txt文件中的内容。

文件压缩 ZipOutputStream

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

01import java.io.File;
02import java.io.FileInputStream;
03import java.io.FileOutputStream;
04import java.io.IOException;
05import java.io.InputStream;
06import java.util.zip.ZipEntry;
07import java.util.zip.ZipOutputStream;
08 
09public class ZipOutputStreamDemo1{
10public static void main(String[] args) throws IOException{
11File file = new File("d:"+ File.separator +"hello.txt");
12File zipFile = new File("d:"+ File.separator +"hello.zip");
13InputStream input = new FileInputStream(file);
14ZipOutputStream zipOut = new ZipOutputStream(newFileOutputStream(
15zipFile));
16zipOut.putNextEntry(new ZipEntry(file.getName()));
17// 设置注释
18zipOut.setComment("hello");
19int temp = ;
20while((temp = input.read()) != -1){
21zipOut.write(temp);
22}
23input.close();
24zipOut.close();
25}
26}

【运行结果】

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

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

上面的这个例子测试的是压缩单个文件,下面的们来看看如何压缩多个文件。

01import java.io.File;
02import java.io.FileInputStream;
03import java.io.FileOutputStream;
04import java.io.IOException;
05import java.io.InputStream;
06import java.util.zip.ZipEntry;
07import java.util.zip.ZipOutputStream;
08 
09/**
10* 一次性压缩多个文件
11* */
12public class ZipOutputStreamDemo2{
13public static void main(String[] args) throws IOException{
14// 要被压缩的文件夹
15File file = new File("d:"+ File.separator +"temp");
16File zipFile = new File("d:"+ File.separator +"zipFile.zip");
17InputStream input = null;
18ZipOutputStream zipOut = new ZipOutputStream(newFileOutputStream(
19zipFile));
20zipOut.setComment("hello");
21if(file.isDirectory()){
22File[] files = file.listFiles();
23for(int i = ; i < files.length; ++i){
24input = new FileInputStream(files[i]);
25zipOut.putNextEntry(new ZipEntry(file.getName()
26+ File.separator + files[i].getName()));
27int temp = ;
28while((temp = input.read()) != -1){
29zipOut.write(temp);
30}
31input.close();
32}
33}
34zipOut.close();
35}
36}

【运行结果】

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

接下来看看压缩之后的:

大家自然想到,既然能压缩,自然能解压缩,在谈解压缩之前,我们会用到一个ZipFile类,先给一个这个例子吧。java中的每一个压缩文件都是可以使用ZipFile来进行表示的

01import java.io.File;
02import java.io.IOException;
03import java.util.zip.ZipFile;
04 
05/**
06* ZipFile演示
07* */
08public class ZipFileDemo{
09public static void main(String[] args) throws IOException{
10File file = new File("d:"+ File.separator +"hello.zip");
11ZipFile zipFile = new ZipFile(file);
12System.out.println("压缩文件的名称为:" + zipFile.getName());
13}
14}

【运行结果】:

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

现在我们呢是时候来看看如何加压缩文件了,和之前一样,先让我们来解压单个压缩文件(也就是压缩文件中只有一个文件的情况),我们采用前面的例子产生的压缩文件hello.zip

01import java.io.File;
02import java.io.FileOutputStream;
03import java.io.IOException;
04import java.io.InputStream;
05import java.io.OutputStream;
06import java.util.zip.ZipEntry;
07import java.util.zip.ZipFile;
08 
09/**
10* 解压缩文件(压缩文件中只有一个文件的情况)
11* */
12public class ZipFileDemo2{
13public static void main(String[] args) throws IOException{
14File file = new File("d:"+ File.separator +"hello.zip");
15File outFile = new File("d:"+ File.separator +"unZipFile.txt");
16ZipFile zipFile = new ZipFile(file);
17ZipEntry entry = zipFile.getEntry("hello.txt");
18InputStream input = zipFile.getInputStream(entry);
19OutputStream output = new FileOutputStream(outFile);
20int temp = ;
21while((temp = input.read()) != -1){
22output.write(temp);
23}
24input.close();
25output.close();
26}
27}

【运行结果】:

解压缩之前:

这个压缩文件还是175字节

解压之后产生:

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

现在让我们来解压一个压缩文件中包含多个文件的情况吧

ZipInputStream

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

01import java.io.File;
02import java.io.FileInputStream;
03import java.io.FileOutputStream;
04import java.io.IOException;
05import java.io.InputStream;
06import java.io.OutputStream;
07import java.util.zip.ZipEntry;
08import java.util.zip.ZipFile;
09import java.util.zip.ZipInputStream;
10 
11/**
12* 解压缩一个压缩文件中包含多个文件的情况
13* */
14public class ZipFileDemo3{
15public static void main(String[] args) throws IOException{
16File file = new File("d:"+ File.separator +"zipFile.zip");
17File outFile = null;
18ZipFile zipFile = new ZipFile(file);
19ZipInputStream zipInput = new ZipInputStream(newFileInputStream(file));
20ZipEntry entry = null;
21InputStream input = null;
22OutputStream output = null;
23while((entry = zipInput.getNextEntry()) != null){
24System.out.println("解压缩" + entry.getName() +"文件");
25outFile = new File("d:"+ File.separator + entry.getName());
26if(!outFile.getParentFile().exists()){
27outFile.getParentFile().mkdir();
28}
29if(!outFile.exists()){
30outFile.createNewFile();
31}
32input = zipFile.getInputStream(entry);
33output = new FileOutputStream(outFile);
34int temp = ;
35while((temp = input.read()) != -1){
36output.write(temp);
37}
38input.close();
39output.close();
40}
41}
42}

【运行结果】:

被解压的文件:

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

PushBackInputStream回退流

01import java.io.ByteArrayInputStream;
02import java.io.IOException;
03import java.io.PushbackInputStream;
04 
05/**
06* 回退流操作
07* */
08public class PushBackInputStreamDemo{
09public static void main(String[] args) throws IOException{
10String str = "hello,rollenholt";
11PushbackInputStream push = null;
12ByteArrayInputStream bat = null;
13bat = new ByteArrayInputStream(str.getBytes());
14push = new PushbackInputStream(bat);
15int temp = ;
16while((temp = push.read()) != -1){
17if(temp == ','){
18push.unread(temp);
19temp = push.read();
20System.out.print("(回退" + (char) temp +") ");
21}else{
22System.out.print((char) temp);
23}
24}
25}
26}

【运行结果】:

hello(回退,) rollenholt

1/**
2* 取得本地的默认编码
3* */
4public class CharSetDemo{
5public static void main(String[] args){
6System.out.println("系统默认编码为:" + System.getProperty("file.encoding"));
7}
8}

【运行结果】:

系统默认编码为: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接口一样。实现了这个接口之后,就表示这个类具有被序列化的能力。

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

01import java.io.*;
02/**
03* 实现具有序列化能力的类
04* */
05public class SerializableDemo implementsSerializable{
06public SerializableDemo(){
07
08}
09public SerializableDemo(String name, intage){
10this.name=name;
11this.age=age;
12}
13@Override
14public String toString(){
15return "姓名:"+name+" 年龄:"+age;
16}
17private String name;
18private int age;
19}

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

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

先给一个ObjectOutputStream的例子吧:

01import java.io.Serializable;
02import java.io.File;
03import java.io.FileOutputStream;
04import java.io.IOException;
05import java.io.ObjectOutputStream;
06 
07/**
08* 实现具有序列化能力的类
09* */
10public class Person implementsSerializable{
11public Person(){
12 
13}
14 
15public Person(String name, intage){
16this.name = name;
17this.age = age;
18}
19 
20@Override
21public String toString(){
22return "姓名:" + name + " 年龄:"+ age;
23}
24 
25private String name;
26private int age;
27}
28/**
29* 示范ObjectOutputStream
30* */
31public class ObjectOutputStreamDemo{
32public static void main(String[] args) throws IOException{
33File file = new File("d:"+ File.separator +"hello.txt");
34ObjectOutputStream oos = new ObjectOutputStream(newFileOutputStream(
35file));
36oos.writeObject(new Person("rollen",20));
37oos.close();
38}
39}

【运行结果】:

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

虽然我们不能直接查看里面的内容,但是我们可以使用ObjectInputStream类查看:

01import java.io.File;
02import java.io.FileInputStream;
03import java.io.ObjectInputStream;
04 
05/**
06* ObjectInputStream示范
07* */
08public class ObjectInputStreamDemo{
09public static void main(String[] args) throws Exception{
10File file = new File("d:"+ File.separator +"hello.txt");
11ObjectInputStream input = new ObjectInputStream(newFileInputStream(
12file));
13Object obj = input.readObject();
14input.close();
15System.out.println(obj);
16}
17}

【运行结果】

姓名:rollen年龄:20

到底序列化什么内容呢?

其实只有属性会被序列化。

Externalizable接口

Serializable接口声明的类的对象的属性都将被序列化,但是如果想自定义序列化的内容的时候,就需要实现Externalizable接口。

当一个类要使用Externalizable这个接口的时候,这个类中必须要有一个无参的构造函数,如果没有的话,在构造的时候会产生异常,这是因为在反序列话的时候会默认调用无参的构造函数。

现在我们来演示一下序列化和反序列话:

01package IO;
02 
03import java.io.Externalizable;
04import java.io.File;
05import java.io.FileInputStream;
06import java.io.FileOutputStream;
07import java.io.IOException;
08import java.io.ObjectInput;
09import java.io.ObjectInputStream;
10import java.io.ObjectOutput;
11import java.io.ObjectOutputStream;
12 
13/**
14* 序列化和反序列化的操作
15* */
16public class ExternalizableDemo{
17public static void main(String[] args) throws Exception{
18ser(); // 序列化
19dser(); // 反序列话
20}
21 
22public static void ser() throws Exception{
23File file = new File("d:"+ File.separator +"hello.txt");
24ObjectOutputStream out = new ObjectOutputStream(newFileOutputStream(
25file));
26out.writeObject(new Person("rollen",20));
27out.close();
28}
29 
30public static void dser() throws Exception{
31File file = new File("d:"+ File.separator +"hello.txt");
32ObjectInputStream input = new ObjectInputStream(newFileInputStream(
33file));
34Object obj = input.readObject();
35input.close();
36System.out.println(obj);
37}
38}
39 
40class Person implements Externalizable{
41public Person(){
42 
43}
44 
45public Person(String name, intage){
46this.name = name;
47this.age = age;
48}
49 
50@Override
51public String toString(){
52return "姓名:" + name + " 年龄:"+ age;
53}
54 
55// 复写这个方法,根据需要可以保存的属性或者具体内容,在序列化的时候使用
56@Override
57public void writeExternal(ObjectOutput out)throwsIOException{
58out.writeObject(this.name);
59out.writeInt(age);
60}
61 
62// 复写这个方法,根据需要读取内容 反序列话的时候需要
63@Override
64public void readExternal(ObjectInput in)throwsIOException,
65ClassNotFoundException{
66this.name = (String) in.readObject();
67this.age = in.readInt();
68}
69 
70private String name;
71private int age;
72}

【运行结果】:

姓名:rollen年龄:20

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

Serializable接口实现的操作其实是吧一个对象中的全部属性进行序列化,当然也可以使用我们上使用是Externalizable接口以实现部分属性的序列化,但是这样的操作比较麻烦,

当我们使用Serializable接口实现序列化操作的时候,如果一个对象的某一个属性不想被序列化保存下来,那么我们可以使用transient关键字进行说明:

下面举一个例子:

01package IO;
02 
03import java.io.File;
04import java.io.FileInputStream;
05import java.io.FileOutputStream;
06import java.io.ObjectInputStream;
07import java.io.ObjectOutputStream;
08import java.io.Serializable;
09 
10/**
11* 序列化和反序列化的操作
12* */
13public class serDemo{
14public static void main(String[] args) throws Exception{
15ser(); // 序列化
16dser(); // 反序列话
17}
18 
19public static void ser() throws Exception{
20File file = new File("d:"+ File.separator +"hello.txt");
21ObjectOutputStream out = new ObjectOutputStream(newFileOutputStream(
22file));
23out.writeObject(new Person1("rollen",20));
24out.close();
25}
26 
27public static void dser() throws Exception{
28File file = new File("d:"+ File.separator +"hello.txt");
29ObjectInputStream input = new ObjectInputStream(newFileInputStream(
30file));
31Object obj = input.readObject();
32input.close();
33System.out.println(obj);
34}
35}
36 
37class Person1 implements Serializable{
38public Person1(){
39 
40}
41 
42public Person1(String name, intage){
43this.name = name;
44this.age = age;
45}
46 
47@Override
48public String toString(){
49return "姓名:" + name + " 年龄:"+ age;
50}
51 
52// 注意这里
53private transient String name;
54private int age;
55}

【运行结果】:

姓名:null年龄:20

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

01import java.io.File;
02import java.io.FileInputStream;
03import java.io.FileOutputStream;
04import java.io.ObjectInputStream;
05import java.io.ObjectOutputStream;
06import java.io.Serializable;
07 
08/**
09* 序列化一组对象
10* */
11public class SerDemo1{
12public static void main(String[] args) throws Exception{
13Student[] stu = { new Student("hello",20),new Student("world",30),
14new Student("rollen",40) };
15ser(stu);
16Object[] obj = dser();
17for(int i = ; i < obj.length; ++i){
18Student s = (Student) obj[i];
19System.out.println(s);
20}
21}
22 
23// 序列化
24public static void ser(Object[] obj) throws Exception{
25File file = new File("d:"+ File.separator +"hello.txt");
26ObjectOutputStream out = new ObjectOutputStream(newFileOutputStream(
27file));
28out.writeObject(obj);
29out.close();
30}
31 
32// 反序列化
33public static Object[] dser() throws Exception{
34File file = new File("d:"+ File.separator +"hello.txt");
35ObjectInputStream input = new ObjectInputStream(newFileInputStream(
36file));
37Object[] obj = (Object[]) input.readObject();
38input.close();
39return obj;
40}
41}
42 
43class Student implements Serializable{
44public Student(){
45 
46}
47 
48public Student(String name, intage){
49this.name = name;
50this.age = age;
51}
52 
53@Override
54public String toString(){
55return "姓名: " + name + " 年龄:"+ age;
56}
57 
58private String name;
59private int age;
60}

【运行结果】:

姓名:hello年龄:20

姓名:world年龄:30

姓名:rollen年龄:40