Java——I/O(字节流、字符流与转换流 )

 

目录

字节流和字符流

1. 流操作流程

2. 字节输出流(OutputStream)

2.1 输出方法

3. 自动关闭支持AutoCloseable-JDK1.7

4. 字节输入流(InputSream)

4.1 输入方法 

5. 字符流

5.1 字符输出流(Writer)

5.2 字符输入流(Reader)

6. 字节流与字符流

7. 转换流


字节流和字符流

字节流(byte):InputStream、OutputStream 

字符流(char):Reader、Writer

  • 字节流与字符流的区别:

字节流是原生的操作,而字符流是字节流经过处理后的操作。

  • 一般使用字节流——无论是网络传输还是磁盘的数据保存均以字节为单位,只有处理中文文本时才会用到字符流。

1. 流操作流程

  • 输入流:
  1. 准备文件
  2. 实例化FileInputSream对象
  3. read()读取数据
  4. 业务处理数据
  5. 关闭输入流-finally
  • 输出流:
  1. 准备文件,文件不存在自动创建,但是目录一定要存在
  2. 实例化FileOutputSream对象
  3. 业务处理数据
  4. write()输出数据
  5. 关闭输出流-finally
  • 业务处理

    读取数据 -> while( ){ },读到末尾返回-1

package com.qqy.io;

import java.io.*;
import java.nio.file.Paths;

/**
 * 将文件当作输入流,读取内容并处理,再输出到另一个文件中
 * Author: qqy
 */
