Java IO

JAVA IO详解

前言:  

    Java IO 操作主要指的是使用Java进行输入、输出操作,Java中的所有操作类都存放在java.io包中,而整个java.io包中最重要的就是5个类和一个接口,5个类指的是File、OutputStream、ImputStream、Writer、Reader。一个接口指的是Serializable。掌握了这些就等于掌握了IO操作的核心。

一、操作文件的类——File

1.File类的基本介绍

        在整个io包中,唯一表示与文件本身有关的类就是File类。使用File类可以进行创建或删除文件等常用操作。要想使用File类,则首先要观察File类的构造方法,此类的常用构造方法如下所示:

        public File(String pathname)  ->实例化File类的时候,必须设置好路径

                                                                                                          表1   File类中的常用方法和常量

2.使用File类操作文件

实例操作一:创建一个新文件

直接使用creatNewFile()创建一个新文件,但是此方法使用了throws关键字声明,所以使用中,必须使用try..cath进行异常处理。

注意:如果在不同的操作系统中,则路径的分隔符表示是不一样的,例如:

           Windows 中使用反斜杠表示目录的分隔符  “\”

           Linux 中使用正斜杠表示目录的分隔符 “/”

因此,为了达到可移植性的目的,在操作文件时,一定要学会使用File.separator表示分隔符

实例操作二:删除一个指定的文件

直接使用File类中的delete()方法

注意:在删除文件前应该保证文件存在,所以最好在删除之前判断一下文件是否存在,在此,可以使用File类提供的exists()方法,此方法返回boolean类型

//以下给出两个实例相结合的代码

import java.io.File;
import java.io.IOException;
/*
 * 创建文件,注意文件路径,采用拼凑给出路径,以便适合不同操作系统
 * 删除文件,创建新文件时要判断文件是否已经存在
 */

public class IoDemo1 {

