I/O流

前言

I/O是Input/Output的缩写, I/O技术是非常实用的技术,如读/写文件,网络通讯等等。

流(Stream)是指从源节点到目标节点的数据流动。
源节点和目标节点可以是文件、网络、内存、键盘、显示器等等。
源节点的数据流称为输入流(用来读取数据)。
目标节点的数据流称为输出流(用来写入数据)。

Java中使用流来处理程序的输入和输出操作,流是一个抽象的概念,封装了程序数据于输入输出设备交换的底层细节。JavaIO中又将流分为字节流和字符流,字节流主要用于处理诸如图像,音频视频等二进制格式数据,而字符流主要用于处理文本字符等类型的输入输出。

一、流的分类

按操作数据单位不同分为:字节流(8 bit),字符流(16 bit)
按数据流的流向不同分为:输入流,输出流
按流的角色的不同分为:节点流,处理流

这里写图片描述

Java的IO流共涉及40多个类,实际上非常规则,都是从如下4个抽象基类派生的。由这四个类派生出来的子类名称都是以其父类名作为子类名后缀。

这里写图片描述

InputStream 和 Reader 是所有输入流的基类。
InputStream(典型实现:FileInputStream)
int read()
int read(byte[] b)
int read(byte[] b, int off, int len)

Reader(典型实现:FileReader)
int read()
int read(char [] c)
int read(char [] c, int off, int len)

程序中打开的文件 IO 资源不属于内存里的资源,垃圾回收机制无法回收该资源,所以应该显式关闭文件 IO 资源。

1.字节输入流InputStream

输入流InputStream负责从各种数据/文件源产生输入,输入源包括:数组,字符串,文件,管道,一系列其他类型的流,以及网络连接产生的流等等。

常用字节输入流的主要类型:

(1).ByteArrayInputStream字节数组输入流:
主要功能:允许内存缓存作为输入流。
ByteArrayInputStream包含一个内部缓冲区,该缓冲区包含从流中读取的字节。内部计数器跟踪read()方法要提供的下一个字节。
注意:关闭ByteArrayInputStream无效,该类中的方法在关闭此流之后仍可被调用,而不会产生任何的IOException。

(2).FileInputStream文件输入流:
主要功能:从文件系统中的某个文件获得输入字节,用于读取诸如图像数据子类的原始字节流。若要读取字符流,请使用FileReader。

(3).PipedInputStream管道输入流:
主要功能:和管道输出流一起构成一个输入输出的管道,是管道的数据输入端。
管道输入流应该连接到管道输出流,管道输入流提供要写入管道输出流的所有数据字节。通常,这些数据有某个线程从PipedInputStream对象中读取,并有其他线程将其写入到相应的PipedOutputStream对象中。
注意:不建议PipedInputStream和PipedOutputStream对象使用单线程,因为这样可能死锁线程。管道输入流包含一个缓冲区,可以在缓冲区限定范围内将读操作和写操作分离开,如果先连接管道输出流提供数据字节的线程不再存在,则认为该管道已损坏。

(4).SequenceInputStream顺序输入流:
重要功能:将两个或多个输入流对象转换为一个单个输入流对象。
SequenceInputStream表示其他输入流的逻辑串联关系,它从输入流的有序集合开始,并从第一个输入流开始读取,直到到达文件末尾,接着从第二个输入流读取,以此类推,直到到达包含的最后一个输入流的文件末尾为止。

(5).FilterInputStream过滤输入流:
主要功能:包含其他一些输入流,将这些被包含的输入流用作其基本数据源,它可以直接传输数据或者提供一些额外的功能。
常用的FilterInputStream是DataInputStream数据输入流,主要用于允许程序以与机器无关的方式从底层输入流中读取java基本数据类型。其常用的方法有readInt(),readBoolean(),readChar()等等。

2.字节输出流OutputStream:

和字节输入流相对应,字节输出流负责字节类型数据想目标文件或设备的输出。常见的字节输出流如下:

(1).ByteArrayOutputStream字节数组输出流:
主要功能:在内存中创建一个缓冲区,将接收到的数据放入该内存缓冲区中。
ByteArrayOutputStream实现了一个输出流,其中的数据被写入一个byte数组中。缓冲区会随着数据的不断写入而自动增长,可使用toByteArray()和toString()方法获取数据。
注意:和ByteArrayInputStream类似,关闭ByteArrayOutputStream也是无效的,此类中的方法在关闭此流后仍可被调用,而不会产生任何IOException。

(2).FileOutputStream文件输出流:
主要功能:将数据写入到指定文件中。
文件输出流是用于将数据写入File或FIleDescriptor的输出流,用于写入诸如图像数据之类的原始字节流,若要写入字符流,请使用FileWriter。

(3).PipedOutputStream管道输出流:
主要功能:连接管道输入流用来创建通信管道,管道输出流是管道数据输出端。

(4).FilterOutputStream过滤输出流:
主要功能:用于将已存在的输出流作为其基本数据接收器,可以直接传输数据或提供一些额外的处理。
常用的FIlterOutputStream是DataOutputStream数据输出流,它允许程序以适当的方式将java基本数据类型写入输出流中。其常用方法有writeInt(intV),writeChar(int v),writeByte(String s)等等。

3.字符流:

Java中得字节流只能针对字节类型数据,即支持处理8位的数据类型,由于java中的是Unicode码,即两个字节代表一个字符,于是在JDK1.1之后提供了字符流Reader和Writer。
字符流相关常用类如下:

(1).Reader:
用于读取字符串流的抽象类,子类必须实现的方法只有reader(char[],int, int)和close()。

