文件流

作者: 提笔忘字_波 | 来源:发表于2019-05-09 14:02 被阅读0次

    https://www.cnblogs.com/xdp-gacl/p/3634409.html

    一、文件流的应用

    使用FileInputStream流来读取FileInputStream.java文件的内容

    package cn.galc.test;
    
    import java.io.*;
    
    public class TestFileInputStream {
        public static void main(String args[]) {
            int b = 0;// 使用变量b来装调用read()方法时返回的整数
            FileInputStream in = null;
            // 使用FileInputStream流来读取有中文的内容时,读出来的是乱码,因为使用InputStream流里面的read()方法读取内容时是一个字节一个字节地读取的,而一个汉字是占用两个字节的,所以读取出来的汉字无法正确显示。
            // FileReader in = null;//使用FileReader流来读取内容时,中英文都可以正确显示,因为Reader流里面的read()方法是一个字符一个字符地读取的,这样每次读取出来的都是一个完整的汉字,这样就可以正确显示了。
            try {
                in = new FileInputStream("D:\\Java\\MyEclipse 10\\Workspaces\\AnnotationTest\\src\\cn\\galc\\test\\FileInputStream.java");
                // in = new FileReader("D:/java/io/TestFileInputStream.java");
            } catch (FileNotFoundException e) {
                System.out.println("系统找不到指定文件!");
                System.exit(-1);// 系统非正常退出
            }
            long num = 0;// 使用变量num来记录读取到的字符数
            try {// 调用read()方法时会抛异常,所以需要捕获异常
                while ((b = in.read()) != -1) {
                    // 调用int read() throws Exception方法时,返回的是一个int类型的整数
                    // 循环结束的条件就是返回一个值-1,表示此时已经读取到文件的末尾了。
                    // System.out.print(b+"\t");//如果没有使用“(char)b”进行转换,那么直接打印出来的b就是数字,而不是英文和中文了
                    System.out.print((char) b);
                    // “char(b)”把使用数字表示的汉字和英文字母转换成字符输入
                    num++;
                }
                in.close();// 关闭输入流
                System.out.println();
                System.out.println("总共读取了" + num + "个字节的文件");
            } catch (IOException e1) {
                System.out.println("文件读取错误!");
            }
        }
    }
    

    使用FileOutputStream流往一个文件里面写入数据

    package cn.galc.test;
    import java.io.*;
    public class TestFileOutputStream {
        public static void main(String args[]) {
            int b = 0;
            FileInputStream in = null;
            FileOutputStream out = null;
            try {
                in = new FileInputStream("D:\\Java\\MyEclipse 10\\Workspaces\\AnnotationTest\\src\\cn\\galc\\test\\MyMouseAdapter.java");
                out = new FileOutputStream("D:/java/TestFileOutputStream1.java");
                // 指明要写入数据的文件,如果指定的路径中不存在TestFileOutputStream1.java这样的文件,则系统会自动创建一个
                while ((b = in.read()) != -1) {
                    out.write(b);
                    // 调用write(int c)方法把读取到的字符全部写入到指定文件中去
                }
                in.close();
                out.close();
            } catch (FileNotFoundException e) {
                System.out.println("文件读取失败");
                System.exit(-1);// 非正常退出
            } catch (IOException e1) {
                System.out.println("文件复制失败!");
                System.exit(-1);
            }
            System.out
                    .println("TestFileInputStream.java文件里面的内容已经成功复制到文件TestFileOutStream1.java里面");
        }
    }
    

    FileInputStream和FileOutputStream这两个流都是字节流,都是以一个字节为单位进行输入和输出的。所以对于占用2个字节存储空间的字符来说读取出来时就会显示成乱码。
    使用FileWriter(字符流)向指定文件中写入数据

    package cn.galc.test;
    /*使用FileWriter(字符流)向指定文件中写入数据
    写入数据时以1个字符为单位进行写入*/
    import java.io.*;
    public class TestFileWriter{
        public static void main(String args[]){
            /*使用FileWriter输出流从程序把数据写入到Uicode.dat文件中
            使用FileWriter流向文件写入数据时是一个字符一个字符写入的*/
            FileWriter fw = null;
            try{
                    fw = new FileWriter("D:/java/Uicode.dat");
                    //字符的本质是一个无符号的16位整数
                    //字符在计算机内部占用2个字节
                    //这里使用for循环把0~60000里面的所有整数都输出
                    //这里相当于是把全世界各个国家的文字都0~60000内的整数的形式来表示
                    for(int c=0;c<=60000;c++){
                        fw.write(c);
                        //使用write(int c)把0~60000内的整数写入到指定文件内
                        //调用write()方法时,我认为在执行的过程中应该使用了“(char)c”进行强制转换,即把整数转换成字符来显示
                        //因为打开写入数据的文件可以看到,里面显示的数据并不是0~60000内的整数,而是不同国家的文字的表示方式
                }
                /*使用FileReader(字符流)读取指定文件里面的内容
                读取内容时是以一个字符为单位进行读取的*/
                    int b = 0;
                    long num = 0;
                    FileReader fr = null;
                    fr = new FileReader("D:/java/Uicode.dat");
                    while((b = fr.read())!= -1){
                        System.out.print((char)b + "\t");
                        num++;
                    }
                    System.out.println();
                    System.out.println("总共读取了"+num+"个字符");
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    }
    

    二、处理流讲解

    2.1 第一种处理流——缓冲流(Buffering)

    package cn.gacl.test;
    import java.io.*;
    public class TestBufferStream {
        public static void main(String args[]) {
            FileInputStream fis = null;
            try {
                fis = new FileInputStream("D:/java/TestFileInputStream.java");
                // 在FileInputStream节点流的外面套接一层处理流BufferedInputStream
                BufferedInputStream bis = new BufferedInputStream(fis);
                int c = 0;
                System.out.println((char) bis.read());
                System.out.println((char) bis.read());
                bis.mark(100);// 在第100个字符处做一个标记
                for (int i = 0; i <= 10 && (c = bis.read()) != -1; i++) {
                    System.out.print((char) c);
                }
                System.out.println();
                bis.reset();// 重新回到原来标记的地方
                for (int i = 0; i <= 10 && (c = bis.read()) != -1; i++) {
                    System.out.print((char) c);
                }
                bis.close();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (Exception e1) {
                e1.printStackTrace();
            }
        }
    }
    
    package cn.gacl.test;
    
    import java.io.*;
    public class TestBufferStream1{
        public static void main(String args[]){
            try{
            BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\java\\dat.txt"));
                //在节点流FileWriter的外面再套一层处理流BufferedWriter
                String s = null;
                for(int i=0;i<100;i++){
                    s = String.valueOf(Math.random());//“Math.random()”将会生成一系列介于0~1之间的随机数。
                    // static String valueOf(double d)这个valueOf()方法的作用就是把一个double类型的数转换成字符串
                    //valueOf()是一个静态方法,所以可以使用“类型.静态方法名”的形式来调用 
                    bw.write(s);//把随机数字符串写入到指定文件中
                    bw.newLine();//调用newLine()方法使得每写入一个随机数就换行显示
                }
                bw.flush();//调用flush()方法清空缓冲区
                
            BufferedReader br = new BufferedReader(new FileReader("D:/java/dat.txt"));
                    //在节点流FileReader的外面再套一层处理流BufferedReader
                while((s = br.readLine())!=null){
                    //使用BufferedReader处理流里面提供String readLine()方法读取文件中的数据时是一行一行读取的
                    //循环结束的条件就是使用readLine()方法读取数据返回的字符串为空值后则表示已经读取到文件的末尾了。
                    System.out.println(s);
                }
            bw.close();
            br.close();
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    }
    

    2.2 第二种处理流——转换流

    转换流非常的有用,它可以把一个字节流转换成一个字符流,转换流有两种,一种叫InputStreamReader,另一种叫OutputStreamWriter。InputStream是字节流,Reader是字符流,InputStreamReader就是把InputStream转换成Reader。OutputStream是字节流,Writer是字符流,OutputStreamWriter就是把OutputStream转换成Writer。把OutputStream转换成Writer之后就可以一个字符一个字符地通过管道写入数据了,而且还可以写入字符串。我们如果用一个FileOutputStream流往文件里面写东西,得要一个字节一个字节地写进去,但是如果我们在FileOutputStream流上面套上一个字符转换流,那我们就可以一个字符串一个字符串地写进去。

    package cn.gacl.test;
    
    import java.io.*;
    
    public class TestTransform1 {
        public static void main(String args[]) {
            try {
                OutputStreamWriter osw = new OutputStreamWriter(
                        new FileOutputStream("D:/java/char.txt"));
                osw.write("MircosoftsunIBMOracleApplet");// 把字符串写入到指定的文件中去
                System.out.println(osw.getEncoding());// 使用getEncoding()方法取得当前系统的默认字符编码
                osw.close();
                osw = new OutputStreamWriter(new FileOutputStream(
                        "D:\\java\\char.txt", true), "ISO8859_1");
                // 如果在调用FileOutputStream的构造方法时没有加入true,那么新加入的字符串就会替换掉原来写入的字符串,在调用构造方法时指定了字符的编码
                osw.write("MircosoftsunIBMOracleApplet");// 再次向指定的文件写入字符串,新写入的字符串加入到原来字符串的后面
                System.out.println(osw.getEncoding());
                osw.close();
    
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    
    package cn.gacl.test;
    
    import java.io.*;
    public class TestTransform2{
        public static void main(String args[]){
            try{
                InputStreamReader isr = new InputStreamReader(System.in);
                //System.in这里的in是一个标准的输入流,用来接收从键盘输入的数据
                BufferedReader br = new BufferedReader(isr);
                String s = null;
                s = br.readLine();//使用readLine()方法把读取到的一行字符串保存到字符串变量s中去
                while(s != null){
                    System.out.println(s.toUpperCase());//把保存在内存s中的字符串打印出来
                    s = br.readLine();//在循环体内继续接收从键盘的输入
                    if(s.equalsIgnoreCase("exit")){
                        //只要输入exit循环就结束,就会退出
                        break;
                    }
                }
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    }
    

    2.3 第三种处理流——数据流

    package cn.gacl.test;
    
    import java.io.*;
    public class TestDataStream{
        public static void main(String args[]){
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            //在调用构造方法时,首先会在内存里面创建一个ByteArray字节数组
            DataOutputStream dos = new DataOutputStream(baos);
            //在输出流的外面套上一层数据流,用来处理int,double类型的数
            try{
                dos.writeDouble(Math.random());//把产生的随机数直接写入到字节数组ByteArray中
                dos.writeBoolean(true);//布尔类型的数据在内存中就只占一个字节
            ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
                System.out.println(bais.available());
                DataInputStream dis = new DataInputStream(bais);
                System.out.println(dis.readDouble());//先写进去的就先读出来,调用readDouble()方法读取出写入的随机数
                System.out.println(dis.readBoolean());//后写进去的就后读出来,这里面的读取顺序不能更改位置,否则会打印出不正确的结果
                dos.close();
                bais.close();
            }catch(Exception e){
                    e.printStackTrace();
                }
        }
    }
    

    通过bais这个流往外读取数据的时候,是一个字节一个字节地往外读取的,因此读出来的数据无法判断是字符串还是bool类型的值,因此要在它的外面再套一个流,通过dataInputStream把读出来的数据转换就可以判断了。注意了:读取数据的时候是先写进去的就先读出来,因此读ByteArray字节数组数据的顺序应该是先把占8个字节的double类型的数读出来,然后再读那个只占一个字节的boolean类型的数,因为double类型的数是先写进数组里面的,读的时候也要先读它。这就是所谓的先写的要先读。如果先读Boolean类型的那个数,那么读出来的情况可能就是把double类型数的8个字节里面的一个字节读了出来。

    2.4 打印流——Print

    package cn.gacl.test;
    
    /*这个小程序是重新设置打印输出的窗口,
     * 把默认在命令行窗口输出打印内容设置成其他指定的打印显示窗口
     */
    import java.io.*;
    public class TestPrintStream{
        public static void main(String args[]){
            PrintStream ps = null;
            try{
                    FileOutputStream fos = new FileOutputStream("D:/java/log.txt");
                    ps = new PrintStream(fos);//在输出流的外面套接一层打印流,用来控制打印输出
                    if(ps != null){
                        System.setOut(ps);//这里调用setOut()方法改变了输出窗口,以前写System.out.print()默认的输出窗口就是命令行窗口.
                        //但现在使用System.setOut(ps)将打印输出窗口改成了由ps指定的文件里面,通过这样设置以后,打印输出时都会在指定的文件内打印输出
                        //在这里将打印输出窗口设置到了log.txt这个文件里面,所以打印出来的内容会在log.txt这个文件里面看到
                    }
                for(char c=0;c<=60000;c++){
                        System.out.print(c+"\t");//把世界各国的文字打印到log.txt这个文件中去
                    }
            }catch(Exception e){
                e.printStackTrace();
            }
        }
    }
    

    2.5 对象流——Object

    package cn.gacl.test;
    
    import java.io.*;
    
    public class TestObjectIo {
        public static void main(String args[]) {
            T t = new T();
            t.k = 8;// 把k的值修改为8
            try {
                FileOutputStream fos = new FileOutputStream(
                        "D:/java/TestObjectIo.txt");
                ObjectOutputStream oos = new ObjectOutputStream(fos);
                // ObjectOutputStream流专门用来处理Object的,在fos流的外面套接ObjectOutputStream流就可以直接把一个Object写进去
                oos.writeObject(t);// 直接把一个t对象写入到指定的文件里面
                oos.flush();
                oos.close();
                FileInputStream fis = new FileInputStream(
                        "D:/java/TestObjectIo.txt");
                ObjectInputStream ois = new ObjectInputStream(fis);
                // ObjectInputStream专门用来读一个Object的
                T tRead = (T) ois.readObject();
                // 直接把文件里面的内容全部读取出来然后分解成一个Object对象,并使用强制转换成指定类型T
                System.out.print(tRead.i + "\t" + tRead.j + "\t" + tRead.d + "\t"
                        + tRead.k);
                ois.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    
    /*
     * 凡是要将一个类的对象序列化成一个字节流就必须实现Serializable接口
     * Serializable接口中没有定义方法,Serializable接口是一个标记性接口,用来给类作标记,只是起到一个标记作用。
     * 这个标记是给编译器看的,编译器看到这个标记之后就可以知道这个类可以被序列化 如果想把某个类的对象序列化,就必须得实现Serializable接口
     */
    class T implements Serializable {
        // Serializable的意思是可以被序列化的
        int i = 10;
        int j = 9;
        double d = 2.3;
        int k = 15;
        // transient int k = 15;
        // 在声明变量时如果加上transient关键字,那么这个变量就会被当作是透明的,即不存在。
    }
    

    相关文章

      网友评论

          本文标题:文件流

          本文链接:https://www.haomeiwen.com/subject/xfjwoqtx.html