Java I/O

课程  Java面向对象程序设计

一、实验目的

掌握数据流的使用

二、实验环境

1微型计算机一台 

2WINDOWS操作系统,Java SDK,Eclipse开发环境

三、实验内容 

1、掌握FileInputStream、FileOutStream、FileReader、FileWriter的使用,并编写程序,实现数据的输入和输出。

2、掌握BufferedInputStream、BufferedOutputStream、BufferedReader、BufferedWriter的使用,并编写程序,实现数据的输入和输出。

3、掌握InputStreamReader、OutputStreamWriter的使用,并编写程序,实现数据的输入和输出。

4、掌握DataInputStream、DataOutputStream的使用,并编写程序,实现数据的输入和输出。

5、掌握PrintStream、PrintWriter的使用,并编写程序,实现数据的输入和输出。

6、掌握ObjectInputStream、ObjectOutputStream的使用,并编写程序,实现数据的输入和输出。

四、实验步骤和结果

   1、掌握FileInputStream、FileOutStream、FileReader、FileWriter的使用,并编写程序,实现数据的输入和输出。

     以上这四个类是属于文件流,文件流是指那些专门用于操作数据源中的文件的流。下面根据它们读写数据时的操作单位,分成两组。

   (1)FileInputStream和FileOutputStream是以字节为操作单位的文件输入流和文件输出流。利用这两个类可以对文件进行读写操作。

    ① 使用FileInputStream类来读取指定文件的数据:

     编写代码(FileInputStreamTest.java)如下:

package FileStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
//使用FileInputStream类来读取数据源中的数据
public class FileInputStreamTest {
    public static void main(String[] args) {
        FileInputStream fin=null;
        try {
            //step1:创建一个连接到指定文件的FileInputStream对象
            fin=new FileInputStream("D:\IOTest\source.txt");
            System.out.println("可读取的字节数:"+fin.available()+"字节");
            //step2:读数据:一次读取一个字节的数据,返回的是读到的字节
            int i=fin.read();
            while (i!=-1) {  //若遇到流的末尾,会返回-1
                System.out.print((char)i);
                i=fin.read(); //再读
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }catch (IOException e) {  //捕获I/O异常
            e.printStackTrace();
        }finally{
            try {//关闭输入流
                if (null!=fin) {
                    fin.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

  其中,“D:IOTestsource.txt”文件的内容如下:

 

运行以上这个程序,在控制台的输出结果为:

 

可以看到,输出结果中中文字符会乱码,因为一个中文字符是由两个字节编码的。

  ② 使用FileOutputStream类往指定文件中写入数据:

     编写代码(FileOutputStreamTest.java)如下:

package FileStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/*使用FileOutputStream类往指定文件中写入数据*/
public class FileOutputStreamTest {
    public static void main(String[] args) {
        FileOutputStream out=null;
        try {
            //Step1:创建一个向指定名的文件中写入数据的FileOutputStream
            //第二个参数设置为true表示:使用追加模式添加字节
            out=new FileOutputStream("D:\IOTest\shenxiaolin.txt",true);
            //Step2:写数据
            out.write('#');
            out.write("105032013120_沈".getBytes());
            out.write("Hello World 你好".getBytes());
            //Step3:刷新输出流
            out.flush();
        } catch (FileNotFoundException e) {
                e.printStackTrace();
        }catch (IOException e) { //捕获IO异常
            e.printStackTrace();
        }finally{
            if (out!=null) {
                try {
                    out.close(); //Step:4:关闭输出流
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

运行这个程序后,可以在D:IOTest看到有一个“shenxiaolin.txt”的文件存在,它的内容如下:

 

(2)FileReader和FileWriter是以字符为操作单位的文件输入流和文件输出流。因此,FileReader和FileWriter适合用来操作字符文本文件。

  如下代码示例(FileReaderAndFileWriterTest.java)实现复制字符文本文件复制的功能:

package FileStream;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class FileReaderAndFileWriterTest {
//用 FileReaderAndFileWriter实现复制字符文本文件复制的功能
    /**     * @param arg */
    public static void main(String[] args) {
        FileReader fr=null;
        FileWriter fw=null;
        int c=0;
        try {
            //创建I/O流对象
            fr=new FileReader("D:\IOTest\shenxiaolin.txt");
            fw=new FileWriter("D:\IOTest\shenxiaolin2.txt");
            while ((c=fr.read())!=-1) {//从源文件中读取字符
                fw.write(c);
            }
            fw.flush();//刷新输出流
        } catch (FileNotFoundException e) {
              e.printStackTrace();
        }catch (IOException e) {
            e.printStackTrace();
        }finally{
            //关闭所有的I/O流对象
            try {
                if (null!=fw) {
                    fw.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (null!=fr) {
                    fr.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

}

运行上述程序后,在D:IOTest目录下新产生一个shenxiaolin2.txt的文件,其内容与shenxialoin.txt的内容完全相同。结果如下截图所示:

 

 2、掌握BufferedInputStream、BufferedOutputStream、BufferedReader、BufferedWriter的使用,并编写程序,实现数据的输入和输出。

  (1)BufferedInputStream和BufferedOutputStream:是针对字节的缓冲输入和输出流。

以下代码(BufferedInputStreamAndBufferedOutputStreamTest.java)是用

BufferedInputStream和BufferedOutputStream实现字节文本文件复制的功能:

package FileStream;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class BufferedInputStreamAndBufferedOutputStreamTest {
    public static void main(String[] args) {
        BufferedInputStream bfiStream=null;
        BufferedOutputStream bfoStream=null;
        try {
            bfiStream=new BufferedInputStream(new FileInputStream("D:\IOTest\source.txt"));
            bfoStream=new BufferedOutputStream(new FileOutputStream("D:\IOTest\shenxiaolinbuffOutStream.txt"));
            int i;
            while ((i=bfiStream.read())!=-1) {
                bfoStream.write((char)i);
            }
            bfoStream.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                if (bfoStream!=null) {
                    bfoStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if(null!=bfiStream){
                    bfiStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

 运行上述程序后,在D:IOTest目录下新产生一个

shenxiaolinbuffOutStream.txt的文件,其内容与source.txt的内容完全相同。结果如下截图所示:

(2)BufferedReader和BufferedWriter:是针对字符的缓冲输入和输出流。

 以下代码(BufferedReaderAndBufferedWriterTest.java)是用

BufferedReader和BufferedWriter实现字符文本文件复制的功能:

package FileStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
//用BufferedReader和BufferedWriter实现字符文本文件复制的功能:
public class BufferedReaderAndBufferedWriterTest {
    public static void main(String[] args) {
        BufferedReader br=null;
        BufferedWriter bw=null;
        try {
          //创建缓冲流对象:它是过滤流,是对节点流的包装
            br=new BufferedReader(new FileReader("D:\IOTest\source.txt"));
            bw=new BufferedWriter(new FileWriter("D:\IOTest\shenxiaolinBF.txt"));
            String str=null;
            while ((str=br.readLine())!=null) {
                //一次性读取字符文本文件的一行字符
                bw.write(str);//一次写入一行字符串
                bw.newLine();//写入行分隔符                
            }
            bw.flush();//刷新缓冲区
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            //关闭I/O流对象
            try {
                if (null!=bw) {
                    bw.close();//关闭过滤流时,会自动关闭它所包装的底层节点流
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

运行上述程序后,在D:IOTest目录下新产生一个shenxiaolinBF.txt的文件,其内容与source.txt的内容完全相同。结果如下截图所示:

 

   3、掌握InputStreamReader、OutputStreamWriter的使用,并编写程序,实现数据的输入和输出。

(1)InputStreamReader用于将字节流中读取到的字节按指定字符集解码成字符。它需要与InputStream“套接”。

  以下(InputStreamReaderByteToCharTest.java)是使用InputStreamReader将字节输入流转换成字符输入流:

package FileStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class InputStreamReaderByteToCharTest {
        public static void main(String[] args) {
        System.out.println("请输入信息(退出请输入e或者exit):");
        //把“标准”输入流(键盘输入)这个字节流包装成字符流,再包装成缓冲流
        BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
        String s=null;
        try {
            while ((s=br.readLine())!=null) {
                //读取用户输入的一行数据-->阻塞程序
                if (s.equalsIgnoreCase("e")||s.equalsIgnoreCase("exit")) {
                    System.out.println("安全退出!");
                    break;
                }
                //将读取到的整行字符串转成大写输出
                System.out.println("-->:"+s.toUpperCase());
                System.out.println("继续输入信息");                
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                if (null!=br) {
                    br.close();//关闭过滤流时,会自动关闭它包装的底层节点流
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

运行程序,结果如下所示:

 

(2)OutputStreamWriter用于将要写入到字节流中的字符按指定字符集解码成字节。它需要与OutputStream“套接”。

以下(OutputStreamWriterCharToByteTest.java)是使用OutputStreamWriter将字符输入流转换成字节输入流:

package FileStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
public class OutputStreamWriterCharToByteTest {
    public static void main(String[] args) {
        System.out.println("请输入信息:");
            BufferedReader bufr1=new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bufw1=new BufferedWriter(new OutputStreamWriter(System.out));
        String line1=null;
        try {
            while ((line1=bufr1.readLine())!=null) {
                if ("over".equals(line1))   break;
                bufw1.write(line1.toUpperCase());
                bufw1.newLine();
                bufw1.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                if (null!=bufw1) {
                    bufw1.close();
                }
            } catch (Exception e2) {
                e2.printStackTrace();
            }
           try {
                if (null!=bufr1) {
                   bufr1.close();
               }
           } catch (Exception e2) {
              e2.printStackTrace();
            }
        }
    }
}

运行结果如下所示:

 

   4、掌握DataInputStream、DataOutputStream的使用,并编写程序,实现数据的输入和输出。

 (1)DataInputStream 用来读取基本数据类型的数据:

以下代码(DataInputStreamAndDataOutputStreamTest.java)是数据流在内存中的使用示例:

package FileStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.IOException;
//数据流在内存中的使用示例
import java.io.DataOutputStream;
public class DataInputStreamAndDataOutputStreamTest {
    public static void main(String[] args) {
        ByteArrayOutputStream baos=new ByteArrayOutputStream();
        DataOutputStream dos=new DataOutputStream(baos);
        try {
            dos.writeDouble(Math.random());
            dos.writeBoolean(true);
            dos.writeChars("shenxiaolin|Java|	");
            dos.writeUTF("沈");
            ByteArrayInputStream bais=new ByteArrayInputStream(baos.toByteArray());
            System.out.println("可读取的字节数是:"+bais.available());
            DataInputStream dis=new DataInputStream(bais);
            System.out.println(dis.readDouble());
            System.out.println(dis.readBoolean());
            char[] temp=new char[200];
            //开辟空间200
            int len=0;
            char c=0;
            while ((c=dis.readChar())!='	') {
                //读取字符
                temp[len] = c;
                len++;
            }
            String name=new String(temp,0,len);
            System.out.println(name);
            System.out.println(dis.readUTF());
            dos.close();
            dis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

运行结果如下所示:

 

 (2)DataOutputStream 用来写出基本数据类型的数据,以下代码是数据流在文件中的使用示例:( DataOutputStreamTest.java)

package FileStream;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class DataOutputStreamTest {
    public static void main(String[] args) {
        DataOutputStream dos=null;
        try {
            //创建连接到指定文件的数据输出流对象
            dos=new DataOutputStream(new  FileOutputStream("D:\IOTest\testData.dat"));
            dos.writeUTF("china中国"); //写入UTF字符串
            dos.writeBoolean(false); //写入布尔值
            dos.writeLong(123456789L);//写入长整数
            System.out.println("写文件成功!");                
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            try {
                if (null!=dos) {
                    dos.close(); //关闭过滤流时,会自动关闭它包装的底层节点流
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

运行这个程序后,在D:\IOTest目录下会产生一个testData.dat文件,用记事本打开这个文件,显示的内容如下:

 

   5、掌握PrintStream、PrintWriter的使用,并编写程序,实现数据的输入和输出。

PrintStream和PrintWriter都属于打印流,提供了一系列的print和println方法,可以实现将基本数据类型的数据格式转化成字符串输出。PrintStream和PrintWriter的输出操作可能不会抛出IOException异常。

(1)以下代码(PrintStreamTest.java )是演示打印流PrintStream的使用:

package FileStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
//把标准的输出改成指定的文件输出
public class PrintStreamTest {
    public static void main(String[] args) {
        FileOutputStream fos=null;
        try {
            fos=new FileOutputStream(new File("D:\IOTest\text.txt"));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        //创建打印输出流,设置为自动刷新模式(写入换行符或字节'
'时都会刷新输出缓冲区)
        PrintStream ps=new PrintStream(fos,true);
        if (ps!=null) {
            //把标准输出流(控制台输出)改成文件
            System.out.println(ps);
        }
        for (int i = 0; i <= 255; i++) { //输出ASCII字符
            System.out.print((char)i);
            if (i%50==0) {
                System.out.println(); //换行
            }
        }
        ps.close();
    }
}

运行这个程序后,会在D:IOTest目录下产生一个text.txt文件,文件的内容如下截图所示:

 

(2)PrintStream只能封装OutputStream类型的字节流,而PrintWriter既可以封装OutputStream,还能够封装Writer类型字符输出流并增强其功能。并且它提供了PrintStream的所有打印方法,这些方法也从不抛出IOException。

以下代码(PrintWriterTest.java)演示PrintWriter的用法:

  package FileStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.io.PrintWriter;
public class PrintWriterTest {
    public static void main(String[] args) {
        String str="Hello ! PrintWriter!";
        try {
            PrintWriter pw=new PrintWriter(new FileOutputStream("D:\IOTest\textPrintWriter.txt"));
            pw.println(str);
            pw.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}                 

运行这个程序后,会在D:IOTest目录下产生一个textPrintWriter.txt文件,文件的内容如下截图所示:

 

   6、掌握ObjectInputStream、ObjectOutputStream的使用,并编写程序,实现数据的输入和输出。

ObjectInputStream类是用于存储和读取基本类型数据或对象的过滤流,它最强大之处就是可以把Java中的对象写到数据源中,也能把对象从数据源中还原回来。用ObjectOutputStream类保存基本类型数据或对象的机制叫作序列化;用ObjectInputStream类读取基本数据类型或对象的机制叫作反序列化。ObjectOutputStream和ObjectInputStream不能序列化static或transient修饰的成员变量。而且需要注意:能被序列化的对象所对应的类必须实现java.io.Serializable这个标识性接口。

(1)定义一个可序列化的Student类。代码(Student.java)如下:

package FileStream;
//可序列化的Student类
public class Student  implements java.io.Serializable{
    private int id;
    private String name;
    private transient int age; //不需要序列化的属性
    public int getId() {  return id;     }
    public String getName() { return name;    }
    public int getAge() {    return age;    }

    public Student(int id, String name, int age) {
        super();
        this.id = id;
        this.name = name;
        this.age = age;
    }
    public String toString() {
        return "Student [id=" + id + ", name=" + name + ", age=" + age + "]";
    }
}

(2)接下来创建一个学生对象,并把它序列化到一个文件(objectSeri.dat)中。

代码(SerializationTest.java)如下所示:

package FileStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
//创建一个学生对象,并把它序列化到一个文件(objectSeri.dat)中:
public class SerializationTest {
    public static void main(String[] args) {
        ObjectOutputStream oos=null;
        try {
            //创建连接到指定文件的对象输出流实例
            oos=new ObjectOutputStream(new FileOutputStream("D:\IOTest\objectSeri.dat"));
            oos.writeObject(new Student(120, "沈", 20));
            //把stu对象序列化到文件中
            oos.flush();//刷新输出流
            System.out.println("序列化成功!!!");
        } catch (IOException e) {
            e.printStackTrace();
        } finally{
             try {
                if(null!=oos){
                    oos.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

上述程序运行后,在D:IOTest目录下产生一个objectSeri.dat文件,文件的内容如下截图所示:

 

(3)把指定文件中的数据反序列化回来,打印输出它的信息。代码(DeserializationTest.java)如下:

package FileStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
//把指定文件中的数据反序列化回来,打印输出它的信息。
public class DeserializationTest {
    public static void main(String[] args) {
        ObjectInputStream ois=null;
        try {
            //创建连接到指定文件的对象输入流实例
            ois=new ObjectInputStream(new FileInputStream("D:\IOTest\objectSeri.dat"));
            Student stu=(Student)ois.readObject();//读取对象
            System.out.println(stu);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }catch (IOException e) {
            e.printStackTrace();
        }finally{
           try {
            if (null!=ois) {
                ois.close();//关闭
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        }
    }
}

程序的运行结果如下:

 

从运行结果来看,读取出来的数据中age的值丢了,这是因为它是用transient修饰的,它的值根本没序列化到文件中。

五、实验总结

  1.本次实验按时按量完成。

  2.在Java编程中,I/O系统主要负责文件的读写。在运行程序时,Java I/O程序将源磁盘、文件或网络上的数据通过输入流类的相应方法读入内存,然后通过输出流类的相应方法将处理完的数据写回目标文件、磁盘或网络资源指定的位置。I/O系统类库位于java.io包中,提供了全面的I/O接口,包括文件读写、标准设备输出等。Java中I/O是以流为基础进行输入输出的,所有数据被串行化写入输出流,或者从输入流读入。

  3.InputStream抽象类是表示字节输入流的所有类的超类,它以字节为单位从数据源中读取数据。

  OutputStream抽象类是表示字节输出流的所有类的超类,它以字节为单位向数据源写出数据。

 Reader抽象类是表示字符输入流的所有类的超类,它以字符为单位从数据源中读取数据。

 Writer抽象类是表示字符输出流的所有类的超类,它以字符为单位向数据源写出数据。

  4.FileInputStream和FileOutputStream是以字节为操作单位的文件输入流和文件输出流。

      FileReader和FileWriter是以字符为操作单位的文件输入流和文件输出流。

  5. BufferedInputStream和BufferedOutputStream:针对字节的缓冲输入和输出流。BufferedReader和BufferedWriter:针对字符的缓冲输入和输出流。

  6.InputStreamReader用于将字节流中读取到的字节按指定字符集解码成字符。OutputStreamWriter用于将要写入到字节流中的字符按指定字符集编码成字节。

  7.DataOutputStream对输出管道进行套接,然后把一些Java类型的数据写到字节数组中去。DataInputStream对输入管道进行套接,然后可以获取相关的数据内容。

  8.PrintStream和PrintWriter都属于打印流,提供了一系列的print和println方法,可以实现将基本数据类型的数据格式转化成字符串输出。PrintStream和PrintWriter的输出操作可能不会抛出IOException异常。

  9.ObjectInputStream类是用于存储和读取基本类型数据或对象的过滤流,它最强大之处就是可以把Java中的对象写到数据源中,也能把对象从数据源中还原回来。用ObjectOutputStream类保存基本类型数据或对象的机制叫作序列化;用ObjectInputStream类读取基本数据类型或对象的机制叫作反序列化。ObjectOutputStream和ObjectInputStream不能序列化static或transient修饰的成员变量。而且,能被序列化的对象所对应的类必须实现java.io.Serializable这个标识性接口。

 

原文地址:https://www.cnblogs.com/shenxiaolin/p/5040298.html