java io流详解

  •  

     

    2 Java流被分为 字节流和字符流两大流类,有什么区别 ?

    字节流的两个基类是 inputstream 和outputstream,字符流的两个基类是 Reader和writer,他们都是Object类的直接子类,字符流是处理以8位字节为基本单位的字节流类,Reader和writer是专门处理16位字节的字符流类

     

     

    • 字符流:因为数据有不同的编码,可以对字符进行不同的操作,其本质还是基于字节流,然后再查询相应的码表。一般用于处理纯文本数据。
    • 字节流:可以处理所有类型数据,二进制文件(图片,音频等)。
    • 输入流:读入数据,也就是数据的源,如键盘,磁盘文件,网络文件,内存等。字符流对应的基本输入流为Reader,字节流对应的基本输入流为InputStream。
    • 输出流:输出数据,数据的目的地,如控制台,磁盘文件,内存等。字符流对应的基本输出流为Writer,字节流对应的基本输出流为OutputStream。

    二、字符流

    字符流的基本输入输出流是Reader和Writer,两者有一些常用的方法:

    Reader的常用读取操作:

    1.  int read() 读取单个字符。 还有一点关于数据的读入过程,如使用int read()一个字节一个字节的读入,到达流尾时,返回-1,这种方式,需要注意其返回int需要强制转换一下,如int data = reader.read();,那么读到的数据便是(char)data
    2. int read(char[] cbuf) 将字符读入数组。
    3. abstract int read(char[] cbuf, int off, int len) 将字符读入数组的某一部分。

    Writer的常用写入操作:

    1. abstract void flush() 刷新该流的缓冲。
    2. void write(char[] cbuf) 写入字符数组。
    3. void write(int c) 写入单个字符。
    4. void write(String str) 写入字符串。
    5. void write(String str, int off, int len) 写入字符串的某一部分。

    在使用Reader和Writer进行数据流的读入和写入操作时是不会直接创建Reader和Writer对象的,一般都是使用其子类,如FileReader和FileWriter,示例代码如下:

     

    import java.io.FileNotFoundException;

    import java.io.FileReader;

    import java.io.IOException;

     

    public class ReaderDemo {

         public static void main(String[] args) throws IOException {

         //创建一个FileReader对象用来读取文件中的字符 

    FileReader reader=new FileReader("/Users/mac/frf");

           int ch;

        while( (ch=reader.read())!=-1) {

    System.out.println((char)ch);

    }

       

        reader.close();

    }

    }

     

     

    注意:io流在进行数据读写操作时会出现异常,然而一遇到io异常,io流的close()方法将无法得到执行,通常将关闭流的操作写在finally代码中

     

    具体代码如下

    finally {

    try {

    if (in!=null

    in.close();

    } catch (Exception e) {

    e.printStackTrace();

    }

    try {

    if(out!=null)

    out.close();

    } catch ( Exception e) {

    e.printStackTrace();

    }

    }

     

     

     

    另一个例子:

    import java.io.FileNotFoundException;

    import java.io.FileReader;

    import java.io.FileWriter;

    import java.io.IOException;

     

    public class Test {

     public static void main(String[] args) {

    FileReader reader=null;

    FileWriter writer=null;

    //向流中写入一个char[],内容为[i love you]

    try {

    writer =new FileWriter("file.txt");

    writer.write("i love you".toCharArray());

    writer.flush();

    } catch (IOException e) {

    //io异常在这里处理

    // TODO Auto-generated catch block

    e.printStackTrace();

    }finally {

    //在finally中关闭流,并判断是否为null

    if (writer!=null) {

    try {

    writer.close();

    } catch (IOException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    }

    }

    try {

    reader=new FileReader("file.txt");

    } catch (FileNotFoundException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    char[]  buf=new char[1024];

    int n=0;

    try {

    while ((n=reader.read(buf))!=-1) {

    System.out.println(new String(buf,0,n));

    }

    } catch (IOException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    finally {

    if (reader!=null) {

    try {

    reader.close();

    } catch (IOException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    }

    }

    }

    }

     

     

     

    BufferedWriter和BufferedReader使用简介

    BufferedInputStream和BufferedOutputStream是为提高读取和写入的效率而出现的,当我们读取和写入数据时,可以现在内存中建立一个缓冲区,加快数据流的读写,其使用非常简单,将Reader或者Writer对象做为参数传递给其构造函数即可。功能和类似,示例代码如下:

     

    import java.io.*;

     

    public class TestBuffererWriter {

      public static void main(String[] args) {

       BufferedWriter bw=null;

       BufferedReader br=null;

       try {

    bw=new BufferedWriter(new FileWriter("file.txt"));

    bw.write("me,tpp".toCharArray());

    bw.flush();

    } catch (IOException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

       finally {

    try {

    if (bw!=null) {

    bw.close();

    }

    } catch (Exception e2) {

    e2.printStackTrace();

    }

    }

       

       try {

    br=new BufferedReader(new FileReader("file.txt"));

    String  string;

    while ((string=br.readLine())!=null) {

    System.out.println(string);

    }

    } catch (FileNotFoundException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    } catch (IOException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }finally {

    try {

    br.close();

    } catch (IOException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    }

    }

    }

     

     

    其中newLine()是输出一个换行,这种操作是跨平台的,即在Windows下输出\r\n,而在Linux下输出\n。

    LineNumberReader使用简介

    LineNumberReader单从类名上看,大致也知道了类的功能,便是可以输出文本文件的行号。这里行号是从1开始的,也可以使用setLineNumber(int)功能为其设置一个偏移值,如设置100,那么行号就会从101开始输出。

     

     

    三、字节流

    字符流操作的是纯文本内容,而字节流则是所有二进制文件都可以操作,如图片,视频,当然文件文件也是可以的。与字符流中读出和写入的类型为char型相对应,字节流读出和写入的是byte类型。字节流的两个基本输入输出流为InputStream和OutputStream,其功能与字符流的功能类似。对于文件的操作的流是相应的FileInputStream和FileOutputStream,下面通过一个图片拷贝功能作为字节流的一个示例代码:

     

    import java.io.*;
    class Demo {
        public static void main(String[] args) throws IOException {

    FileInputStream fin = new FileInputStream("pic.png");
            FileOutputStream fout = new FileOutputStream("pic2.png");

    // 与Reader不同的是这里使用的是byte类型
            byte[] buf = new byte[1024];
            int n = 0;

    while((n=fin.read(buf)) != -1) {
                fout.write(buf, 0, n);
            }

    // 关闭流
            fin.close();
            fout.close();
        }
    }

     

    BufferedInputStream和BufferedOutputStream使用简介

    为了提高流操作的效率,这里也用相应的缓冲流,到底使用缓冲流与不使用缓冲流在效率上有多大的差别,可以通过比较得出结果。从下面代码的比较结果可以明显的发现,加入缓冲机制会大大提高程序的运行效率,原因大致解释为,未加入缓冲机制,每次读取read()都会调用系统底层读取磁盘操作,每次读取一个字节,非常耗时;而加入缓冲机制后,系统会一次将很多内容读取到内存,而调用read()时,只需要从内存中返回数据内容即可,大大减少了系统底层访问磁盘的次数,所以速度会加快很多。代码示例如下:

     

     

    四、流的总结

    Java将IO单独封装在一个包内,其中不同功能的流数不胜数,使用起来很容易混乱,所以,在使用java io流时需要按照一定的规则,如按照流的流向可以分为两大类,即输入流和输出流,输入流来自数据源,输出流有目的地。常见的源和目的地有如下:

    • 源:键盘录入,磁盘读入,网络文件,内存。
    • 目的地:控制台输出,磁盘文件,内存。

    在明确流向后,在看流的数据是否为纯文本类型,若是则优先选用Reader或Writer字符流来操作,若是二进制类型,则使用InputStream和OutputStream字节流来操作。

    提高流的效率,可以使用BufferedXXX来包装流。对于编码问题,可以使用InputStreamReader和OutputStreamWriter,其可以指定编码类型,如utf-8或者GBK等。

     

     

    五、File的使用简介

    是将文件和文件夹封装成的对象,方便对文件或者文件夹的属性信息进行操作,也可以作为参数传递。

    File常用内容

    static String separator为一种夸平台文件路径分隔符。

    文件的创建和删除

    File file = new File("file.txt");
    file.createNewFile(); // 用于创建一个空文件,成功返回true,若已存在,则不会创建并返回false,
    file.delete(); // 删除成功返回true,否则返回false
    file.deleteOnExit(); // 退出时删除,一般用于系统退出时删除临时文件

     

    文件的判断

     

    File file = new File("c:" + File.separator + "java", "info.txt");
    file.canExecute(); // 是否可被执行
    file.exists(); // 是否存在
    file.mkdir(); // 创建目录,一层(成功返回true,失败返回false)
    file.mkdirs(); // 创建多级目录
    file.isDirectory(); // 是否为目录文件,不存在或者不是目录返回false
    file.isFile(); // 是否为文件,不存在或不是文件返回false
    file.isHidden(); // 是否为隐藏文件
    file.isAbsolute(); // 是否为据对路径
    file.getName(); // 获取文件名
    file.getParh(); // 获取文件路径
    file.getParent(); // 父目录
    file.lastModified(); // 最后修改时间

     

     

    5、对象的序列化,实现Serializable接口,序列化即使将一个对象整个存储到文件中保存,可以实现数据的保存,下次可以将对象从文件中恢复出,只需要此对象实现了Serializable接口即可,注意的两点是,一是为对象添加static long serialVersionUID = 42L;随便指定一个数值,这是这个对象的唯一标识,即有相同标识才可以从文件中恢复出对象;二是在不需要序列化的对象前加上transient关键字。序列化只会序列化堆中的数据,静态数据不会被序列化,transient关键字的也不会。

     

    import java.io.*;

    public class TestPerson {

        public static void main(String[] args) throws IOException {

    Person p1=new Person("zhang", "2014", 20);

    FileOutputStream fos=new FileOutputStream("we.txt");

    ObjectOutputStream  oos=new ObjectOutputStream(fos);

    oos.writeObject(p1);

    }

        

    }

     

    class Person implements Serializable{

    private String name;

    private String id;

    private int age;

    public Person(String name, String id, int age) {

    super();

    this.name = name;

    this.id = id;

    this.age = age;

    }

    public String getName() {

    return name;

    }

    public void setName(String name) {

    this.name = name;

    }

    public String getId() {

    return id;

    }

    public void setId(String id) {

    this.id = id;

    }

    public int getAge() {

    return age;

    }

    public void setAge(int age) {

    this.age = age;

    }

    }

     

     

     

    小练习

    编写一个程序分别使用一个字符流和字节流拷贝一个文本文件

    import java.io.*;

    public class Test01 {

    public static void main(String[] args) throws Exception { // 字节流拷贝 

        FileInputStream in = new FileInputStream("E:/src.txt");

        FileOutputStream out = new FileOutputStream("E:/des1.txt");

        byte[] buf = new byte[1024];

        int len;

            while ((len = in.read(buf)) != -1) {

            out.write(buf, 0, len);

    }

    in.close();

    out.close();

    // 字符流拷贝

    BufferedReader bf = new BufferedReader(new FileReader("E:/src.txt"));

     BufferedWriter bw = new BufferedWriter(new FileWriter("E:/des2.txt"));

     

     

    String str;

    while ((str = bf.readLine()) != null) { 

                bw.write(str);

                bw.newLine();

        }

            bf.close(); 

            bw.close();

    }


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值