Java IO Basic

Java IO Basic

  • 首先看下关于Java的IO的图:
    这里写图片描述
    我看到这个,感觉头都大了不少。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()/(1024*1024*1024)+"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=0;//统计文件字节长度
        InputStream stream=null;//文件输入流
        try {
            stream = new FileInputStream(new File("F:\\f\\2365157.lrc"));
           //FileInputStream是有缓冲区的,所以用完之后必须关闭,否则可能导致内存占满,数据丢失。
            while (stream.read()!=-1){//读取文件字节,并递增指针到下一个字节  
                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[512];//缓冲区大小
        int numberRead=0;//一次读取的字节数
        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))!=-1){//numberRead的目的在于防止最后一次读取的字节小于buffer长度
                out.write(buffer,0,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",22));
            objectWriter.writeObject(new Student("tt",23));
            objectWriter.writeObject(new Student("zz",21));

            objectReader = new ObjectInputStream(new FileInputStream("F:\\f\\2365157_copy.lrc"));
            for(int i=0;i<3;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",12),
                new Member("dacaibi",13),
                new Member("xyd",14)};

        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=0;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[512];
        int numberRead=0;
        FileReader reader=null;
        PrintWriter writer=null;

        try {
            reader=new FileReader("F:\\f\\2365157.lrc");
            writer=new PrintWriter(System.out);
            while ((numberRead=reader.read(buffer))!=-1){
                writer.write(buffer,0,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[512];
        int numberRead=0;
        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))!=-1){
                writer.write(buffer,0,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=0;
            int wordSum=0;
            int symbolSum=0;
            int total=0;
            //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 -1;
        } catch (IOException e) {
            e.printStackTrace();
            return -1;
        }
        finally {
            if(reader!=null){
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值