public class Test {
    public static void main(String[] args) {
        File inputFile = Paths.get("E:" , "JAVA" ,"input.txt").toFile();
        File outputFile = Paths.get("E:" , "JAVA" ,"output.txt").toFile();
        
        if(!outputFile.getParentFile().exists()){
            outputFile.getParentFile().mkdirs();
        }
        
        FileInputStream ins=null;
        FileOutputStream out=null;
        try {
            ins=new FileInputStream(inputFile);
            //输出流中的内容向后追加
            //out=new FileOutputStream(outputFile,true);
            //默认false,不追加
            out=new FileOutputStream(outputFile);
            //若读取结束,则返回-1
            int value=-1;
            //输入
            //从输入流读取数据的下一个字节
            while((value=ins.read())!=-1){
                //将大写变为小写
                value= value +32;
                //输出
                out.write(value);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally{
            if(ins!=null) {
                //关闭数据流
                try {
                    ins.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if(out!=null) {
                try {
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
  • I/O操作属于于资源处理,所有的资源处理操作(IO操作、数据库操作、网络)使用后必须要进行关闭。 

2. 字节输出流(OutputStream)

public abstract class OutputStream implements Closeable, Flushable
//Closeable接口: 
public void close() throws IOException; 
//Flushable接口: 
public void flush() throws IOException;
  • 2.1 输出方法

//将给定的字节数组内容全部输出
public void write(byte b[]) throws IOException 
//将部分字节数组内容输出
public void write(byte b[], int off, int len) throws IOException 
//输出单个字节
public abstract void write(int b) throws IOException;
  • 要进行文件内容的输出,使用FileOutputStream()
//文件内容覆盖
public FileOutputStream(File file) throws FileNotFoundException 
//文件内容追加
public FileOutputStream(File file,boolean append) throws FileNotFoundException 
  • 当使用FileOutputStream进行文件内容输出时,只要文件父路径存在,FileOutputStream会自动创建文件
import java.io.*;

/**
 * 字节输出流
 * Author: qqy
 */
public class Test {
    public static void main(String[] args) throws IOException {
        //1.取得终端对象
        File file = new File("E:"+File.separator+"JAVA"+File.separator+"Test.txt");
        //只要文件父路径存在,FileOutputStream会自动创建文件
        //OutputStream为抽象方法,需要借用子类进行实例化
        OutputStream out =null;
        OutputStream out1 =null;
        //2.取得终端对象的输出流
        try {
            out = new FileOutputStream(file);
            //允许内容的追加
            out1 = new FileOutputStream(file,true);
            //3.进行数据的输出
            String msg="你好世界!!!\r\n";
            //当出现中文时,最好全部输出,避免出现乱码
            out.write(msg.getBytes(),0,6);  //你好
            out1.write(97); //a
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }catch (IOException e) {
            e.printStackTrace();
        }finally{
            //4.关闭流
            out.close();
            out1.close();
        }
    }
}

3. 自动关闭支持AutoCloseable-JDK1.7

  • 使用前提:结合try...catch...
/**
 * 自动关闭
 * Author: qqy
 */
public class Test1 {
    public static void main(String[] args) {
        //try-with-resources 
        //实现AutoCloseable接口后,对资源的一些释放、关闭,JVM可以自动调用close()
        //try(实例化对象的代码,实例化对象的类实现AutoCloseable接口)
        //实例化多个对象时,用分号隔开,最后一个不用加分号
        try(Msg msg1=new Msg()
        ){
            //自动调用close()
            msg.print();  //normal method...   auto close...
        }catch (Exception e){

        }
    }
}

class Msg implements AutoCloseable{

    @Override
    public void close() throws Exception {
        System.out.println("auto close...");
    }

    public void print(){
        System.out.println("normal method...");
    }
}

4. 字节输入流(InputSream)

public abstract class InputStream implements Closeable
  • 4.1 输入方法 

//读取数据到字节数组b中
public int read(byte b[]) throws IOException 
//读取单个字节
public int read() throws IOException 
  • 返回值:

返回b长度:读取数据大小>字节数组大小,返回字节数组大小

返回大于0但是小于b长度:读取数据大小<字节数组大小,返回真正读取个数

返回-1:数据读取完毕

import java.io.*;

/**
 * 字节输入流和输出流的缓存方式读取和写入
 * Author: qqy
 */
public class Test{
     public static void main(String[] args) throws IOException {
        //1.取得File对象
        File file = new File("E:" + File.separator + "JAVA" + File.separator + "input.txt");
        File destFile = new File("E:" + File.separator + "JAVA" + File.separator + "output.txt");
        //2.取得输入流、输出流
        InputStream in = null;
        OutputStream out = null;
        try {
            in = new FileInputStream(file);
            out = new FileOutputStream(destFile);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        //3.读取文件内容、写入内容
        byte[] data = new byte[5];
        int value = -1;
        try {
            //从输入流读取数据的一些字节数,并将其存储到缓冲区data
            //每次循环,先开辟一个长度为5的数组,读取文件中从头开始的3个字节,放入该数组的第1个位置
            // value存放每次读的内容的长度,b是每次数组中存放的内容
            while ((value = in.read(data, 1, 3)) != -1) {
                System.out.println(value);    //3  1
                System.out.println(new String(data));  // ABC   DBC

                out.write(data);  //写入为ABCDBC
                //缓冲方式写数组的时候,偏移量为0,res为每一批读的数据的量
                out.write(data, 0, value);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        //4.关闭流
        in.close();
        out.close();
    }

}

5. 字符流

  • 5.1 字符输出流(Writer)

实现了Closeable接口,可以自动关闭

public abstract class Writer implements Appendable, Closeable, Flushable

除了参数为字符数组外,多了一个传入String对象的方法

public void write(String str) throws IOException
import java.io.*;

/**
 * 字符输出流
 * Author: qqy
 */
public class Test3 {
    public static void main(String[] args) throws IOException {
        //1.取得File对象
        File file = new File("E:"+File.separator+"JAVA"+File.separator+"Test.txt");
        //2.取得输出流
        Writer writer=new FileWriter(file);
        //3.写入数据
        String str="你好 Bonjour !!";
        writer.write(str);
        writer.write(new char[]{'a','b','c','\n'});
        writer.write(new char[]{'A','B','C'},2,1);
        //4.关闭流
        writer.close();
    }
}
  • 5.2 字符输入流(Reader)

Reader类中没有方法可以直接读取字符串,只能通过字符数组来读取

import java.io.*;

/**
 * 字符输入流
 * Author: qqy
 */
public class Test4 {
    public static void main(String[] args) throws IOException {
        //1.取得File对象
        File file = new File("E:"+File.separator+"JAVA"+File.separator+"Test.txt");
        //2.取得输入流
        Reader reader= new FileReader(file);
        //3.读取数据
        char[] data=new char[1024];
        int result=reader.read(data);
        System.out.println(result);
        System.out.println(new String(data,0,result));
        //4.关闭流
        reader.close();
    }
}

6. 字节流与字符流

  • 开发中,优先考虑字节流,只有处理中文时才考虑使用字符流。
  • 所有字符流操作,无论是写入还是输出,数据都先保存在缓存中——字符输出流不关闭,文件中无内容;字节输出流不关闭,文件中有内容。
  • 想要将字符输出流在文件中显示,要么正常关闭—out.close(),要么强制清空缓存区—out.flush()

练习:文件复制(字节流)

import java.io.*;
import java.nio.file.Paths;

/**
 * 文件复制
 * Author: qqy
 */
public class Test6 {
    public static void main(String[] args) throws IOException {
        String src="";
        String dest="";
        long start=System.currentTimeMillis(); //毫秒数
        copy(src,dest);
        long end=System.currentTimeMillis();
        System.out.println(end-start/1000+"s");  //秒数
    }

    public static void copy(String srcFilePath,String destFilePath){
        //参数校验
        if (srcFilePath==null||srcFilePath.isEmpty()) {
            throw new IllegalArgumentException("srcFilePath not null/empty!");
        }
        if (destFilePath==null||destFilePath.isEmpty()) {
            throw new IllegalArgumentException("destFilePath not null/empty!");
        }

        File srcFile =Paths.get(srcFilePath).toFile();
        File destFile =Paths.get(destFilePath).toFile();
        //文件校验以及准备工作
        if(!srcFile.exists()||!srcFile.isFile()){
            throw new IllegalArgumentException("srcFilePath not exists or not file!")
        }

        File parentFile= destFile.getParentFile();
        if(!parentFile.exists()){
            if(!parentFile.mkdirs()){
                throw new RuntimeException("can't create"+parentFile.getAbsolutePath()+"directory");
            }
        }

        //文件复制
        try(FileInputStream in=new FileInputStream(srcFile);
            FileOutputStream out =new FileOutputStream(destFile)
        ){
          //缓冲数组
          //引入缓冲区
          byte[] buff = new byte[1024];  //1k,2k,4k,8k
          int len=-1;
          //一次只读一个字节,再输出一个字节
          while((len=in.read(buff))!=-1){
              //为了避免数据读取不全,使用下列方式进行写入
              out.write(buff,0,len);
          }
        }catch(IOException e){
            System.out.println(e.getMessage());
        }
    }
}

7. 转换流

字节流—>字符流,用于将底层的字节流转为字符流供子类使用

OutputStreamWriter:字节输出流—>字符输出流

InputStreamReader:字节输入流—>字符输入流

import java.io.*;

/**
 * 转换流
 * Author: qqy
 */
public class Test7 {
    public static void main(String[] args) throws IOException {
        //1.取得文件对象
        File file = new File ("E:"+File.separator+"JAVA"+File.separator+"Test.txt");
        //2.取得输出流
        OutputStream outputStream=new FileOutputStream(file);
        //3.字节流变为字符流,注意编码格式
        OutputStreamWriter out=new OutputStreamWriter(outputStream);
        out.write("你好 Bonjour");
        //4.关闭流
        out.close();
    }
}

 

你可能感兴趣的:(JavaSE)