十、java_IO

目录:

一、java流式输入/输出原理

二、java流类的分类

三、输入/输出流类

四、常见的节点流和处理流

五、文件流

六、缓冲流

七、数据流

八、转换流

九、Print流

十、Ubject流

 

 

一、java流式输入/输出原理

java中,对于数据的输入/输出操作以”流”(Stream)方式进行;JDK提供了各种各样的”流”类,用以获取不同类型的数据;程序中通过标准的方法输入或输出数据

 

二、java流类的分类

  • 按数据流的方向不同可以分为输入流和输出流
  • 按处理数据单位不同可以分为字节流和字符流
  • 按照功能不同可以分为节点流和处理流

jdk所提供的所有流类型位于包java.io内,分别继承自以下四种抽象流类型

  字节流 字符流
输入流 InputStream Reader
输出流 OutputStrean Writer

节点流:可以从一个特定的数据源(节点)读写数据(如:文件、内存)

处理流:是链接已存在的流(节点流或处理流)纸上,通过对数据的处理为程序提供更为强大的读写功能

三、输入/输出流类

1.InputStream

继承自InputStream的流都是用于向程序中输入数据,且数据的单位为字节(8bit);下图中神色为节点流,浅色为处理流

image

InputSream的基本方法:

//读取一个字节并以整数的形式返回(0-255),如果返回-1则已经到输入流的末尾
int read() throws IOException    
//读取一系列字节并存储到一个数组buffer,返回实际读取的字节数。如果读取前已经到输入流的末尾返回-1
int read(byte[] buffer) throws IOException    
//读取length个字节,并存储到一个字节数组buffer,从length位置开始,返回实际读取的字节数,如果读取前已经到输入流的末尾返回-1
int read(byte[] buffer, int offset, int length) throws IOException    
//关闭流释放内存资源
void close() throws IOException    
//跳过n个字节不读,返回实际跳过的字节数
long skip(long n) throws IOException

2.OutputStream

继承自OutPutStream的流是用于程序输出数据,且数据的单位为字节(8bit);下图中神色为节点流,浅色为处理流

image

OutputStream的基本方法:

//向输出流中写入一个字节数据,该字节数据为参数b的低8位
void write(int b) throws IOException
//将一个字节类型的数组中的数据写入输出流
void write(byte[] b) throws IOException
//将一个字节类型的数组中的从指定位置(off)开始的len个字节写入到输出流
void write(byte[] b, int off, int len) throws IOException
//关闭流释放内存资源
void close() throws IOException
//将输出流中还从的数据全部写入到目的地
void flush() throws IOException

3.Reader

继承自Reader的流都是用于向程序中输入数据,且数据的单位为字符(16bit);下图中神色为节点流,浅色为处理流

image

Reader的基本方法:

//读取一个字符并以整数的形式返回(0-255),如果返回-1则已经到输入流的末尾
int read() throws IOException    

//读取一系列字符并存储到一个数组buffer,返回实际读取的字符数。如果读取前已经到输入流的末尾返回-1
int read(char[] buffer) throws IOException    

//读取length个字符,并存储到一个字符数组buffer,从length位置开始,返回实际读取的字符数,如果读取前已经到输入流的末尾返回-1
int read(char[] buffer, int offset, int length) throws IOException    

//关闭流释放内存资源
void close() throws IOException    

//跳过n个字符不读,返回实际跳过的字符数
long skip(long n) throws IOException

4.Writer

继承自writer的流都是用于程序中输出数据,且数据的单位为字符(16bit);下图中神色为节点流,浅色为处理流

image

Writer常用方法

//向输出流中写入一个字符数据,该字符数据为参数b的低16位
void write(int b) throws IOException

//将一个字符类型的数组中的数据写入输出流
void write(char[] b) throws IOException

//将一个字符型的数组中的从指定位置(off)开始的len个字符写入到输出流
void write(char[] b, int off, int len) throws IOException

//将一个字符串中的字符写入到输出流
void wrete(String string) throws IOException

//将一个字符串从offset开始的length个字符写入到输出流
void write(String string, int offset, int length) throws IOException

//关闭流释放内存资源
void close() throws IOException

//将输出流中还从的数据全部写入到目的地
void flush() throws IOException

   

 

