字节流(InputStream、OutputStream,FileInputStream,FileOutputStream)

字节流
1.一切皆为字节
在电脑中,一切的文件数据(文本,图片,视频)都是二进制进行存储,是一个一个字节,所以字节流可以传输任何数据

2.字节输出流(OutputStream)---》切输出流的父类,超类
Output输出 stream字节流
OutputStream为一个抽象类,需要子类继承父类,继承其方法,实现抽象方法
方法有:
void close()关闭此输出流并释放与此流相关联的任何系统资源。
void flush() 刷新此输出流并强制任何缓冲的输出字节被写出。
void write(byte[] b)将 b.length字节从指定的字节数组写入此输出流。
void write(byte[] b, int off, int len) 从指定的字节数组写入 len个字节,从偏移 off开始输出到此输出流。
abstract void write(int b) 将指定的字节写入此输出流。
常用子类:BufferedOutputStream , ByteArrayOutputStream , DataOutputStream , FilterOutputStream , InputStream , write(int)


2.1子类FileOutputStream------》将内存中的数据写入到硬盘上的文件
构造方法:
FileOutputStream(String name)
FileOutputStream(File file)
参数:
name:文件路径
file:指定文件
构造方法的作用:
1.创建FileOutputStream对象
2.会根据构造方法中的参数(文件/文件路径),创建一个空的文件
3.将创建好的FileOutputStream对象指向创建的空文件

写入数据的原理(内存-->硬盘)
java程序--》jvm(java虚拟机)--》OS(操作系统)--》OS调用写数据的方法--》把数据写入到文件中去

字节输出流的使用步骤
1.创建一个FileOutputStream对象,构造方法中传递写入数据的目的地
2.调用FileOutputStream对象中的write()方法,将数据写入到文件中
3.释放资源(流的使用会占用一定的内存,使用完毕要将内存清空,提高程序的效率)

写数据的时候会将十进制的整数转化为二进制的整数 fos.write(97) 97-->1100001

任意的文本编辑器(记事本、notepad++)在打开文件的时候,会查询编码表,把字节转化为字符表示
0-127查询ASCII表 97--》a
其他值:查询系统默认码表(中文系统GBK)

/*
* public void write(int b) throws IOException--一次只能写一个字节*/

/*
* public void write(byte b[]) throws IOException--一次写多个字节
* 注意:1.byte[] b 如果第一个字节为正数(0-127),显示时会查询ASCII码
* 2.如果第一个字节为负数,那么第一个字节会和第二个字节组成一个中文显示,查询系统默认码表(GBK)*/

/*
* public void write(byte b[], int off, int len) throws IOException---一次写字符数组中特定长度字节
* int off ---数组的开始索引
* int len--写入字节的长度
*/

/*
* 写入字符的方法,使用string类中的方法,将字符转化为字节数组
* getBytes() 将字符转化为字节数组*/

package iotest.byteIOtest;

import java.io.FileOutputStream;
import java.io.IOException;

public class TestFileOutputStream {
    public static void main(String[] args) throws IOException {
        FileOutputStream fos = new FileOutputStream("C:\\test\\c.txt");
        /*
        * public void write(int b) throws IOException--一次只能写一个字节*/
        fos.write(98);
        fos.write(97);
//        byte[] b = {65,66,67,68,69};
        /*
        * public void write(byte b[]) throws IOException--一次写多个字节
        * 注意:1.byte[] b 如果第一个字节为正数(0-127),显示时会查询ASCII码
        *      2.如果第一个字节为负数,那么第一个字节会和第二个字节组成一个中文显示,查询系统默认码表(GBK)*/
        byte[] b = {-65,-66,-67,68,69};
        fos.write(b);
        /*
        * public void write(byte b[], int off, int len) throws IOException---一次写字符数组中特定长度字节
        * int off ---数组的开始索引
        * int len--写入字节的长度
         */
        fos.write(b,0,2);
        /*
        * 写入字符的方法,使用string类中的方法,将字符转化为字节数组
        * getBytes() 将字符转化为字节数组*/
        byte[] bytes = "你好".getBytes();
        System.out.println(bytes);
        fos.close();
    }
}

 

 

/*追加写/续写--用到两个构造方法
* public FileOutputStream(File file, boolean append)
* public FileOutputStream(String name, boolean append)
* 其中append为追加续写开关,
* 为true时,不覆盖源文件,继续在文件的末尾追加数据
* 为false时,创建的新文件会覆盖源文件 */

/*写换行:写换行符合
* Windows:\r\n
* linux:/n
* mac:/r*/

package iotest.byteIOtest;

import java.io.FileOutputStream;
import java.io.IOException;