(2).InputStreamReader:
是将字节输入流转换为字符输入流的转换器,它使用指定的字符集读取字节并将其解码为字符。即:字节——>字符。
它使用的字符集可以有名称指定或显式给定,也可以使用平台默认的字符集。

(3).Writer:
用于写入字符流的抽象类,子类必须实现的方法只有write(char[],int, int)和close()。

(4).OutputStreamWriter:
是将字符输出流转换为字节输出流的转换器,它使用指定的字符集将要写入流的字符编码成字节。即:字符——>字节。

4.综合使用Java IO各种流:
Java IO中的各种流,很少单独使用,经常结合起来综合使用,既可以满足特定需求,又搞效。例子如下:
(1).使用缓冲流读取文件:

import java.io.*;  

public class BufferedInputFile{  
    public static String read(String filename) throws IOException{  
        //缓冲字符输入流  
    BufferedReader in = new BufferedReader(new FileReader(filename));  
    String s;  
    StringBuilder sb = new StringBuilder();  
    //每次读取文件中的一行  
    While((s = in.readLine()) != null){  
    sb.append(s + “\n”);  
}  
in.close();  
return sb.toString();  
}  
public static void main(String[] args) throws IOException{  
    System.out.println(read(“BufferedInputFile.java”));  
}  
}  

(2).读取内存中的字符串:

import java.io.*;  

public class MemoryInput{  
    public static void main(String[] args) throws IOException{  
        //将字符串包装为字符输入流  
        StringReader in = new StringReader(  
  BufferedInputFile.read(“BufferedInputFile.java”));  
        int c;  
        //读取字符输入流中的字符  
        while((c == in.read()) != -1){  
    System.out.println((char)c);  
}  
}  
}  

(3).数据输入/输出流:

import java.io.*;  

public class DataInputOutput{  
    public static void main(String[] args) thows IOException{  
        DataOutputStream out = new DataOutputStream(new BufferedOutputStream(  
new FileOutputStream(“Data.txt”)));  
        out.writeDouble(3.14159);  
        out.writeUTF(“That was pi”);  
        out.writeDouble(1.41413);  
        out.writeUTF(“Square root of 2”);  
        out.close();  
        DataInputStream in = new DataInputStream(new BufferedInputStream(  
new FileOutputStream(“Data.txt”)));  
        System.out.println(in.readDouble());  
        System.out.println(in.readUTF());  
System.out.println(in.readDouble());  
        System.out.println(in.readUTF());  
}  
}  
输出结果:
3.14159
That was pi
1.41413
Square root of 2

(4).文本文件输出流:

import java.io.*;  

public class TextFileOutput{  
    //输出文件名  
    static String file = “BasicFileOutput.out”;  
    public static void main(String[] args) throws IOException{  
        //将字符串先包装成字符串输入流,然后将字符串输入流再包装成缓冲字符输入流  
    BufferedReader in = new BufferedReader(new StringReader  
(BufferedInputFile.read(“TextFileOutput.java”)));  
        //字符输出流  
        PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(file)));  
        int lineCount = 1;  
        String s;  
        While((s = in.readLine()) != null){  
    out.println(lineCount++ + “: ” + s);  
}  
out.close();  
}  
}  

(5).二进制文件读写:

import java.io.*;  

public class BinaryFileOutput{  
    //输出文件名  
    static String file = “BinaryFileOutput.out”;  
    public static void main(String[] args) throws IOException{  
        //将字符串先包装成字符串输入流,然后将字符串输入流再包装成缓冲字符输入流  
    BufferedInputStream in = new BufferedInputStream(  
new FileInputStream(“TestFile.png”)));  
        //字符输出流  
        BufferedOutputStream out = new BufferedOutputStream (  
new FileOutputStream(file));  
        byte[] buf = new byte[1024];  
        int n;  
        While((n = in.read(buf)) > 0){  
    out.write(buf, 0, n);  
}  
out.close();  
}  
}  

二、I/O控制

1、标准输入输出流

System.in和System.out分别代表了系统标准的输入和输出设备
默认输入设备是键盘,输出设备是显示器。
System.in的类型是InputStream
System.out的类型是PrintStream,其是OutputStream的子类FilterOutputStream 的子类。
通过System类的setIn,setOut方法对默认设备进行改变。
public static void setIn(InputStream in)
public static void setOut(PrintStream out)

2、转换流

Java API提供了两个转换流,转换流提供了在字节流和字符流之间的转换:

InputStreamReader和OutputStreamWriter
字节流中的数据都是字符时,转成字符流操作更高效。

这里写图片描述

InputStreamReader:用于将字节流中读取到的字节按指定字符集解码成字符。需要和InputStream“套接”。

构造方法:

public InputStreamReader(InputStream in)
public InputSreamReader(InputStream in,String charsetName)

Reader isr = new InputStreamReader(System.in,”ISO5334_1”);

OutputStreamWriter
用于将要写入到字节流中的字符按指定字符集编码成字节。需要和OutputStream“套接”。

构造方法:

public OutputStreamWriter(OutputStream out)
public OutputSreamWriter(OutputStream out,String charsetName)

示例代码:

public void testMyInput() throws Exception{
    FileInputStream fis = new FileInputStream("dbcp.txt");
    FileOutputStream fos = new FileOutputStream("dbcp5.txt");

    InputStreamReader isr = new InputStreamReader(fis,"GBK");
    OutputStreamWriter osw = new OutputStreamWriter(fos,"GBK");

    BufferedReader br = new BufferedReader(isr);
    BufferedWriter bw = new BufferedWriter(osw);

    String str = null;
    while((str = br.readLine()) != null){
        bw.write(str);
        bw.newLine();
        bw.flush();
}

编码:字符串->字节数组
解码:字节数组->字符串

注:从键盘输入的是字节流。可以了解下scanner用法

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值