JavaIO——字符流字节流拷贝文件

  • 什么是字节流,字符流
    File类不支持文件内容处理,如果要处理文件内容,必须要通过流的操作模式来完成。
    在java.io包中,流分为两种:字节流与字符流
    字节流:数据流中最小的数据单元是字节 。InputStream、OutputStream
    字符流:数据流中最小的数据单元是字符, Java中的字符是Unicode编码,一个字符占用两个字节。Reader、Writer

字节流拷贝

拷贝文件的四个步骤

  1. 打开文件
  2. 读取文件内容
  3. 写入文件内容
  4. 关闭连接

import java.io.*;

public class IODemo {
    FileOutputStream fileOutputStream = null;
    FileInputStream fileInputStream = null;

    public void copyImage(){
        try {
            //0.打开文件,用构造方法来指定对象
            //也可以用一个File对象来指定
            //InputStream找不见这个文件会报错
            //OutputStream找不见这个文件会自动创建
            fileInputStream = new FileInputStream("G:\\test.txt");
            fileOutputStream = new FileOutputStream("F:\\test2.txt");
            int len = 0;
            byte[] buffer = new byte[1024]; //    此处的 buffer 都是用户指定的缓冲区, 而 FileInputStream 和 FileOutputStream 内部没有缓冲区..
            
            // 1. 读取玫瑰花文件.
            //    read() 版本是一次读一个字节. 读到的内容会放到返回值中.
            //    read(byte[]) 版本是一次读 N 个字节, N 取决于 byte[] 的长度, 会尽量尝试把数组填满.
            //    read(byte[], int offset, int len) 版本是针对上一个版本的加强版本.           
            while((len=fileInputStream.read(buffer)) != -1){ 
            	//    byte[] 就相当于是用户指定的缓冲区, 返回值表示实际读到的字节数. 如果返回 -1 表示读取结束了
            	// 这样的循环读取就能保证把整个文件都读完.
            	// 这个代码的含义是, 先调用 read, 把返回值写入 len 变量中.
           		// 再拿 len 和 -1 进行比较
                fileOutputStream.write(buffer,0,len);
                // 2. 把文件内容写入到另外一个文件中.
                // write 有三个版本
                // write(int b)  一次写一个字节.
                // write(byte[] buffer) 一次写 N 个字节. 把整个数组中的内容全写进去.
                // write(byte[] buffer, int offset, int len) 第二个版本的加强版.
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                // 读写完成之后, 一定要记得关闭文件.
                // 关闭顺序无所谓.
                // [注意!!!!!!] 这个代码虽然写了 close , 但是仍然存在潜在的问题.
                // close 可能会执行不到!!!!
                //fileInputStream有可能是空指针
                fileInputStream.close();
                fileOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    public static void main(String[] args) throws IOException {
        IODemo ioDemo = new IODemo();
        ioDemo.copyImage();
    }
}

上边的代码是我们按照具体步骤一步一步来的,能清晰地看到每一步执行,但是上边的代码不光复杂,而且会存在潜在的问题
我们可以用另一种方式来写这段代码

public class IODemo2 {

    public void copyImage(){
        try(FileInputStream fileInputStream = new FileInputStream("G:\\test.txt");
            FileOutputStream fileOutputStream = new FileOutputStream("F:\\test.txt")){
            int len = 0;
            byte[] buffer = new byte[1024];
            while((len = fileInputStream.read(buffer)) != -1){
                fileOutputStream.write(buffer,0,len);
            }
        }catch (IOException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) throws IOException {
        IODemo2 ioDemo = new IODemo2();
        ioDemo.copyImage();
    }
}

把打开文件的那步,即构造FileInputStream对象放进try括号中,如果为空程序会自动抛出异常,而且代码执行完毕后,会自动关闭连接,不用我们在手动调用close方法关闭连接了。这样不仅代码整洁,而且可读性和安全性更高。

字符流拷贝

拷贝文件的四个步骤

  1. 打开文件
  2. 读取文件内容
  3. 写入文件内容
  4. 关闭连接
//步骤上基本上和字节流拷贝一样
public class IODemo4 {
    public void copyImage(){
        try(FileReader fileReader = new FileReader("G:\\test.png");
            FileWriter fileWriter = new FileWriter("G:\\test3.png")){
            int len = 0;
            char[] chars = new char[1024];
            while((len = fileReader.read(chars)) != -1){
                fileWriter.write(chars,0,len);
            }
        }catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        IODemo4 ioDemo4 = new IODemo4();
        ioDemo4.copyImage();
    }
}

注意事项

字符流只能拷贝字符数据
字节流只能拷贝字节数据
比如使用字符流去拷贝一张照片就会失败,因为照片是二进制格式储存,不是字符数据,用字符流拷贝会出现乱码,数据丢失等问题。一般只有在拷贝纯文本文件的时候才会使用字符流。

你可能感兴趣的:(java)