java第七课

 

 ■  文件和目录的创建

 文件的创建可以实现如下:

import  java.io. * ;
class  FileTest {
    
public static void main(String[] args)throws Exception{
        File f
=new File("sky2098.txt");
        f.createNewFile();
    }

}

编译运行:

将会在当前目录下生成一个sky2098.txt文件。

目录的创建可以实现如下:

import  java.io. * ;
class  FileTest {
    
public static void main(String[] args)throws Exception{
        File f
=new File("xiaoyu");
        f.mkdir();
    }

}

编译运行:

将会在当前目录下生成一个名称为xiaoyu的目录。

我们在创建一个文件时可以使用绝对路径:

File f.new File("D://javae//Lesson7//sky9999.ini");

f.createNewFile();

但是如果用下面的语句就会出错:

File f.new File("D:/javae/Lesson7/sky9999.ini");

f.createNewFile();

这是因为java中遇到"/"会查看它的后面的字符,是否构成转义字符,而"/j"没有 意义,所以出错了。

我们编写一个不依赖于系统平台的代码:

import  java.io. * ;
class  FileTest {
    
public static void main(String[] args)throws Exception{
        File fDir
=new File(File.separator);  //表示当前目录为“”
        String 
strFile
="javae"+File.separator+"Lesson7"+File.separator+"sky0000.aspx"//表示子目录
        File f=new File(fDir,strFile);
        f.createNewFile();
    }

}

编译运行:

可以看到在我们指定的目录下创建了一个sky0000.aspx文件。

程序中使用到File类的构造函数File(File parent, String child)。

其中parent为父目录名,child为子目录名。

还有File类的separator表示一个分隔符,这使得使用它的语句不依赖于平台。

其中 "javae"+File.separator+"Lesson7"+File.separator+"sky0000.aspx" ; 表示子目录为:

javae/Lesson7sky000.aspx

另外,可以使用f.delete();删除一个文件或者目录。

我们也可以调用f.deleteOnExit();在退出程序时删除一个文件或者目录。

我们通过下面语句:

for ( int  i = 0 ;i < 5 ;i ++ ) {
            File.createTempFil e(
"myfile"+i,".temp");
        }

可以连续创建5个临时文件。

其中,createTempFile是File类的静态方法。

调用File类的 String[] list() 方法可以列出目录下的所有文件和目录:

import  java.io. * ;
class  FileTest {
    
public static void main(String[] args)throws Exception{
        File fDir
=new File(File.separator);
        String strFile
="javae"+File.separator+"Lesson7";
        File f
=new File(fDir,strFile);
        String[] names
=f.list();
        
for(int i=0;i<names.length;i++){
            System.out.println (names[i]);
        }

    }

}

编译运行:

 ■  文件过滤器

下面介绍文件过滤器的使用:

import  java.io. * ;
class  FileTest {
    
public static void main(String[] args)throws Exception{
        File fDir
=new File(File.separator);
        String strFile
="javae"+File.separator+"Lesson7";
        File f
=new File(fDir,strFile);
        String[] names
=f.list(new FilenameFilter() {
            
public boolean accept (File dir,String name){
                 
return name.indexOf(".java")!=-1;
            }

        }
);
        
for(int i=0;i<names.length;i++){
            System.out.println (names[i]);
        }

    }

}

编译运行:

程序中FilenameFilter是一个接口,它只有一个accept方法,我们在程序中还使用了匿名类。

在程序中我们过滤掉了除.java以外的其它文件,并打印显示出来。

File类有很多方法,可以自己尝试着使用一下,了解各个方法能够实现的功能。

 ■  InputStream类

三个基本的读方法

      abstract int read() :读取一个字节数据,并返回读到的数据, 如果返回-1,表示读到了输入流的末尾。

      int read(byte[] b) :将数据读入一个字节数组,同时返回 实际读取的字节数。如果返回-1,表示读到了输入流的末尾。

      int read(byte[] b, int off, int len) :将数 据读入一个字节数组,同时返回实际读取的字节数。如果返回-1,表示读到了输入流的末尾。off指定在 数组b中存放数据的起始偏移位置;len指定读取的最大字节数。
