[面试要点]java io编程

java io 简介

惯例先祭出一张图

这里写图片描述
[1]输入字节流InputStream:InputStream 是所有的输入字节流的父类,它是一个抽象类;ByteArrayInputStream、StringBufferInputStream、FileInputStream 是三种基本的介质流,它们分别从Byte 数组、StringBuffer、和本地文件中读取数据;PipedInputStream 是从与其它线程共用的管道中读取数据;ObjectInputStream 和所有FilterInputStream 的子类都是装饰流(装饰器模式的主角)。
[2]输出字节流OutputStream:OutputStream 是所有的输出字节流的父类,它是一个抽象类。
ByteArrayOutputStream、FileOutputStream 是两种基本的介质流,它们分别向Byte 数组、和本地文件中写入数据。PipedOutputStream 是向与其它线程共用的管道中写入数据,ObjectOutputStream 和所有FilterOutputStream 的子类都是装饰流。
[3]字符输入流Reader:Reader 是所有的输入字符流的父类,它是一个抽象类;CharReader、StringReader 是两种基本的介质流,它们分别将Char 数组、String中读取数据;PipedReader 是从与其它线程共用的管道中读取数据;BufferedReader 很明显就是一个装饰器,它和其子类负责装饰其它Reader 对象;FilterReader 是所有自定义具体装饰流的父类,其子类PushbackReader 对Reader 对象进行装饰,会增加一个行号;InputStreamReader 是一个连接字节流和字符流的桥梁,它将字节流转变为字符流。FileReader 可以说是一个达到此功能、常用的工具类,在其源代码中明显使用了将FileInputStream 转变为Reader 的方法。我们可以从这个类中得到一定的技巧。Reader 中各个类的用途和使用方法基本和InputStream 中的类使用一致。
[4]字符输出流Writer:Writer 是所有的输出字符流的父类,它是一个抽象类;CharArrayWriter、StringWriter 是两种基本的介质流,它们分别向Char 数组、String 中写入数据。PipedWriter 是向与其它线程共用的管道中写入数据,BufferedWriter 是一个装饰器为Writer 提供缓冲功能;PrintWriter 和PrintStream 极其类似,功能和使用也非常相似;

简述: IO流简单来说就是Input和Output流,IO流主要是用来处理设备之间的数据传输,Java对于数据的操作都是通过流实现,而java用于操作流的对象都在IO包中。使用流对象要抛出IO异常,IO异常为checked异常

分类:

    按操作数据分为:字节流和字符流。 如:Reader和InpurStream,只要是以stream结尾的都是字节流

    按流向分:输入流和输出流。如:InputStream和OutputStream,输入则为input或reader,输出则为output或writer,应用中主要将外来的数据流(文件来的,或者网络传输流等)首先通过输入流输入到内存,处理之后通过输出流输出
    按功能分:节点流和过滤流   
    节点流: 用于直接操作目标设备的流
    过滤流: 是对一个已存在的流的链接和封装,通过对数据进行处理为程序提供功能强大、灵活的读写功能。

可以把我们的程序想象成一个容器(内存),把要处理的数据流通过输入流(input,reader)输入,处理后,通过输出流(output ,writer)输出

字符流

  1. 字符流简介
    *字符流中的对象融合了编码表,也就是系统默认的编码表。我们的系统一般都是GBK编码
    • 字符流只用来处理文本数据
    • 字符流在处理输出流时必须flush(刷新)才能将数据输出

实例一:在硬盘创建一个文件,写入一些文本信息

package com.oldbig.io;

import java.io.FileWriter;
import java.io.IOException;

