天天看点

Java IO Basic

Java IO Basic

  • 首先看下关于Java的IO的图:
    Java IO Basic
    我看到这个,感觉头都大了不少。Java的先驱们简直是煞费苦心,来设计Java IO。
    • 字节流
    1.先从文件开始吧
import java.io.File;

/**
 * Created by XYD on 2016/1/4 0004.
 */
public class FileExample {

    public static void main(String[] args){
        FileExample example = new FileExample();
        example.createFile();
    }

    private  void createFile(){
        File f = new File("F:\\f\\2365157.lrc");
        try {
            f.createNewFile();//当文件不存在时,创建文件
            System.out.println("该分区大小"+f.getTotalSpace()/(**)+"G");
            f.mkdirs();//创建指定目录,所有必须但不存在的父目录
            System.out.println("文件名  "+f.getName());
            System.out.println("文件父目录字符串"+f.getParent());
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
           

2.InputStream

import java.io.*;

/**
 * Created by XYD on 2016/1/4 0004.
 * 检测文件的长度
 */
public class FileLength {
    public static void main(String[] args){
        int count=;//统计文件字节长度
        InputStream stream=null;//文件输入流
        try {
            stream = new FileInputStream(new File("F:\\f\\2365157.lrc"));
           //FileInputStream是有缓冲区的,所以用完之后必须关闭,否则可能导致内存占满,数据丢失。
            while (stream.read()!=-){//读取文件字节,并递增指针到下一个字节  
                count++;
            }
            System.out.println("---长度是: "+count+" 字节");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        finally {
            try {
                stream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
           
上面的程序肯定是有问题的,每读一个字节都要用到FileInputStream,如果是300字节,使用300次;如果是30000次,就要进行30000次操作.....想想都有些可怕,如果文件十分庞大的话,这样的做法会出大问题,这样就引出了缓冲区的使用。
可以使用stream.read(byte[] b)来代替stream.read(),这个方法可以一次读取字节数目等于数组长度的字节,**读取的数据存储在字节数组中,并且返回读取的字节数。**
           

3.FileOutputStream

以一个文件复制程序来描述下怎么使用它,同时展示下缓冲区的使用。

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * Created by XYD on 2016/1/4 0004.
 */
public class FileCopy {
    public static void main(String[] args){
        byte[] buffer = new byte[];//缓冲区大小
        int numberRead=;//一次读取的字节数
        FileInputStream input = null;
        FileOutputStream out = null;
        try {
            input=new FileInputStream("F:\\f\\2365157.lrc");
            out=new FileOutputStream("F:\\f\\2365157_copy.lrc");//如果文件不存在会自动创建  
            while ((numberRead=input.read(buffer))!=-){//numberRead的目的在于防止最后一次读取的字节小于buffer长度
                out.write(buffer,,numberRead);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
           

4.读写对象:ObjectInputStream 和ObjectOutputStream

该流允许读取或写入用户自定义的类,但是要实现这种功能,被读取和写入的类必须实现Serializable接口(这个接口里面什么方法都没有,但却是必不可少,奇怪!).

import java.io.*;

/**
 * Created by XYD on 2016/1/4 0004.
 */
public class ObjectStream {
    public static void main(String[] args){
        ObjectOutputStream objectWriter =null;
        ObjectInputStream objectReader=null;

        try {
            objectWriter = new ObjectOutputStream(new FileOutputStream("F:\\f\\2365157_copy.lrc"));
            objectWriter.writeObject(new Student("gg",));
            objectWriter.writeObject(new Student("tt",));
            objectWriter.writeObject(new Student("zz",));

            objectReader = new ObjectInputStream(new FileInputStream("F:\\f\\2365157_copy.lrc"));
            for(int i=;i<;i++){
                System.out.println(objectReader.readObject());
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

class Student implements Serializable{
    private String name;
    private int age;

    public Student(String name , int age){
        super();
        this.name=name;
        this.age=age;
    }

    @Override
    public String toString() {
        return "Student + [ name = "+name+", age = "+age+"]";
    }
}
           

5.DataInputStream、DataOutputStream

有时没有必要存储整个对象的信息,而只是要存储一个对象的成员数据,成员数据的类型假设都是Java的基本数据类型,这样的需求不必使用到与Object输入、输出相关的流对象,可以使用DataInputStream、DataOutputStream来写入或读出数据。

/**
 * Created by XYD on 2016/1/4 0004.
 */
public class Member {

    private String name;
    private int age;

    public Member(String name, int age){
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}
           

打算将Member类实例的成员数据写入文件中,并打算在读入文件数据后,将这些数据还原为Member对象。下面的代码简单示范了如何实现这个需求。

DataInputStream的好处在于在从文件读出数据时,不用费心地自行判断读入字符串时或读入int类型时何时将停止,使用对应的readUTF()和readInt()方法就可以正确地读入完整的类型数据。

import java.io.*;

/**
 * Created by XYD on 2016/1/4 0004.
 */
public class DataStreamDemo {
    public static void main(String[] args){
        Member[] members = {
                new Member("heheda",),
                new Member("dacaibi",),
                new Member("xyd",)};

        try {
            DataOutputStream outputStream = new DataOutputStream(new FileOutputStream("F:\\f\\2365157_copy.lrc"));

            for(Member member:members){
                //写入UTF字符串
                outputStream.writeUTF(member.getName());
                //写入int数据
                outputStream.writeInt(member.getAge());
            }
            //所有数据至目的地(但是我测试了下,并没有什么卵用)
//            outputStream.flush();
            //关闭流
            outputStream.close();

            DataInputStream inputStream = new DataInputStream(new FileInputStream("F:\\f\\2365157_copy.lrc"));
            //读出数据并还原为对象  
            for(int i=;i<members.length;i++){
                String name=inputStream.readUTF();
                int age=inputStream.readInt();
                members[i] = new Member(name,age);
            }
            inputStream.close();
            for(Member member:members){
                System.out.printf("%s\t%d%n", member.getName(), member.getAge());
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
           

6.PushbackInputStream类继承了FilterInputStream类是iputStream类的修饰者。SequenceInputStream:有些情况下,当我们需要从多个输入流中向程序读入数据。此时,可以使用合并流,将多个输入流合并成一个SequenceInputStream流对象。(没用过,不想写了)

7.PrintStream 说这个名字可能你不熟悉,如果说System.out.print()你肯定熟悉,System.out这个对象就是PrintStream;

  • 字符流

    1.FileReader ,PrintWriter ,BufferedWriter 和 BufferedReader

import java.io.*;

/**
 * Created by XYD on 2016/1/4 0004.
 */
public class FileReaderDemo {

    public static void main(String[] args){
        FileReaderDemo demo = new FileReaderDemo();
        //两个方法只能有一个被使用,不知道为什么,知道的大哥求指教
  //      demo.bufferReader();//使用BufferedWriter 和 BufferedReader
        demo.fileReader();//使用FileReader和PrintWriter,这个会出现乱码

    }

    private void fileReader(){
        char[] buffer = new char[];
        int numberRead=;
        FileReader reader=null;
        PrintWriter writer=null;

        try {
            reader=new FileReader("F:\\f\\2365157.lrc");
            writer=new PrintWriter(System.out);
            while ((numberRead=reader.read(buffer))!=-){
                writer.write(buffer,,numberRead);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            writer.close();
        }
    }

    private void bufferReader(){
        char[] buffer = new char[];
        int numberRead=;
        InputStreamReader reader=null;
        PrintWriter writer=null;

        try {
            reader = new InputStreamReader(new FileInputStream("F:\\f\\2365157.lrc"),"UTF-8");
            writer = new PrintWriter(System.out);

            while((numberRead=reader.read(buffer))!=-){
                writer.write(buffer,,numberRead);
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        finally {
            try {
                reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            writer.close();
        }
    }
}
           

2.Console类,该类提供了用于读取密码的方法,可以禁止控制台回显并返回char数组,对两个特性对保证安全有作用,平时用的不多,了解就行

3.StreamTokenizer 类,这个类非常有用,它可以把输入流解析为标记(token), StreamTokenizer 并非派生自InputStream或者OutputStream,而是归类于io库中,因为StreamTokenizer只处理InputStream对象。

首先是文本对象:

‘水上漂’

青青草

“i love cjjjjj”

{3211}

23223 3523

i love wyh ,。

. ,

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

/**
 * Created by XYD on 2016/1/4 0004.
 */
 /** 
 * 使用StreamTokenizer来统计文件中的字符数 
* StreamTokenizer 类获取输入流并将其分析为“标记”,允许一次读取一个标记。 
* 分析过程由一个表和许多可以设置为各种状态的标志控制。 
* 该流的标记生成器可以识别标识符、数字、引用的字符串和各种注释样式。 
 * 
*  默认情况下,StreamTokenizer认为下列内容是Token: 字母、数字、除C和C++注释符号以外的其他符号。 
*  如符号"/"不是Token,注释后的内容也不是,而"\"是Token。单引号和双引号以及其中的内容,只能算是一个Token。 
*  统计文章字符数的程序,不是简单的统计Token数就万事大吉,因为字符数不等于Token。按照Token的规定, 
*  引号中的内容就算是10页也算一个Token。如果希望引号和引号中的内容都算作Token,应该调用下面的代码: 
*    st.ordinaryChar('\''); 
* st.ordinaryChar('\"'); 
*/  

public class StreamTokenizerExample {

    public static void main(String[] args){
        String fileName = "f:\\f\\test.txt";
        StreamTokenizerExample.statis(fileName);
    }

    public static long statis(String fileName){

        FileReader reader=null;
        try {
            reader=new FileReader(fileName);
            //创建分析给定字符流的标记生成器 
            StreamTokenizer st = new StreamTokenizer(reader);
            //ordinaryChar方法指定字符参数在此标记生成器中是“普通”字符。  
            //下面指定单引号、双引号和注释符号是普通字符
            st.ordinaryChar('\'');
            st.ordinaryChar('\"');
            st.ordinaryChar('/');

            String s;
            int numberSum=;
            int wordSum=;
            int symbolSum=;
            int total=;
            //nextToken方法读取下一个Token.
            //TT_EOF指示已读到流末尾的常量。  
            while (st.nextToken()!=StreamTokenizer.TT_EOF){
                //在调用 nextToken 方法之后,ttype字段将包含刚读取的标记的类型 
                switch (st.ttype){
                    //TT_EOL指示已读到行末尾的常量。
                    case StreamTokenizer.TT_EOL:
                        break;
                    //TT_NUMBER指示已读到一个数字标记的常量  
                    case StreamTokenizer.TT_NUMBER:
                        //如果当前标记是一个数字,nval字段将包含该数字的值 
                        s=String.valueOf(st.nval);
                        System.out.println("数字有:"+s);
                        numberSum++;
                        break;
                    //TT_WORD指示已读到一个文字标记的常量  
                    case StreamTokenizer.TT_WORD:
                        //如果当前标记是一个文字标记,sval字段包含一个给出该文字标记的字符的字符串  
                        s=st.sval;
                        System.out.println("单词有:"+s);
                        wordSum++;
                        break;
                    default:
                        //如果以上3中类型都不是,则为英文的标点符号  
                        s=String.valueOf((char)st.ttype);
                        System.out.println("标点有: "+s);
                        symbolSum++;
                }
            }
            System.out.println("数字有 "+numberSum+"个");
            System.out.println("单词有 "+wordSum+"个");
            System.out.println("标点符号有 "+symbolSum+"个");
            total=symbolSum+numberSum+wordSum;
            System.out.println("Total="+total);
            return total;
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return -;
        } catch (IOException e) {
            e.printStackTrace();
            return -;
        }
        finally {
            if(reader!=null){
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}