public class TestFileOutputStream02 {
    public static void main(String[] args) throws IOException {
        /*追加写/续写--用到两个构造方法
        * public FileOutputStream(File file, boolean append)
        * public FileOutputStream(String name, boolean append)
        * 其中append为追加续写开关,
        * 为true时,不覆盖源文件,继续在文件的末尾追加数据
        * 为false时,创建的新文件会覆盖源文件 */
        /*写换行:写换行符合
        * Windows:\r\n
        * linux:/n
        * mac:/r*/
        FileOutputStream fos = new FileOutputStream("src\\iotest\\byteIOtest\\a.txt",true);
        for (int i = 0; i < 10; i++) {
            fos.write("你好".getBytes());
            fos.write("\r\n".getBytes());
        }

        fos.close();
    }
}

 

3.字节输入流(InputStream)----》将硬盘上文件的数据,读取到内存中使用
InputStream是所有自己输入流的超类(父类),都要继承该类

读取数据的原理:
java程序-->JVM--》OS--》OS读取数据的方法--》读取文件数据

FileInputStream:
字节输入流的使用步骤(重点):
1.创建FileInputStream对象,构造方法中要绑定要读取的数据源
2.使用FileInputStream对象中的read方法,来读取文件(指针会指向文件的第一个字节,read方法运行后,指针会跳到下一个字节)
3.释放资源(close)


3.1一次读取一个字节的方法:


public int read() throws IOException---》读取文件中一个字节,并返回读取到的字节

读取文件是一个重复的过程,可以循环优化
但不知循环次数,可用while循环
循环结束的条件是读取到-1结束

package iotest.byteIOtest;

import java.io.FileInputStream;
import java.io.IOException;

public class TestFileInputStream {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("src\\iotest\\byteIOtest\\a.txt");
//        int read = fis.read();
//        System.out.println(read);
        int len =0;
        while ((len = fis.read()) != -1) {
            System.out.println((char) len);
        }
        fis.close();
    }
}

 

3.2一次读取多个字节的方法:


public int read(byte b[])---》一次读取多个字节,放到字节数组b内,并返回这次读取到的字节个数

byte b[]:起缓冲作用,存储每次读取到的多个字节(数组的长度一般定义为1024(1kb)或者是1024的整数倍)

这儿也可以用while循环进行优化,循环结束的条件是读取到-1结束

string的构造方法:
public String(byte bytes[]):将字节数组转化为字符串
public String(byte bytes[], int offset, int length) :将字节数组部分转化为字符串,offset为开始索引,length为长度,也就是要转换的字节个数

package iotest.byteIOtest;

import java.io.FileInputStream;
import java.io.IOException;

//字节输入流,一次读取多个字节的方法
public class TestFileInputStream02 {
    public static void main(String[] args) throws IOException {
        FileInputStream fis = new FileInputStream("src\\iotest\\byteIOtest\\a.txt");
        byte[] b = new byte[1024];
        int len = 0;
        while ((len = fis.read(b)) != -1){
            System.out.println(len);
            System.out.println(new String(b,0,len));//如果这儿用new String(b),后面还有很多空格
        }
        fis.close();
    }
}

 

综合使用:
文件的复制(一读一写)
明确:数据源(FileInputStream创建时的文件地址)数据存储的目的地(FileOutputStream创建时的文件地址)
步骤:
1.创建FileInputStream对象,构造方法中要绑定要读取的数据源
2.创建FileOutputStream对象,构造方法中要绑定要写入的数据源
3.使用FileInputStream对象中read方法读取文件
4.使用FileOutputStream对象中write方法写入文件
5.释放资源(先关闭写入,后关闭读,因为读完不一定写完,但写完一定读完)

package iotest.byteIOtest;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class CopyFile {
    public static void main(String[] args) throws IOException {
        long startTime = System.currentTimeMillis();
        FileInputStream fis = new FileInputStream("C:\\test\\MAH05314.MP4");
        FileOutputStream fos = new FileOutputStream("D:\\test\\copyView2.MP4");
       /*
       * 一个字节一个字节读,面对较大文件,效率较低*/
       /* int len = 0;
        while ((len = fis.read()) != -1){
            fos.write(len);
        }*/
        /*运用数组缓冲,一个字节数组一个字节数组的读,效率较高*/
        byte[] bytes = new byte[10240];
        int len = 0;
        while ((len = fis.read(bytes)) != -1){
            fos.write(bytes,0,len);
        }
        //先关写入流,再关读取流
        fos.close();
        fis.close();
        long endTime = System.currentTimeMillis();
        System.out.println("文件复制共用了"+(endTime-startTime)+"毫秒!");

    }
}

注意:如果用字节流来读取中文文件时,可能会出现乱码现象

一个中文:使用GBK编码:占2个字节

                使用UTF-8编码:占3个字节

比如:在一个文本文件中,utf-8编码,一个字节一个字节读的话,需要三次读,这样将一个中文分成三个其他编码文字。

解决方法:使用字符流

posted @ 2020-07-29 16:09  DannyBoy~  阅读(909)  评论(0)    收藏  举报