public class FileWriterDemo {
    public static void main(String[] args) throws IOException {
         //创建一个FileWriter对象,该对象一被初始化就必须要明确被操作的文件。  
        //而且该文件会被创建到指定目录下。如果该目录有同名文件,那么该文件将被覆盖。  
        //若在后面加入参数true,则不覆盖文件,在文件后面添加文本,例如:FileWriter("D:\\ioTest\\1.txt",true);

        FileWriter fw = new FileWriter("D:\\ioTest\\1.txt");
        //调用write的方法将字符串写到流中
        fw.write("hello word");
         //刷新流对象缓冲中的数据,将数据刷到目的地中 
        fw.flush();
         //关闭流资源,但是关闭之前会刷新一次内部缓冲中的数据。当我们结束输入时候,必须close();  
        fw.write("test");       
        fw.close();
        //flush和close的区别:flush刷新后可以继续输入,close刷新后不能继续输入。 
    }
}

实例二:使用FileReader对文件进行读取

    private static void singleRead() throws IOException {
        FileReader fr = null;
        try{
            //创建一个文件读取流对象,和指定名称的文件关联。  
            //要保证文件已经存在,否则会发生异常:FileNotFoundException  
            fr = new FileReader("D:\\ioTest\\1.txt");
            //将文件流包装成缓冲流,读取更方便,若直接用FileReader的read方法读取的是int数据不是文本数据
            BufferedReader br = new BufferedReader(fr);
            String ch = null;
            while((ch=br.readLine()) != null){
                System.out.println(ch);
            }                   

        }catch(IOException e){
            e.printStackTrace();
        }finally{
            fr.close();
        }

    }

实例:复制文本–>另一文本

private static void singleRead() throws IOException {
        FileReader fr = null;
        try{
            //创建一个文件读取流对象,和指定名称的文件关联。  
            //要保证文件已经存在,否则会发生异常:FileNotFoundException  
            fr = new FileReader("D:\\ioTest\\1.txt");
            //将文件流包装成缓冲流,读取更方便
            BufferedReader br = new BufferedReader(fr);
            String ch = null;
            BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\ioTest\\2.txt"));
            while((ch=br.readLine()) != null){
                System.out.println(ch);
                bw.write(ch);
                bw.newLine();  //换行
                bw.flush();     //清空缓冲区
            }                   


        }catch(IOException e){
            e.printStackTrace();
        }finally{
            fr.close();
        }

    }

刚刚用到缓冲区:字符流的缓冲区:BufferedReader和BufferedWriter

  • 缓冲区的出现时为了提高流的操作效率而出现的.

  • 需要被提高效率的流作为参数传递给缓冲区的构造函数

  • 在缓冲区中封装了一个数组,存入数据后一次取出

  • readline()只返回回车符前面的字符,不返回回车符。如果是复制的话,必须加入newLine(),写入回车符

字节流

简述:
1、字节流和字符流的基本操作是相同的,但是要想操作媒体流就需要用到字节流。(媒体文件也是以字节存储的)

2、读写字节流:InputStream 输入流(读)和OutputStream 输出流(写)

3、字节流操作可以不用刷新流操作。

4、InputStream特有方法:

    int available();//返回文件中的字节个数

实例:复制一张图片

package com.oldbig.io;

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