其它方法。

      long skip(long n) :在输入流中跳过n个字节,并返回实际 跳过的字节数。

      int available() :返回在不发生阻塞的情况下,可读取的字节数 。

      void close() :关闭输入流,释放和这个流相关的系统资源。

      void mark(int readlimit) :在输入流的当前位置放置一个 标记,如果读取的字节数多于readlimit设置的值,则流忽略这个标记。在IutputStream类中实际是一个 空实现。

      void reset() :返回到上一个标记。

      boolean markSupported() :测试当前流是否支持mark和reset方 法。如果支持,返回true,否则返回false。在IutputStream类中实际是一个空实现。

在java.io包中InputStream类层析结构如图所示:

 ■  OutputStream类

三个基本的写方法

     abstract void write(int b) :往输出流中写入一个字节。当我们 传递一个int型的b时,写入了b的第一个字节。

     void write(byte[] b) :往输出流中写入数组b中的所有字节。

     void write(byte[] b, int off, int len) :往输出流 中写入数组b中从偏移量off开始的len个字节的数据。


其它方法

     void flush() :刷新输出流,强制缓冲区中的输出字节被写出。只对使 用了缓冲的流类起作用。在OutputStream类中实际是一个空实现。

     void close() :关闭输出流,释放和这个流相关的系统资源。

在java.io包中OutputStream类层析结构如图所示:

可见,InputStream和OutputStream两个类层析结构是相对应的,这更加便于记忆。

在System类中,out和err是PrintStream类的静态对象;in是InputStream类的静态对象。

因此,out和err可以引用PrintStream类的成员方法;in可以引用InputStream类的成员方法。

■  读入与输出数据实例

import  java.io. * ;
class  StreamTest {
    
public static void main(String[] args)throws Exception{
        
int data;
        
while((data=System.in.read())!=-1) {
            System.out.write (data);
        }

    }

}

编译运行,并输入“sky2098”:

我们可以按下Ctrl+C键终止。

 ■  基本的流类

 FileInputStream和FileOutputStream
    节点流,用于从文件中读取 或往文件中写入字节流。如果在构造FileOutputStream时,文件已经存在,则覆盖这个文件。

向指定文件中写入数据:

import  java.io. * ;
class  StreamTest {
    
public static void main(String[] args)throws Exception{
        FileOutputStream fos
=new FileOutputStream("sky2098.txt");
        fos.write(
"My name is sky2098! ".getBytes ());
        fos.close();
    }

}

编译运行:

我们可以打开D:/javae/Lesson7>目录下的sky2098.txt文件,查看写入内容为:

 My name is sky2098!

程序中使用到FileOutputStream类的方法void write(byte[] b) ,所以从写入字符串"My name is sky2098!"通过String类的方法getBytes()得到字节数组b,成功进行写入。

从指定文件中读出数据: 

import  java.io. * ;
class  StreamTest {
    
public static void main(String[] args)throws Exception{
        FileInputStream fis
=new FileInputStream("sky2098.txt");
        
byte[] buf=new byte [100];
        
int len=fis.read(buf);
        System.out.println(
new String(buf,0,len));//由于buf是大小为100的缓冲区,为 了输出有效字符使用String类的构造方法String(byte[]  bytes, int offset, int length)实现输出
        fis.close();
    }

}

编译运行:

 可见从文件sky2098.txt读出了数据。

BufferedInputStream和BufferedOutputStream

    过滤流,需要使用已经存在的节点流来构造,提供带缓冲的读写,提高了读写的 效率。

 向指定文件中写入数据:

import  java.io. * ;
class  StreamTest {
    
public static void main(String[] args)throws Exception{
        FileOutputStream fos
=new FileOutputStream("sky2098.txt");
        BufferedOutputStream bos
=new BufferedOutputStream(fos);
        bos.write(
"Sky2098 is working now!".getBytes());
        bos.close();
    }

}

 

