课外天地 李树青学习天地Java程序语言课件 → 课件20下载——输入输出流


  共有15645人关注过本帖树形打印复制链接

主题:课件20下载——输入输出流

帅哥哟,离线,有人找我吗?
admin
  1楼 博客 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信 管理员
等级:管理员 帖子:1940 积分:26616 威望:0 精华:34 注册:2003/12/30 16:34:32
课件20下载——输入输出流  发帖心情 Post By:2006/2/26 22:11:06 [只看该作者]

1 简介
Java的输入输出流使用统一的类库访问方法,解决了程序和外设(如文件、网络、屏幕、键盘等)间的数据交换问题。

这些流类可以按照不同的标准分为不同的类集:
如果按照处理数据信息的方向,可以分为输入流和输出流。所谓的输入和输出是相对于程序而言的,也就是说,输入流是指从外部向程序输入数据信息,输入流是指从程序向外部输出数据信息。

如果按照处理的数据信息类型,主要分为两部分,一为字节流类,二为字符流类。其中字节流类的基类是InputStream与OutputStream,它们都是抽象类,用于二进制信息的处理;字符流类的基类是Reader与Writer,也都是抽象类,用于对16位字符的处理提供简单的做法。

如果按照类本身的功能是否独立可以分为数据流类和处理流类,前者处理真实的数据信息(如字符串、文件、管道等),而后者处理诸如缓冲或者字符编码等,只能通过操纵数据流类来处理数据。

2、文件输入和输出
文件输入和输出仅仅是众多流处理功能的一个,当然也是比较重要的一个

2、1 基于字节流的文件处理
2、1、1 文件字节输入流
基类为InputStream,在创建时自动打开数据流,利用close()显式关闭。如果没有正常关闭或者flush,文件信息将会丢失。

常用的方法有:
int read():从输入流中读入一个字节,并且返回0到255之间的整数。如果到达流尾,则返回为-1。
long skip(long):指定跳过多少字节,返回实际跳过的字节数量(有时因为提前到达文件尾从而实际跳过的字节数小于指定的数值)。如果为负,则没有跳过任何字节。

下面的程序演示了文件长度的输出:
import java.io.*;

public class exec
{
        public static void main(String[] args)throws IOException
        {
                FileInputStream fis=new FileInputStream("Hello.txt");
                System.out.println(fis.available());            
        }              
}

也可以使用File类对象获取文件长度,如:
import java.io.*;

public class exec
{
        public static void main(String[] args)throws IOException
        {
                File f=new File("Hello.txt");
                System.out.println(f.length());
        }              
}

当然,这两种方式并不一样,如下面的例子显示了available和length()的区别:
import java.io.*;
import java.util.*;

public class exec
{
        public static void main(String[] args)throws IOException
        {
                byte[] bt=new byte[4];  
                
                File f=new File("Hello.txt");
                System.out.println(f.length());
                
                FileInputStream fio = new FileInputStream(f);
                int i=fio.read(bt);
                
                String temp=new String(bt);            
                System.out.println(fio.available());
                System.out.println(temp);
                fio.close();
        }
}
说明:available实际含义为文件可以访问但还尚未访问的字节数,由于刚打开文件,所以和文件长度相等,而如果进行了一些文件访问,这个值就会变化,所以真正求文件长度的方法是应该使用File类

下例是显示文件全部内容:
import java.io.*;

public class exec
{
        public static void main(String[] args)throws IOException
        {
                FileInputStream fis=new FileInputStream("Hello.txt");
                byte[] barray=new byte[fis.available()];
                fis.read(barray);
                String str=new String(barray);
                System.out.println(str);
        }
}
注意:read方法只能一次一个字节的读取,所以必须通过字节数组来接受文件信息,并且这个数组应该和文件一样长

2、1、2 文件字节输出流
基类为OutputStream,在创建时自动打开数据流,利用close()显式关闭。常用的方法有:
void write(int):将指定字节写入输出流,高于八比特的位将会被忽略
void flush():强制写出任何缓冲中的输出字节

如下面的程序将字符‘0’写入文件:
import java.io.*;

public class exec
{
        public static void main(String[] args)throws IOException
        {
                FileOutputStream fos=new FileOutputStream("hello.txt",true);            
                fos.write(0x30);
                fos.close();
        }      
}
注意:
1)如果文件不存在,FileOutputStream会创建文件,并将数据写入文件
2)FileOutputStream构造函数中的true表示追加方式,否则为替换方式

由于此类只支持字节的输出,所以对于其他类型的数据只有在转换为字节后才能向文件输出,如下例将一个字符串写入文件
import java.io.*;

public class exec
{
        public static void main(String[] args)throws IOException
        {
                FileOutputStream fos=new FileOutputStream("hello.txt",true);            
                fos.write("Hello".getBytes());
                fos.close();
        }              
}