四、常见的节点流和处理流 

1.节点流类型:

image_thumb[1]

2.处理流类型:

image

五、文件流

FileInputStream和FileOutputStream分别继承自InputStream和OutputStream用于向文件中输入和输出字节

FileInputStream和FileOutputStream常用构造方法:

FileInputStream(String name) throws FileNotFoundException
FileInputStream(File file) throws FileNotFoundException
FileOutputStream(String name) throws FileNotFoundException
FileOutputStream(File file) throws FileNotFoundException
FileOutputStream(File file,boolean append) throws FileNotFoundException

FileInputStream和FileOutputStream类支持其父类InputStream和OutputStream所提供的数据读写方法。

注意:

  • 在实例化FileInputStream和FileOutputStraeam流时要用try-catch语句来处理其可能抛出的FileNotFoundException
  • 在读写数据时也要用try-catch语句来处理可能抛出IOException
  • FileNotFoundException是IOException的子类

FileInputStream:

public class Test{    
    public static void main(String[] args) {
        
        int b = 0 ;
        FileInputStream in = null;
        //打开文件
        try {
            in = new FileInputStream("F:\\test.txt");//windows下路径分隔符是两个反斜杠,也可以直接使用正斜杠
        } catch (FileNotFoundException e) {
            System.out.println("找不到指定文件");
            System.exit(-1);
        }
        //读取文件
        try {
            long num = 0;
            while((b = in.read()) != -1) {
                System.out.print((char)b);
                num++;
            }
            in.close();
            System.out.println();
            System.out.print("共读取了 "+ num +" 个字节");
        } catch (IOException e1) {
            System.out.println("文件读取错误");
            System.exit(-1);
        }
        
    }
}

FileOutputStream:

public class Test{    
    public static void main(String[] args) {
        
        int b = 0 ;
        FileInputStream in = null;
        FileOutputStream out = null;
        //打开文件
        try {
            in = new FileInputStream("F:\\test.txt");//windows下路径分隔符是两个反斜杠,也可以直接使用正斜杠
            out = new FileOutputStream("F:/test1.txt");//如果目录下没有这个文件FileOutputStream会自动生成一个
            while((b = in.read()) != -1) {
                out.write(b);//一个个字节写进去
            }
            in.close();//管道用完记得关闭
            out.close();
        } catch (FileNotFoundException e) {
            System.out.println("找不到指定文件");
            System.exit(-1);
        } catch (IOException e1) {
            System.out.println("文件复制错误");
            System.exit(-1);
        }
        System.out.print("复制成功");    
    }
}

FileReader:

public class Test{    
    public static void main(String[] args) {
        
        FileReader fr = null; 
        int c = 0;
        try {
            fr = new FileReader("f:/test.txt");
            int in = 0;
            while ((c = fr.read()) != -1) {
                System.out.print((char)c);
            }
        } catch (FileNotFoundException e) {
            System.out.print("找不到指定文件");
        } catch (IOException e1) {
            System.out.print("文件读取错误");
        }

    }
}

FileWriter:

public class Test{    
    public static void main(String[] args) {
        
        FileReader fr = null;
        FileWriter wr = null;
        int c = 0;
        try {
            fr = new FileReader("f:/test.txt");
            wr = new FileWriter("f:/test1.txt");
            int in = 0;
            while ((c = fr.read()) != -1) {
                wr.write(c);
            }
            wr.close();
            fr.close();
        } catch (FileNotFoundException e) {
            System.out.print("找不到指定文件");
        } catch (IOException e1) {
            System.out.print("文件写入错误");
        }
    }
}

六、缓冲流

缓冲流要”套接”在相应的节点流纸上,对读写的数据提供了缓冲的功能,提高了读写的效率,同时增加了一些新的方法

JDK提供了四种缓冲流,其常用的构造方法为:

BufferedReader(Reader in)
BufferedReader(Reader in,int sz)//sz为自定义缓冲区的大小
BufferedWriter(Writer out)
BufferedWriter(Writer out,int sz)
BufferedInputStream(InputStream in)
BufferedInputStream(InputStream in, int sz)
BufferedOutputStream(OutputStream out)
BufferedOutputStream(OutputStream out, int sz)
  • 缓冲流输入支持其父类的mark和reset方法
  • BufferedReader提供了readLine方法用于读取一行字符串(以\r 或\n分割)
  • BufferedWriter提供了newLine用于写入一个行分隔符
  • 对于输出的缓冲流,写出的数据会现在内存中缓存,使用flush方法将会使内存中的数据立刻写出