编译运行:

如果不加bos.close();语句,则运行后打开D:/javae/Lesson7>目录下的sky2098.txt文件会查看不到内容,这是因为我们将数据写入了缓冲区,只有结束程序时才写入到指定文件中。bos.close();实现立即写入到指定文件,不同的是这样如果想要继续写入就不用再次打开文件了。

我们可以打开D:/javae/Lesson7>目录下的sky2098.txt文件,查看写入内容为:

Sky2098 is working now!

从指定文件中读出数据:

import  java.io. * ;
class  StreamTest {
    
public static void main(String[] args)throws Exception{
        FileOutputStream fos
=new FileOutputStream("sky2098.txt");
        BufferedOutputStream bos
=new BufferedOutputStream(fos);
        bos.write(
"Sky2098 is working now!".getBytes());
        bos.close();
    }

}

编译运行:

DataInputStream和DataOutputStream

      过滤流,需要使用已经存在的节点流来构造,提供了读写Java中的 基本数据类型的功能。

 向指定文件中写入数据:

import  java.io. * ;
class  StreamTest {
    
public static void main(String[] args)throws Exception{
        FileOutputStream fos
=new FileOutputStream("sky2098.txt");
        BufferedOutputStream bos
=new BufferedOutputStream(fos);
        DataOutputStream dos
=new DataOutputStream(bos);
        
byte b=3;
        
int i=100;
        
boolean bool=false;
        
char c='k';
        
float f=45.77f;
        dos.writeByte(b);
        dos.writeInt(i);
        dos.writeBoolean(bool);
        dos.writeChar(c);
        dos.writeFloat(f);
        dos.close();
    }

}

编译运行:

我们可以打开D:/javae/Lesson7>目录下的sky2098.txt文件,查看写入内容为:

   d  kB7{

可以使用UltraEdit打开,查看写入的二进制数据文件。

从指定文件中读出数据:

import  java.io. * ;
class  StreamTest {
    
public static void main(String[] args)throws Exception{
        FileInputStream fis
=new FileInputStream("sky2098.txt");
        BufferedInputStream bis
=new BufferedInputStream(fis);
        DataInputStream dis
=new DataInputStream(bis);
        System.out.println(dis.readByte());
        System.out.println(dis.readInt());
        System.out.println(dis.readBoolean());
        System.out.println(dis.readChar());
        System.out.println(dis.readFloat());
        dis.close();
    }

}

编译运行:

PipedInputStream和PipedOutputStream

PipedInputStream和PipedOutputStream分别从InputStream类和OutputStream类继承,因此它们并不是过滤流类。

    管道流,用于线程间的通信。一个线程的PipedInputStream对象从另一个线程的 PipedOutputStream对象读取。要使管道流有用,必须同时构造管道输入流和管道输出流。

利用线程生产者和消费者问题:

import  java.io. * ;
class  PipedStreamTest {
    
public static void main(String[] args){
        PipedOutputStream pos
=new PipedOutputStream();
        PipedInputStream pis
=new PipedInputStream();
        
try{
            pos.connect(pis);
            
new Producer(pos).start();
            
new Consumer(pis).start();
        }
catch(Exception e){
            e.printStackTrace();
        }

    }

}

class  Producer  extends  Thread {
    
private PipedOutputStream pos;
    Producer(PipedOutputStream pos)
{
        
this.pos=pos;
    }

    
public void run(){
        
try{
            pos.write(
"Hello,My friends!".getBytes());
            pos.close();
        }
catch(Exception e){
            e.printStackTrace();
        }

    }

}
 
class  Consumer  extends  Thread {
    
private PipedInputStream pis;
    Consumer(PipedInputStream pis)
{
        
this.pis=pis;
    }

    
public void run(){
        
try{
            
byte[] buf=new byte[100];
            
int len=pis.read(buf);
            System.out.println(
new String(buf,0,len));
            pis.close();
        }
catch(Exception e){
            e.printStackTrace();
        }

    }

}

编译运行:

■  Java I/O库的设计原则

Java的I/O库提供了一个称做链接的机制,可以将一个流与另一个流首尾相接,形成一个流管道的链接。这种机制实际上是一种被称为Decorator(装饰)设计模式的应用。

通过流的链接,可以动态的增加流的功能,而这种功能的增加是通过组合一些流的基本功能而动态获取的。

我们要获取一个I/O对象,往往需要产生多个I/O对象,这也是Java I/O库不太容易掌握的原因,但在I/O库中Decorator模式的运用,给我们提供了实现上的灵活性。

■  Java I/O流的链接

 通过下面的图示我们可以对上面进行总结,对java I/O流有一个总体的认识:

 

 ■  Reader和Writer

Java程序语言使用Unicode来表示字符串和字符,用16位来表示一个字符。

Reader和Writer这两个抽象类主要用来读写字符流。

InputStream和OutputStream是对字节流进行操作的,而Reader和Writer是与前两者相对应的,是对字符流进行操作的。

java.io包中Reader的类层次如下:


 java.io包中Writer的类层次如下:

 我们编写一个例子:

import  java.io. * ;
class  StreamTest {
    
public static void main(String[] args)throws Exception{
        FileOutputStream fos
=new FileOutputStream("sky2098.txt");
        OutputStreamWriter osw
=new OutputStreamWriter(fos);
        BufferedWriter bw
=new BufferedWriter(osw);
        bw.write(
"Hello,I use BufferdWriter write this string!");
        bw.close();
    }

}

如果用的是JDK 1.5,则编译运行如下:

 孙鑫老师也讲过,在JDK1.4内有有个小小的bug,所以在JDK1.5不再支持了。

在JDK 1.4应该能编译运行通过,然后可以在当前目录下的sky2098.txt内查看到写入的数据:

Hello,I use BufferdWriter write this string!

关于读取也是类似的:

import  java.io. * ;
class  StreamTest {
    
public static void main(String[] args)throws Exception{
        FileOutputStream fos
=new FileOutputStream("sky2098.txt");
        OutputStreamWriter osw
=new OutputStreamWriter(fos);
        BufferedWriter bw
=new BufferedWriter(osw);
        bw.write(
"Hello,I use BufferdWriter write this string!");
        bw.close();

        FileInputStream fis
=new FileInputStream("sky2098.txt");
        InputStreamReader isr
=new InputStreamReader(fis);
        BufferedReader br
=new BufferedReader(isr);
        System.out.println(br.readLine());
        br.close();
    }

}

需要在JDK 1.4版本上执行。

■  字符集的编码

ASCII(American Standard Code for Information Interchange,美国信息互换标准代码),是基于常用的英文字符的一套电脑编码系统。我们知道英文中经常使用的字符、数字符号被计算机处理时都是以二进制码的形式出现的。这种二进制码的集合就是所谓的ASCII码。每一个ASCII码与一个8位(bit)二进制数对应。其最高位是0,相应的十进制数是0-127。如,数字“0”的编码用十进制数表示就是48。另有128个扩展的ASCII码,最高位都是1,由一些制表符和其它符号组成。ASCII是现今最通用的单字节编码系统。

GB2312:GB2312码是中华人民共和国国家汉字信息交换用编码,全称《信息交换用汉字编码字符集-基本集》。主要用于给每一个中文字符指定相应的数字,也就是进行编码。一个中文字符用两个字节的数字来表示,为了和ASCII码有所区别,将中文字符每一个字节的最高位置都用1来表示。

GBK:为了对更多的字符进行编码,国家又发布了新的编码系统GBK(GBK的K是“扩展”的汉语拼音第一个字母)。在新的编码系统里,除了完全兼容GB2312 外,还对繁体中文、一些不常用的汉字和许多符号进行了编码。
ISO-8859-1:是西方国家所使用的字符编码集,是一种单字节的字符集 ,而英文实际上只用了其中数字小于128的部分。

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值