    public static void main(String[] args) {
        //File file = new File("d:\\test.txt");  //普通创建文件路径,但不同系统分隔符不一样
        File file = new File("d:"+ File.separator +"text.txt");  
        try {
            if(file.exists()){           //判断文件是否存在
                file.delete();          //删除文件,并且保证文件存在,需要加判断
            }else {
                file.createNewFile();       //创建一个文件
            }
            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}


实例操作四:创建一个文件夹

直接使用mkdir()方法

实例操作五:列出指定目录的全部文件

在File类中,定义了两个列出文件夹内容的方法:

           public String [] list()     列出全部名称,返回一个字符串数组

           public File[] listFiles()   列出完整的路径,返回一个File对象数组

实例操作六:判断一个给定的路径是否是目录

直接使用isDirectory()方法判断

//以下给出以上三个实例的代码

import java.io.File;

/*
 * 创建文件夹,直接使用 mkdir()方法
 * 显示文件夹中所有文件名称,使用list()方法,返回一个字符串数组
 * 显示文件夹中所有文件的完整路径,使用listFiles()方法,返回的是File文件数组
 * 判断一个给定的路径是否是目录,使用isDirectory()方法,返回时boolean
 */

public class IoDemo2 {
    public static void main(String[] args) {
        File f = newFile("d:"+ File.separator+"mldn");  //声明文件夹地址
        f.mkdirs();            //创建文件夹
        
        File file = new File("d:"+File.separator);
        String str[] = file.list();
        File files[] = file.listFiles();               //列出所有文件
        for (int i = 0; i < str.length; i++) {
//            System.out.println(str[i]);
            System.out.println(files[i]);
        }
        if (f.isDirectory()) {             //判断路径是否为目录
            System.out.println(f.getPath()+"路径是目录");
        }else {
            System.out.println(f.getPath()+"路径不是目录");
        }
    }
}

二、RandomAccessFile类

File类只是针对文件本身进行操作,而如果要对文件内容进行操作,则可以使用RandomAccessFile类,此类属于随机读取类,即可以随机读取一个文件中指定位置的数据。

例如:假设给定以下三个数据:

             zhangsan,  30

             lisi , 31

             wangwu,32

                                                                                                                                       表2:RandomAccessFile类的常用操作方法

                                                                                

注意:使用rw方式声明RandomAccessFile对象时,要写入的文件不存在,系统自动创建

//以下给出相应代码

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;

public class RandomAccessFileDemo1 {

    public static void main(String[] args) throws IOException {
        File file = new File("d:"+File.separator+"text.txt");
        RandomAccessFile rdf = null;
        rdf = new RandomAccessFile(file, "rw");
        String name = "zhangsan";
        int age = 30;
        rdf.writeBytes(name);
        rdf.writeInt(age);
        rdf.close();
    }

}


三、字节流

1.字节输出流:OutputStream

OutputStream 是整个IO包中字节输出流的最大父类,此类定义如下:

      public abstreact class OutputStream

      extends Object

      implements Closeable,Flushable

从以上定义中可以看出,OutputStream 类是一个抽象类,即不能直接使用,需要通过子类实例化对象。如果现在操作的是一个文件,可以使用FileOutputStream类,通过向上转型后,可以为OutputStream 实例化。

                                                                                                          表3:OutputStream类的常用方法

No.

方法或常量

类型

描述

1

public void close() throws IOException

普通

关闭输出流

2

public void flush() throws IOException

普通

刷新缓冲区

3

public void write(byte[] b) throws IOException

普通

将一个byte数组写入数据流

4

public void write(byte[] b,int off,int len) throws IOException

普通

将一个指定范围的byte数组写入数据流

5

public abstract void write(int b) throwsIOException

普通

将一个字节数据写入数据流

2.字节输入流

既然程序可以向文件中写入内容,则就可以通过InputStream从文件中把内容读取进来,首先来看InputStream类的定义:

        public abstract class InputStream

        extends Object

        implementsCloseable

OutputStream类一样,InputStream本身也是一个抽象类,必须依靠其子类,如果现在是从文件中读取,子类肯定是FileInputStream

                                                                                                               表4:InputStream类的常用方法

No.

方法或常量

类型

描述

1

public int available() throws IOException

普通

可以取得输入文件的大小

2

public void close() throws IOException

普通

关闭输入流

3

public abstract int read() throws IOException

普通

读取内容,以数字的方式读取

4

public int read(byte[] b) throws IOException

普通

将内容读到byte数组之中,同时返回读入的个数


注意:追加新内容,则需要使用FileOutStream类的另外一个构造方法,OutputStream out = new FileOutputStream(file,true); //表示追加内容

           InputStream类 同上

//以下给出实现代码

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

/*
 *字节流 :
 *1.使用File类打开一个文件
 *2.通过字节流的子类指定输出的位置
 *3.进行读写操作
 *4.关闭输入输出
 */

public class StreamDemo {
    public static void main(String[] args) throws IOException {
        File file = new File("d:"+File.separator+"text.txt");
        //OutputStream out = new FileOutputStream(file);   //参数不带true则再次运行时会取代原有文件内容
        OutputStream out = new FileOutputStream(file,true); //表示追加内容
//        String s = "hellow !";

        String s = "\r\nhellow !";       //追加内容换行
        byte b[] = s.getBytes();        //将字符串转换成字节数组
        out.write(b);
        out.close();
        
        InputStream in = new FileInputStream(file);
        byte b1[] = new byte[(int)file.length()];    //设置数组的大小
        in.read(b1);              //把内容取出,读到b1数组中
        in.close();
        System.out.println(new String(b1));   //输出
    }
}


四、字符流

1.字符输出流Writer

Writer 本身就是第一个字符流的输出类,此类的定义如下:

             public abstract class Writer

             extends Object

              implements Appendable ,Closeable ,Flushable

此类也是一个抽象类,应该使用FileWriter的子类,

                     

                                                                                                          表5:Writer 类的常用方法

No.

方法或常量

类型

描述

1

public abstract void close() throws IOException

普通

关闭输出流

2

public void write(String str) throws IOException

普通

将字符串输出

3

public void write(char[] cbuf) throws IOException

普通

将字符数组输出

4

public abstract void flush() throws IOException

普通

强制性清空缓存


2.字符输入流Reader

Reader是使用字符的方式从文件之中取出数据,Reader类的定义如下

              public abstract class Reader
             extends Object
              implements Readable, Closeable
Reader 本身也是抽象类,如果现在要从文件中读取内容,则可以直接使用 FileReader 子类。


                                                                                         表6:Reader类的常用方法

No.

方法或常量

类型

描述

1

public abstract void close() throws IOException

普通

关闭输出流

2

public int read() throws IOException

普通

读取单个字符

3

public int read(char[] cbuf) throws IOException

普通

将内容读到字符数组之中,返回读入的长度

字符流与字节流的区别:

³ 字节流在操作的时候本身是不会用到缓冲区(内存)的,是与文件本身直接操作的,而字符流在操作的时候是使用到缓冲区的。



//以下给出相应代码


import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;

/*
 * 字符流:与字节流使用步骤差不多
 */

public class WriterReaderDemo {
    public static void main(String[] args) throws IOException {
        File file = new File("d:"+File.separator+"text.txt");
//        Writer writer = new FileWriter(file);
        Writer writer = new FileWriter(file,true);     //文件内容追加与字节流相同
        String str = "\r\nzhangyang";
        writer.write(str);        //直接输入字符串,不需要进行转换
        writer.close();
        
        Reader reader = new FileReader(file);
        char c[] = new char[(int)file.length()];       //这里是将内容读取到字符数组
        reader.read(c);
        reader.close();
        System.out.println(new String(c));
    }
}


五、转换流——OutputStreamWriter和InputStreamReader

在整个 IO 包中,实际上就是分为字节流和字符流,但是除了这两个流之外,还存在了一组字节流 - 字符流的转换类。
OutputStreamWriter
          是
Writer 的子类,将输出的字符流变为字节流,
          即:将一个字符流的输出对象变为字节流输出对象。
² InputStreamReader
         是
Reader 的子类,将输入的字节流变为字符流,
         即:将一个字节流的输入对象变为字符流的输入对象。
转换步骤
         
如果以文件操作为例,则在内存中的字符数据需要通过 OutputStreamWriter 变为字节流才能保存在文件之中,读取的时候需要将读入的字节流通过 InputStreamReader 变为字符流。


//将字节输出流变成字符输出流

importjava.io.File;

importjava.io.FileOutputStream;

importjava.io.OutputStreamWriter;

importjava.io.Writer;

publicclass OutputStreamWriterDemo01 {

  publicstaticvoid main(String[]args) throws Exception {// 所有的异常抛出

  File f = new File("d:" +File.separator +"test.txt");

  Writerout = null;

  out= newOutputStreamWriter(newFileOutputStream(f));// 字节流变为字符流

  out.write("hello world");  // 使用字符流输出

  out.close();

  }

}



//将字节输入流变成字符输入流



importjava.io.File;

importjava.io.FileInputStream;

importjava.io.InputStreamReader;

importjava.io.Reader;

publicclass InputStreamReaderDemo01 {

  publicstaticvoid main(String[]args) throws Exception {// 所有的异常抛出

  File f = new File("d:" +File.separator +"test.txt");

  Readerreader =null;

  reader= newInputStreamReader(newFileInputStream(f));// 将字节流变为字符流

  char c[] =newchar[1024];

  intlen =reader.read(c);

  reader.close();

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

  }

}

六、对象序列化

1.基本概念与Serializable接口

对象序列化,就是把一个对象变为二进制的数据流的一种方法,通过对象序列化可以方便的实现对象的传输或存储。

如果一个类的对象想被序列化,则对象所在的类必须实现 java.io.Serializable 接口
此接口定义如下:
public interface Serializable {}

//定义可序列化类

importjava.io.Serializable;

publicclass PersonimplementsSerializable {  // 此类的对象可以被序列化

  private Stringname// 声明name属性

  privateintage// 声明age属性

  public Person(String name,int age) {  // 通过构造方法设置属性内容

  this.name = name;

  this.age = age;

  }

  public StringtoString() {  // 覆写toString()方法

  return"姓名:" +this.name +";年龄:" +this.age;

  }

}


要想完成对象的输入或输出,还必须依靠对象输出流( ObjectOutputStream )和对象输入流( ObjectInputStream
使用对象输出流输出序列化对象的步骤,有时也称为序列化,而使用对象输入流读入对象的过程,有时也称为反序列化


对象输出流: ObjectOutputStream

一个对象如果要想进行输出,则必须使用 ObjectOutputStream
此类定义如下:
                      public class ObjectOutputStream
                      extends
OutputStream
                      implements
ObjectOutput , ObjectStreamConstants
 
                                                                                         表7  此类常用方法

No.

方法或常量

类型

描述

1

public ObjectOutputStream(OutputStream out) throws IOException

构造

传入输出的对象

2

public final void writeObject(Object obj) throws IOException

普通

输出对象



对象输入流:ObjectInputStream

使用 ObjectInputStream 可以直接把被序列化好的对象反序列化回来
ObjectInputStream 的定义如下:

                                    public class
ObjectInputStream
                                    extends
InputStream
                                     implements
ObjectInput , ObjectStreamConstants

                                                                                                     表8:此类常用方法

No.

方法或常量

类型

描述

1

public ObjectInputStream(InputStream in) throws IOException

构造

构造输入对象

2

public final Object readObject() throws IOException, ClassNotFoundException

普通

从指定位置读取对象



//以下给出具体实现代码


import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;

/*
 * 对象序列化:把一个对象变为二进制的数据流存储
 * 被序列化的类要实现 java.io.Serializable 接口
 * 还必须依靠对象输出流 (ObjectOutputStream)和对象输入流 (ObjectInputStream)
 * 并且对象输入流输出流  的构造方法 参数为 输出流  输入流对象 ,OutputStream和InputStream的 对象
 */

public class ObjectStreamDemo {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        File file = new File("d:"+File.separator+"text.txt");
        OutputStream out = new FileOutputStream(file);      //文件输出流
        ObjectOutputStream oos = new ObjectOutputStream(out);   //实例化对象
        oos.writeObject(new person("张三", "12"));    //保存对象到文件
        oos.writeObject(new person("李四", "11"));
        oos.close();              //关闭输出
        
        InputStream in = new FileInputStream(file);
        ObjectInputStream ois = new ObjectInputStream(in);
        Object o = ois.readObject();

        ois.close();
        System.out.println(o);
        
    }
}
class person implements Serializable{

    /**
     *
     */
    private static final long serialVersionUID = 1L;
    private String name;
    private String age;
    @Override
    public String toString() {
        return "person [name=" + name + ", age=" + age + "]";
    }
    public person(String name, String age) {
        super();
        this.name = name;
        this.age = age;
    }
}



import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;

/*
 * 序列化多个文件:
 * 使用对象数组保存多个对象
 */

public class ObjectStreamDemo1 {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        Student s[] = {new Student("战三", 19),new Student("lis ", 19)};
        ser(s);
        Object o[] = dlser();
        for (int i = 0; i < o.length; i++) {
            Student student = (Student)o[i];
            System.out.println(student);
        }
        
    }
    public static void ser(Object o[]) throws IOException{
        File file = new File("d:"+File.separator+"text.txt");
        OutputStream out = new FileOutputStream(file);
        ObjectOutputStream oos = new ObjectOutputStream(out);
        oos.writeObject(o);
        oos.close();
        
    }
    public static Object[] dlser() throws IOException, ClassNotFoundException{
        File file = new File("d:"+File.separator+"text.txt");
        InputStream in = new FileInputStream(file);
        ObjectInputStream ois = new ObjectInputStream(in);
        Object o[] = (Object[])ois.readObject();
        ois.close();
        return o;
    }
}
class Student implements Serializable{

    /**
     *
     */

    private static final long serialVersionUID = 1L;
    private String name;
    private int age;
    @Override
    public String toString() {
        return "Student [name=" + name + ", age=" + age + "]";
    }
    public Student(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
}



Externalizable接口与Serializable接口实现序列化的区别 

No.

区别

Serializable

Externalizable

1

实现复杂度

实现简单,Java对其有内建支持

实现复杂,由开发人员自己完成

2

执行效率

所有对象由JAVA统一保存,性能较低

开发人员决定那个对象保存,可能的速度提升

3

保存信息

保存时占用空间大

部分存储,可能的空间减少


transient关键字

当使用 Serializable 接口实现序列化操作时,如果一个对象中的某个属性不希望被序列化的话,则可以使用 transient 关键字进行声明

例如: Student中name不想被序列化

class Student implements Serializable{

    /**
     *
     */

    private static final long serialVersionUID = 1L;
    private transientString name;
    private int age;
    @Override
    public String toString() {
        return "Student [name=" + name + ", age=" + age + "]";
    }
    public Student(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }
}
 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值