天天看点

Java IO流

I/O流

Java IO流

按照流向可以分为输入流和输出流;按照操作单元来分的话,可以分为字节流和字符流;按照流的角色来划分的话,可以划分为节点流和处理流;

  • InputStream(输入)/Reader(读入):所有的输入流的基类,前者是字节输入流,后者是字符输入流。
  • OutputStream(输出)/Writer(写出):所有输出流的基类,前者是字节输出流,后者是字符输出流。
Java IO流

节点流

直接从数据源或者目的地读写数据;

Java IO流

节点流(文件流)

节点流的作用在于将一个已存在的文件,加载到程序中,从而进行操作,或者写出流到文件中;

读取文件

// 1、建立一个流对象,将一个已经存在的文件加载进流
FileReader fr = new FileReader("hello.txt");
// 2、创建一个临时存放数据的数组
char [] buffer = new char[1024];
// 3、用数组盛放入进来的文件流
fr.read(buffer);
// 4、关闭资源
fr.close();
           

代码:

FileReader fr = null;
try{
    // 这里需要注意的是,当在 main 方法中时,那么我们的当前路径就是当前的工程路径;
    // 如果是单元测试方法,那么当前路径就是相对于我们当前 model 的;
    fr = new FileReader("C:\\hello.txt");
    char [] buffer = new char[1024];
    int len;
    while ((len = fr.read()) != -1){
        System.out.println(new String(buffer,0,len));
    }catch(IOException e){
        System.out.println("捕获异常:" + e.getMessage());
    }finally{
        if(fr != null){
            try{
                fr.close();
            }catch(IOException e)
                System.out.println("捕获异常:" + e.getMessage());
        }
    }
}
           

写入文件

定义文件路径时,可以使用"/"或者"\"。

在写入一个文件时,使用构造器 FileOutputStream(file),则会覆盖写文件;使用构造器 FileOutputStream(file,true),则会追加文件内容。

// 1、创建流对象,建立数据存放文件
FileWriter fw = new FileWriter("hello.txt");
// 2、调用流对象的写入方法,将文件写入流
fw.write("hello java,hello world");
// 3、关闭资源文件,并将流中的数据清空到文件中
// fw.flus();
fw.close();
           
FileWriter fw = null;
try{
    fw = new FileWriter("hello.txt");
    fw.write("hello world");
}catch(Exception e){
    e.printStackTrace();    
}finally{
    try{
        if(fw != null){
            fw.close();
        }
    }catch(IOException e){
        System.out.println(e.getMessage());
    }
}
           

处理流

不能直接连接到数据源或目的地,而是“连接”在已存在的流(节点流或处理流)之上,通过对数据的处理为程序提供更为强大的读写功能;

Java IO流

处理流之缓冲流

缓冲流要套接在相应的节点流之上,根据数据操作单位可以把缓冲流分为

BufferedInputStream

BufferedOutputStream

BufferedReader

BufferedWriter

。为了提高读写的速度,在使用这些流类的时候,会创建一个内部缓冲区数组,默认使用 8 k大小的缓冲区。缓冲流要套接在相应的节点流上。

  • 当使用 BufferedInputStream 读取文件的时候,他会一次性在文件中读取 8 K大小的字节,存到缓冲区,缓冲区满的时候,才从文件中读取下一个 8 K;
  • 向文件中写入数据字节时,不会直接写入,而是先写满缓冲区,再将缓冲区的数据一次性的写到文件中。使用 flush( ) 方法可以一强制将缓冲区的内容全部写入文件;
  • 关闭流时,只需要关闭最外层流即可,关闭最外层流也会关闭相对应的内层节点流;
  • 如果是带有缓冲区的流对象的 close( ),方法,会在关闭流之前进行刷新缓存区。关闭之后就不能进行写出操作;

图解:

Java IO流
BufferedReader br = null;
bufferedWriter bw = null;
try{
    br = new BufferedReader(new FileReader("D:\\hello.txt"));
    bw = new BufferedWriter(new FileWriter("D:\\hi.txt"));
    String str = null;
    while((str = br.readLine()) != null){
        bw.write(str);
        bw.newLine(); // 写入分隔符
    }
    bw.flush(); // 刷新缓存区,将缓存区的内容一次性全部写入文件
}catch(IOException e){
    System.out.println(e.getMessage());
}finally{
    // 关闭资源 在这里关掉最外层的即可
    try{
        if(br != null){
            br.close();
        }
    }catch(IOException e){
        System.out.println(e.getMessage());            
    }
    try{
        if(bw != null){
            bw.close();
        }
    }catch(IOexception e){
        System.out.println(e.getMessage());
    }
}
           

处理流之转换流

转换流,提供了在字节流和字符流之间的转换方法;

  • InputStreamReader:将 InputStream 转换为 Reader,将字节转换为字符;
  • OutputStreamWriter:将 Writer 装换为 OutputStream,将字符转换为字节;

字节流中的数据都是字符时,转成字符流操作更高效,我们会经常使用转换流处理文件乱码问题。实现编码和解码功能;

Java IO流
// 构造器

// 输入
public InputStreamReader(InputStream is);
public InputStreamReader(InputStream is,"gbk"); // 指定字符集

// 输出
public OutputStreamWirter(OutputStream os);
public OutputStreamWirter(OutputStream os,"utf-8"); // 指定字符集
           

代码

// 文件输入输出流
FileInputStream fis = new FileInputStream("hello.txt");
FileOutputStream fos = new FileOutputStream("helloCopy.txt");
// 处理流-转换流
InputStreamReader isr = new InputStreamReader(fis,"gbk");
OutputStreamWriter osw = new OutputStreamWriter(fos,"utf-8");
// 处理流-缓冲流
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();
}
// 关闭流操作
try{
    if(br != null){
        br.close();
    }	
}catch(IOException e){
    System.out.println(r.getMessage());
}

try{
    if(bw != null){
        bw.close();
    }
}catch(IOException e){
    System.out.println(e.getMessage());
}

           
System.in 和 System.out 分别代表了系统标准的输入和输出设备,System.in 的类型是 InputStream;System.out 的类型是 PrintStream,是OutputStream 的子类

处理流之对象流

ObjectInputStream 和 ObjectOutputStream ,分别用于反序列化读取和序列化保存基本数据类型或者对象。但是不能序列化 static 或 transient 修饰的成员变量

序列化:可以将任何实现了 Serializable 接口的对象转化为字节数据,使其在保存和传输时可被还原。(实现对象平台无关性)

序列化:写出

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("data.txt"));
Person person = new Person("zhangsan",15);
oos.write(p);
oss.flush();
oss.close();
           

反序列化:读入

ObjectInputStream ois = new ObjectInputStream(new FileInputStream("data.txt"));
Person person = (Person) ois.readObject();
String str = person.toString();
System.out.println(str);
ois.close();
           

输入流

InputStream 和 Reader

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 )

用来读取字符;

输出流

OutputStream 和 Writer

OutputStream 和 Writer 是相对应的字节输出流和字符输出流

先 flush( ) 刷新后,再关闭流;flush 操作会刷新输出流并强制写出所有缓冲的输出字节或字符

FileOutputStream,用于写出字节文件(非文本类型文件);

FileWriter,用于写出字符类型的文件(文本文件);