public class CopyStream {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        copyJpg();
        System.out.println("复制完成");

    }

    private static void copyJpg() {
        // TODO Auto-generated method stub
        FileInputStream fis = null;
        FileOutputStream fos = null;
        try{
            fis = new FileInputStream("D://ioTest//1.jpg");
            fos = new FileOutputStream("D://ioTest//2.jpg");

            byte[] info = new byte[1024];
            int len = 0;
            while((len = fis.read(info)) != -1 ){
                fos.write(info, 0, len);
            }
        }catch(IOException e){
            e.printStackTrace();
            throw new RuntimeException("复制文件异常");
        }finally{
            try {
                fis.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

}

流操作规律

System.out: 对应的标准输出设备:控制台 //它是PrintStream对象,(PrintStream:打印流。OutputStream的子类)

System.in: 对应的标准输入设备:键盘 //它是InputStream对象

示例:从键盘录入流,打印到控制台上

package com.oldbig.io;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

public class SystemInOutDemo {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        BufferedReader br = null;
        BufferedWriter bw = null;
        try{
            InputStream is = System.in;
            InputStreamReader isr = new InputStreamReader(is, "UTF-8");
            //InputSteamReader:读取字节并将其解码为字符  
            br = new BufferedReader(isr);

            //OutputStreamWriter:要写入流中的字符编码成字节  
            bw = new BufferedWriter(new OutputStreamWriter(System.out));
            String info = null;
            while((info = br.readLine()) != null){
                bw.write(info);
                bw.newLine();

                bw.flush();
            }
        }catch(IOException e){
            e.printStackTrace();
        }

    }

}

java 管道通信

Java提供管道功能,实现管道通信的类有两组:PipedInputStream和PipedOutputStream或者是PipedReader和PipedWriter。管道通信主要用于不同线程间的通信。

一个PipedInputStream实例对象必须和一个PipedOutputStream实例对象进行连接而产生一个通信管道。PipedOutputStream向管道中写入数据,PipedIntputStream读取PipedOutputStream向管道中写入的数据。一个线程的PipedInputStream对象能够从另外一个线程的PipedOutputStream对象中读取数据。

实例:两个线程之间建立通信管道

package com.oldbig.io;

import java.io.IOException;
import java.io.PipedOutputStream;

public class PipedSend extends Thread{
    private PipedOutputStream out = new PipedOutputStream();

    public PipedOutputStream getOut() {
        return out;
    }
    public void run(){
        String info = "hello ,receiver";
        try{
            out.write(info.getBytes()); //写入数据
            out.close();
        }catch(IOException e){
            e.printStackTrace();
        }
    }

}
package com.oldbig.io;

import java.io.IOException;
import java.io.PipedInputStream;

public class PipedReader extends Thread{

    private PipedInputStream in = new PipedInputStream();


    public PipedInputStream getIn() {
        return in;
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        byte[] info = new byte[1024];
        try{
            int len = in.read(info);
            System.out.println("receive from send :" + new String(info,0,len));
            in.close();
        }catch(IOException e){
            e.printStackTrace();
        }
    }

}
public class PipedTest {

    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub
        PipedSend send = new PipedSend();
        PipedReader reader = new PipedReader();

        PipedOutputStream out = send.getOut();
        PipedInputStream in = reader.getIn();

        in.connect(out);//或者也可以用out.connect(in);  
        send.start();
        reader.start();

    }

}

总结

*字节流和字符流的区别:
字节流没有缓冲区,是直接输出的,而字符流是输出到缓冲区的。因此在输出时,而字符流只有在调用close()方法关闭缓冲区时,信息才输出。要想字符流在未关闭时输出信息,则需要手动调用flush()方法。

· 读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。
· 处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。

结论:只要是处理纯文本数据,就优先考虑使用字符流。除此之外都使用字节流

*什么是java序列化,如何实现java序列化?

我们有时候将一个java对象变成字节流的形式传出去或者从一个字节流中恢复成一个java对象,例如,要将java对象存储到硬盘或者传送给网络上的其他计算机,这个过程我们可以自己写代码去把一个java对象变成某个格式的字节流再传输,但是,jre本身就提供了这种支持,我们可以调用OutputStream的writeObject方法来做,如果要让java 帮我们做,要被传输的对象必须实现serializable接口,这样,javac编译时就会进行特殊处理,编译的类才可以被writeObject方法操作,这就是所谓的序列化。需要被序列化的类必须实现Serializable接口,该接口是一个mini接口,其中没有需要实现的方法,implements Serializable只是为了标注该对象是可被序列化的。

例如,在web开发中,如果对象被保存在了Session中,tomcat在重启时要把Session对象序列化到硬盘,这个对象就必须实现Serializable接口。如果对象要经过分布式系统进行网络传输或通过rmi等远程调用,这就需要在网络上传输对象,被传输的对象就必须实现Serializable接口。

参考:https://www.cnblogs.com/xll1025/p/6418766.html
http://blog.csdn.net/liufeng_king/article/details/12978101

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值