2、2 基于字符流的文件处理
2、2、1 文件字符输入流
基类为Reader,面向Unicode字符,能够读取任何字符从而实现了国际化。和InputStream和OutputStream一样,在创建时自动打开数据流,利用close()显式关闭

如使用字符方式读取文件的一个字符:
import java.io.*;

public class exec
{
        public static void main(String[] args)throws IOException
        {
                FileReader fr=new FileReader("Hello.txt");
                System.out.println((char)fr.read());
        }
}

使用字符方式读取文件全部信息的例子:
import java.io.*;
import java.util.*;

public class exec
{
        public static void main(String[] args)throws IOException
        {
                File file = new File("Hello.txt");
                int size = (int)file.length();
                FileReader in = new FileReader(file);
                char[] data = new char[size];
                in.read(data, 0, size);
                System.out.println(new String(data));
                in.close();
        }
}

2、2、2 文件字符输入流
基类为Writer,面向Unicode字符,能够写入任何字符从而实现了国际化。和Read、InputStream和OutputStream一样,在创建时自动打开数据流,利用close()显式关闭

如下面的程序向文件输出字符串:
import java.io.*;

public class exec
{
        public static void main(String[] args)throws IOException
        {
                FileWriter fw=new FileWriter("Hello.txt");
                fw.write("hello!");
                fw.close();            
        }
}

2、3 在基于字节的流类和基于字符的流类进行转换
下面考虑一个程序,可以从键盘输入信息,以回车结束,保存到文件,再读取显示在屏幕上:
import java.io.*;

public class exec
{
        public static void main(String[] args)throws IOException
        {
                byte[] inarray=new byte[10];
                int index=0;
                while(true)
                {
                        int ch=System.in.read();
                        if(ch==13)
                                break;
                        else
                        {
                                inarray[index]=(byte)ch;
                                index++;
                        }
                }
                
                FileOutputStream fos=new FileOutputStream("hello.txt");
                for(int i=0;i<index;i++)
                        fos.write(inarray);
                fos.close();
                
                File f=new File("Hello.txt");
                
                FileInputStream fis=new FileInputStream("Hello.txt");
                for(index=0;index<f.length();index++)
                        System.out.print((char)fis.read());            
        }              
}
注意:这个程序存在两个问题,一是代码相当繁琐,二是对于输入的中文信息无法正确显示在屏幕上。此时可以考虑使用使用基于字符的处理方式,但是很多情况下,我们只能获得基于字节的流对象,这时就可以使用InputStreamReader将基于字节的输入流转换为基于字符的输入流,使用OutputStreamWriter将基于字节的输出流转换为基于字符的输出流,同时这些类还支持字符集的转换

上述代码修改为:
import java.io.*;

public class exec
{
        public static void main(String[] args)throws IOException
        {
                InputStreamReader isr=new InputStreamReader(System.in,"GBK");
        
                char[] inarray=new char[1000];
                isr.read(inarray);

                FileOutputStream fos=new FileOutputStream("hello.txt");
                OutputStreamWriter osw=new OutputStreamWriter(fos,"GBK");

                for(int i=0;i<inarray.length;i++)
                        osw.write(inarray);
                osw.close();
                
                osw=new OutputStreamWriter(System.out,"GBK");
                for(int i=0;i<inarray.length;i++)
                        osw.write(inarray);
                osw.close();
        }              
}

2、4 功能流类的使用
单纯使用上述流类并不有时十分方便,如上述的流类,只能按照逐字节或者整个字节数组进行输入,有时需要按照按行输入(以回车键为结束标记)就不是非常方便了。一些常用的功能流类可以解决这些问题

2、4、1 缓冲流类
包含BufferedReader和BufferedWriter,提供了很多很好用的方法,如newLine()和readLine()方法等
import java.io.*;

public class exec
{
        public static void main(String[] args)throws IOException
        {      
                FileOutputStream fos=new FileOutputStream("Hello.txt");
                BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(fos));
                bw.write("Hello!");
                bw.newLine();
                bw.write("Bye!");
                bw.close();
                
                FileInputStream fis=new FileInputStream("Hello.txt");
                BufferedReader br=new BufferedReader(new InputStreamReader(fis));
                System.out.println(br.readLine());              
        }
}

利用这些方法可以方便的实现文本文件的拷贝,如:
import java.io.*;

public class exec
{
        public static void main(String[] args)throws IOException
        {      
                FileInputStream fis=new FileInputStream("Hello.txt");
                BufferedReader br=new BufferedReader(new InputStreamReader(fis));
                
                FileOutputStream fos=new FileOutputStream("Hello.bak");
                BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(fos));
                