BufferStream1:

public class Test{    
    public static void main(String[] args) {
        
        try {
            FileInputStream fis = new FileInputStream("f:/test.txt");
            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();//回到100的那个点上
            for(int i=0; i<=10 && (c=bis.read()) != -1; i++) {
                System.out.print((char)c + " ");
            }
            bis.close();
        } catch(IOException e) {
            e.printStackTrace();
        }    
    }
}

BufferStream2:

public class Test{    
    public static void main(String[] args) {
        
        try {
            BufferedWriter bw = new BufferedWriter(new FileWriter("f:/test.txt"));//管道套接
            BufferedReader br = new BufferedReader(new FileReader("f:/test.txt"));
            //写入
            String s = null;
            for(int i=1; i<100; i++) {
                s = String.valueOf(Math.random());//产生一个字符串的随机数
                bw.write(s);//写一个字符串到缓冲区
                bw.newLine();//写一个换行到缓冲区
            }
            bw.flush();//将缓存内存中的数据写出
            //逐行读取
            while((s=br.readLine()) != null) {
                System.out.println(s);
            }
            
            bw.close();
            br.close();
        } catch(IOException e) { 
            e.printStackTrace();
        }    
    }
}

    

 

七、数据流

  • DataInputStream和DataOutPutStream分别继承自InputStream和OutPutStream,它属于处理流,需要分别”套接”在InputStream和OutputStream类型的节点流上
  • DataInputStream和DataOutputStream提供了可以存取与机器无关的java原始类型数据(如:int,double等)的方法
  • DataInputStream和DataOutputStream的构造方法为:
DataInputStream(InputStream in)
DataOutputStream(OutputStream out)

看一个例子:

public class Test{    
    public static void main(String[] args) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();//在内存中分配字节数组
        DataOutputStream dos = new DataOutputStream(baos);//套接
        
        try {
            dos.writeDouble(Math.random());//写一个double类型的随机数,double是8个字节
            dos.writeBoolean(true);//写一个布尔值进去,布尔值在内存中只占一个字节
            ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());//读数据,只能一个字节一个字节读
            System.out.println(bais.available());//输出字节数
            
            DataInputStream dis = new DataInputStream(bais);//套接
            System.out.println(dis.readDouble());//输出数据1,注意,先写的先读
            System.out.println(dis.readBoolean());//输出数据2
            dos.close();
            dis.close();
            
        } catch(IOException e) {
            e.printStackTrace();
        }
    }
}

 

八、转换流

  • InputStreamReader和OutputStreamWriter用于字节数据到字符数据之间的转换
  • InputStreamReader需要和InputStream”套接”
  • OutputStreamWriter需要和OutputStream”套接”
  • 转换流在构造时可以指定其编码集合,例如:InputStream isr = new InputStreamReader(System.in, “ISO8859_1”)

OutputStreamWriter:

public class Test{    
    public static void main(String[] args) {

        try {            
            OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("f:/test.txt"));
            osw.write("aaa");            
            System.out.println(osw.getEncoding());    //获取osw的字符编码        
              osw.close();
            //true表示在原文件的基础上追加,如果不加true,则会删除原文件的内容后再写入新的内容,ISO8859_1是一种字符编码,指定了要写入内容的编码格式
              osw = new OutputStreamWriter(new FileOutputStream("f:/test.txt", true), "ISO8859_1");
            osw.write("bbb");
            System.out.println(osw.getEncoding());
            osw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

InputStreamReader:

/*
 * 这个程序相当于一直逐行读取键盘输入,直到输入exit为止,这是一种阻塞式的方法,程序运行起来后不输入exit程序就一直停在那,也可以理解为是同步式的
 */

public class Test{    
    public static void main(String[] args) {
        InputStreamReader isr = new InputStreamReader(System.in);//System.in是接收的键盘输入
        BufferedReader br = new BufferedReader(isr);
        String s = null;
        
        try {
            s = br.readLine();
            //除非s="exit"否则就不停的读
            while(s != null) {
                if(s.equalsIgnoreCase("exit")) {
                    break;
                } else {
                    System.out.println(s.toUpperCase());
                    s = br.readLine();
                }                
            }
            br.close();            
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

 

九、Print流

  • PrintWriter和PrintStream都属于输出流,分别针对与字符和字节
  • PrintWriter和PrintStream提供了重载的print
  • Println方法用于多种数据类型的输出
  • PrintWriter和PrintStream的输出操作不会抛出异常,用户通过检测错误状态获取错误信息
  • PrintWriter和PrintStream有子的佛那个flush功能
PrintWriter(Writer out)
PrinWriter(Writer out,boolean autoFlush)
PrintWriter(OutputStream out)
PrintWriter(PutputStream out, boolean autoFlush)
PrintStream(OutputStream out)
PrintStream(OutputStream out, boolean autoFlush)

例子1:

public class Test{    
    public static void main(String[] args) {
        PrintStream ps = null;
        
        try {
            FileOutputStream fos = new FileOutputStream("f:/test.txt");
            ps = new PrintStream(fos);//套接
        } catch(IOException e) {
            e.printStackTrace();
        }
        
        if(ps != null) {
            System.setOut(ps);//更改默认输出位置为ps,System.out默认指向的是控制台
        }
        
        int ln = 0;
        for(char c=0; c<=60000; c++) {
            System.out.print(c+" ");
            if(ln++ >= 100) {
                System.out.println();
                ln = 0;
            }
        }
    }
}

例子2:

public class Test{    
    public static void main(String[] args) {
        String filename = args[0];//外部传参
        if(filename != null) {
            list(filename,System.out);
        }
    }
    public static void list(String f,PrintStream fs){
        try {
            BufferedReader br = new BufferedReader(new FileReader(f));
            String s = null;
            //按行读取
            while((s=br.readLine()) != null) {
                fs.println(s);
            }
            br.close();
        } catch(IOException e) {
            fs.println("无法读取文件");
        }
    }
}

例子3:

public class Test{    
    public static void main(String[] args) {
        String s = null;
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));//System.in是键盘输入
        
        try {
            FileWriter fw = new FileWriter("f:/test.txt",true);//true追加在原文件后面
            PrintWriter log = new PrintWriter(fw);
            
            while((s=br.readLine()) != null){
                if(s.equalsIgnoreCase("exit")){
                    break;//如果键盘输入exit则停止运行
                }
                
                System.out.println(s.toUpperCase());//控制台输出
                log.println("----");
                log.println(s.toUpperCase());//写入
                log.flush();
            }
            log.println("==="+new Date()+"===");//new Date()指的是util里的date,也就是当前时间
            log.flush();
            log.close();
        } catch(IOException e) {
            e.printStackTrace();
        }
    }
}

 

十、Ubject流

作用:直接将Object写入或读出

  • transient关键字
  • serializable接口      标记类里的对象可以序列化
  • externalizable接口    控制类的对象是怎么写出去的,也就是说可以自己控制序列化过程

看一个例子:

class T implements Serializable{//如果要写入或者读对象必须要实现Serializable接口,这是一个标记接口,所以不需要重写方法
    int i = 0;
    int j = 9;
    double d = 2.3;
    int k = 0;
}
public class Test{    
    public static void main(String[] args) throws Exception{
        T t = new T();
        t.k = 8;
        FileOutputStream fos = new FileOutputStream("f:/test.txt");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        
        oos.writeObject(t);//把t对象写入f:/test.txt
        oos.flush();
        oos.close();
        
        FileInputStream fis = new FileInputStream("f:/test.txt");
        ObjectInputStream ois = new ObjectInputStream(fis);
        
        T tReaded = (T)ois.readObject();//读对象
        System.out.println(tReaded.i+" "+tReaded.j+" "+tReaded.d+" "+tReaded.k);
    }
}

上面例子中的输出结果为:0    9    2.3    8

如果将T里的 int k = 0; 改为 transient int k = 0;

则输出结果应该是0    9    2.3    0

因为transient相当于把k变成了透明的,使用transient修饰的成员变量在序列化(操作对象)的时候不予考虑

posted @ 2016-08-13 16:48  许忠慧  阅读(507)  评论(0编辑  收藏  举报