                while(true)
                {
                        String line=br.readLine();
                        if(line==null)
                                break;
                        else
                        {
                                bw.write(line+"\n");
                        }
                }
                br.close();    
                bw.close();
        }
}

2、4、2 PrintWriter
包含一些使生成格式化输出变得更简单的方法,如println()方法等
import java.io.*;

public class exec
{
        public static void main(String[] args)throws IOException
        {      
                FileOutputStream fos=new FileOutputStream("Hello.txt");
                PrintWriter pw=new PrintWriter(fos);
                pw.println("Hello!"+1);
                pw.println(true);
                pw.close();
        }
}

3、流类在异种设备上的使用
不同的硬件设备具有不同的输入和输出方式,然而使用流类可以将具体的操作细节屏蔽掉,通过流类对象可以使用一种统一的方式来对这些设备进行访问

如下面的程序能够读入一个文件中的一行,存放在另一个文件中:
import java.io.*;

public class exec
{
        public static void main(String[] args)throws IOException
        {      
                FileInputStream fis=new FileInputStream("Hello.txt");
                BufferedReader br=new BufferedReader(new InputStreamReader(fis));
                
                FileOutputStream fos=new FileOutputStream("Hello.bak");
                BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(fos));

                String line=br.readLine();
                bw.write(line+"\n");
                
                br.close();
                bw.close();
        }
}

再如下面这个相似的程序能够从键盘读入一行,存放在另一个文件中:
import java.io.*;

public class exec
{
        public static void main(String[] args)throws IOException
        {      
                BufferedReader br=new BufferedReader(new InputStreamReader(System.in,"GBK"));
                
                FileOutputStream fos=new FileOutputStream("Hello.bak");
                BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(fos));

                String line=br.readLine();
                bw.write(line+"\n");
                
                br.close();
                bw.close();
        }
}

甚至在网络上的通信中,也有相似的代码,如下面的程序片段能够获取网络服务器传来的一行文本信息:
BufferedReader is=new BufferedReader( new InputStreamReader(socket.getInputStream()));
String readline;
readline=sin.readLine();

4 File类
提供定位本地文件系统、描述文件和目录的功能,其中的诸多方法相当有用。
import java.io.*;
import java.util.*;

public class exec
{
        public static void main(String[] args)throws IOException
        {
                File fl=new File("files","Hello.txt");
                System.out.println(fl.getName());
                System.out.println(fl.getPath());
                System.out.println(fl.getAbsolutePath());
                System.out.println(new Date(fl.lastModified()));
                System.out.println(fl.exists());
                System.out.println(fl.isDirectory());
                System.out.println(fl.isFile());
                if(fl.canRead())
                        System.out.println("Can Read!");
                else
                        System.out.println("Can not Read!");
                if(fl.canWrite())
                        System.out.println("Can Write!");
                else
                        System.out.println("Can not Write!");
        }
}
上述程序在没有Hello.txt文件的时候,输出为
Hello.txt
files\Hello.txt
C:\Documents and Settings\Administrator\桌面\共享资源\files\Hello.txt
Thu Jan 01 08:00:00 CST 1970
false
false
false
Can not Read!
Can not Write!

上述程序在有Hello.txt文件的时候,输出为
Hello.txt
files\Hello.txt
C:\Documents and Settings\Administrator\桌面\共享资源\files\Hello.txt
Sat Sep 17 07:59:22 CST 2005
true
false
true
Can Read!
Can Write!

上述程序在有Hello.txt文件并且为只读属性的时候,输出为
Hello.txt
files\Hello.txt
C:\Documents and Settings\Administrator\桌面\共享资源\files\Hello.txt
Sat Sep 17 07:59:22 CST 2005
true
false
true
Can Read!
Can not Write!

通过File类可以遍历目录文件
import java.io.*;

public class exec
{
        public static void main(String[] args)throws IOException
        {
                File f=new File(System.getProperty("user.dir"));
                File files[]=f.listFiles();
                for(int i=0;i<files.length;i++)
                {
                        System.out.print(files.getName());
                        if(files.isDirectory())
                                System.out.println("\t<dir>");
                        else
                            System.out.println("\t"+files.length());                
                }
        }
}

进一步遍历下级子目录中的文件
import java.io.*;

public class exec
{
        public static void main(String[] args)throws IOException
        {
                seeIt(System.getProperty("user.dir"));
        }
        
        public static void seeIt(String str)
        {
                File f=new File(str);
                File files[]=f.listFiles();
                for(int i=0;i<files.length;i++)
                {
                        System.out.print(files.getName());
                        if(files.isDirectory())
                        {
                                System.out.println("\t<dir>");
                                seeIt(files.getPath());
                        }                      
                        else
                            System.out.println("\t"+files.length());                
                }
        }
}


 

[此贴子已经被作者于2010-12-12 08:04:00编辑过]

 回到顶部