java语言中的 BIO 流

java语言中的 BIO 流


一、流

(1)流的分类

1)根据数据传输的方向划分:
  输入流:(得到数据)从文件中获取数据;
  输出流:(输出数据)将数据保存到文件中。
2)根据读写数据的单位划分:
  字节流:也称万能流,以字节为单位,可以读写所有数据;
  字符流:以字符为单位,只能读写文本数据。
3)根据功能划分:
  基础流:具有实际传输数据的读写功能;
  包装流:在基础流的基础之上增强功能。

(2)File类:操作文件及目录(也叫文件夹)的类

1)File类一些方法的使用
public class Demo01 {
    public static void main(String[] args) {
    
		//相对路径:相对于项目底下的路径
		//File file = new File("File01.txt");
		//绝对路径:文件完整的路径(从盘符开始)
		//File file = new File("E:/test/File02.txt");

        File file = new File("File.txt");
        System.out.println("是否为文件:"+file.isFile());
        System.out.println("文件名:"+file.getName());
        System.out.println("相对路径:"+file.getPath());
        System.out.println("绝对路径:"+file.getAbsolutePath());
        System.out.println("文件是否可读:"+file.canRead());
        System.out.println("文件是否可写:"+file.canWrite());
        System.out.println("文件是否隐藏:"+file.isHidden());
    }
}
2)目录结构存在的情况下创建文件
public class Test {
    public static void main(String[] args) {
        try {
        	//前提是E盘中已经存在名为 “File” 的文件夹
            File file = new File("E:\\File\\file.txt");
            //判断文件夹中是否已经存在名为 “file.txt” 的文件
            if(!file.exists()){
                //如果不存在就创建名为 “file.txt” 的文件
                file.createNewFile();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
3)当前对象的父目录结构不存在的情况下创建文件
public class Test {
    public static void main(String[] args) {
        try {
            File file = new File("E:\\File\\File\\file.txt");
            //创建父目录结构
            //获取父目录的对象  ---  E:\\File\\File
            File parentFile = file.getParentFile();
            //判断父目录是否存在
            if(!parentFile.exists()){
                //创建单层父目录
                parentFile.mkdir();
                //创建多层父目录
                //parentFile.mkdirs();
            }
            //判断文件是否存在
            if(!file.exists()){
            	//创建文件
                file.createNewFile();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
4)输出所有文件及目录的绝对路径的方法
	//输出所有文件及目录的绝对路径的方法
    private static void aaa(File file) {
        File[] files = file.listFiles();
        //foreach遍历
        for (File file01:files) {
        	//判断是否为文件
            if (file01.isFile()) {
                System.out.println(file01);
            }else {
            	//使用递归一层一层的遍历文件夹
                aaa(file01);
                System.out.println(file01);
            }
        }
    }
5)删除文件及目录
//因为File流的删除方法只能删除文件夹里面为空的文件夹
//所以下面写了一个方法,一层一层的遍历文件夹,直到找到文件或者文件夹里面为空的文件夹,然后一层一层的往回删除
	private static int bbb(File file) {
        int flag = 0;
        File[] files = file.listFiles();
        for (File file01:files) {
            //如果是文件或者文件夹为空就删除
            if (file01.isFile() || file01 == null) {
                file01.delete();
                flag = 1;
            }else {
                //使用递归一层一层的遍历文件夹
                bbb(file01);
                file01.delete();
                flag = 1;
            }
        }
        file.delete();
        return flag;
    }
6)使用过滤器输出指定目录下的所有以.txt结尾的文件
public class Test {
    public static void main(String[] args) {
        File file = new File("F:\\File");
        //使用匿名内部类实现并重写FileFilter接口
        File[] files = file.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                //判断是否是文件
                if(pathname.isFile()){
                    //f.getName()输出的是所有的文件名
                    //endsWith()限制输出的内容
                    if(pathname.getName().endsWith(".txt")){
                        return true;
                    }
                }
                return false;
            }
        });
        for (File f:files) {
            System.out.println(f.getName());
        }
    }
}

二、字节流:针对任何文件

字节流字节输出流字节输入流描述
字节抽象类OutputStreamInputStream字节输出 / 输入流的基类
字节节点流FileOutputStreamFileInputStream文件字节输出 / 输入流
字节缓冲流BufferedOutputStreamBufferedInputStream带缓冲区的字节输出 / 输入流,
只有关流或者缓冲区满了,缓冲区的数据才会保存到文件中
对象流ObjectOutputStreamObjectInputStream实体类需要实现序列化接口,拥有序列号,
输出是序列化,输入是反序列化
内存流ByteArrayOutputStreamByteArrayInputStream针对临时文件,存放的数据小,效率高
打印流PrintStream没有输入,只有输出,
直接打印数据,是输出信息最方便的类
随机访问流RandomAccessFileRandomAccessFile拥有指针,原始数据会被覆盖不会被清空,
读取和写入使用的都是同一个类

(1)字节抽象类:InputStream、OutputStream

(2)字节节点流:FileOutputStream、FileInputStream

1)读取文件中的单个字节
public class Test {
    public static void main(String[] args) {
        try {
            FileInputStream fis = new FileInputStream("F:\\File\\File.txt");
            //读取一个字节
            int read = fis.read();
            System.out.println((char)read);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
2)多个字节读取整个文件
public class Test {
    public static void main(String[] args) {
        FileInputStream fis = null;
        try {
            fis = new FileInputStream("File.txt");
            //定义一个byte类型的数组当缓冲区
            byte[] b = new byte[100];
            int len;
            //fis.read(b)返回的是写入缓冲区的字节总数
            while((len = fis.read(b)) != -1){
                //第一个参数为存放数据的缓冲区
                //第二个参数为偏移量
                //第三个参数为缓冲区中的数据长度
                System.out.println(new String(b,0,len));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //关流    --  释放资源
            if(fis != null){
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
3)将数据写入到磁盘文件中
public class Test {
    public static void main(String[] args) {
        FileOutputStream fos = null;
        try {
            //如果没有这个文件,实例化对象的时候会自动创建文件,true表示在文件末尾追加数据
            fos = new FileOutputStream("IO.txt",true);
            //写入字符串“good”,getBytes()方法把String类型的数据转换成byte类型的数组
            fos.write("good".getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(fos != null){
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
4)字节流的拷贝(可以拷贝任何文件)
//从一个txt文本拷贝到另一个txt文本
public class Demo01 {
    public static void main(String[] args) {
        FileInputStream fis = null;
        FileOutputStream fos = null;
        int len;
        byte[] b = new byte[100];
        try {
            fis = new FileInputStream("File01.txt");
            fos = new FileOutputStream("File02.txt");
            //用while循环从文件"File01.txt"中读取数据,暂时保存在byte数组中,再写入到"File02.txt"文件中
            while ((len = fis.read(b)) != -1){
                fos.write(b,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //自定义释放资源工具类
            IOUtil.closeAll(fis,fos);
        }
    }
}

(3)字节缓冲流:BufferedOutputStream、BufferedInputStream

  • 提高IO效率,减少访问磁盘的次数。
  • 数据存储在缓冲区中,flush是将缓存区的内容写入文件中,也可以直接close。
1)带缓冲区的字节输出流
public void test01() throws IOException {
        //带缓冲区的字节输出流
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("IO1.txt"));
        bos.write("good good study day day up!".getBytes());
        bos.close();
    }
2)带缓冲区的字节输入流
public void test02() throws IOException {
        //带缓冲区的字节输入流
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream("IO1.txt"));
        byte[] b = new byte[1024];
        int len;
        while( (len = bis.read(b)) != -1){
            System.out.println(new String(b,0,len));
        }
        bis.close();
    }

(4)对象流:ObjectInputStream、ObjectOutputStream

对象流写入对象信息:序列化 - - - 把对象转换成字节序列的成程;
对象流读取对象信息:反序列化 - - - 把字节序列恢复成对象的过程。

私有的transient属性不会被序列化,如:private transient int id;
私有的static属性不会被序列化,如:private static int id。

1)把对象存进集合中,再把集合写入文件中
	public void aaa() throws Exception {
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("File.txt"));
        ArrayList<Student> arr = new ArrayList();
        arr.add(new Student("aa",11));
        arr.add(new Student("bb",22));
        arr.add(new Student("cc",33));
        oos.writeObject(arr);
        oos.close();
    }
2)读取集合,遍历并输出
	public void bbb() throws Exception{
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("File.txt"));
        ArrayList<Student> arr = (ArrayList<Student>)ois.readObject();
        for (Student student : arr){
            System.out.println(student);
        }
        ois.close();
    }

(5)内存流:ByteArrayOutputStream 、ByteArrayInputStream

针对临时文件,存放的数据小,效率高

内存流的读写操作:
@org.junit.Test
    public void ddd() throws Exception {
        //创建内存输出流对象
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        //写到内存中
        bos.write("aaa".getBytes());
        //toByteArray()获取存放在内存中的字节数组
        byte[] bytes = bos.toByteArray();
        //把内存中的数据写入到指定文本文件中
        bos.writeTo(new FileOutputStream("File.txt"));
        int c;
        //创建内存输入流对象
        ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
        while((c = bis.read()) != -1) {
            System.out.println((char) c);
        }
        //内存流无法关闭
        bos.close();
    }

(6)打印流:PrintStream

public class Demo01 {
    public static void main(String[] args) throws Exception {
        PrintStream ps = new PrintStream(new FileOutputStream("File.txt"));
        //打印流独有的方法  --  直接打印数据(原样保存到文件中)
        ps.println(97);
        ps.println("a");
        ps.println(true);
        ps.close();
    }
}

(7)随机访问流:RandomAccessFile

1)从文件指定位置处写入数据
	//从文件指定位置处写入数据
    @Test
    public void test02() throws Exception {
        RandomAccessFile rw = new RandomAccessFile("File.txt", "rw");
        //设置偏移量,从文件中第6位开始写入
        rw.seek(6);
        //写入的位置后面的数据都会被覆盖
        rw.write("Hello".getBytes());
        rw.close();
    }
    //文本里原始的内容:RandomAccessFile
    //写入后文本里的内容:RandomHellosFile
2)从文件指定位置处读取数据
	//从文件指定位置处读取数据
    @Test
    public void test04() throws Exception {
        RandomAccessFile r = new RandomAccessFile("File.txt", "r");
        //设置偏移量,从文件中第6位开始读取
        r.seek(6);
        byte[] b = new byte[1024];
        int len;
        while( (len = r.read(b)) != -1){
            System.out.println(new String(b,0,len));
        }
        r.close();
    }
	//文本里原始的内容:RandomAccessFile
    //控制台显示的内容:AccessFile
3)利用随机访问流实现的断点续传功能
	//断点续传
    @Test
    public void test05() throws Exception {
        //源文件的对象
        RandomAccessFile r = new RandomAccessFile("E:\\hello.mp4", "r");
        //目标文件的对象
        RandomAccessFile rw = new RandomAccessFile("F:\\hello.mp4", "rw");
        //源文件和目标文件进行读写操作之前设置指针的位置(目标文件的长度)
        r.seek(rw.length());
        rw.seek(rw.length());
        byte[] b = new byte[100];
        int len;
        while( (len = r.read(b)) != -1){
            rw.write(b,0,len);
        }
        r.close();
        rw.close();
    }

三、常见的字符编码

编码说明
ISO-8859-1收录除ASCII外,还包括西欧、希腊语、泰语、阿拉伯语、希伯来语对应的文字符号。
UTF-8针对Unicode的可变长度字符编码。
GB2312简体中文。
GBK简体中文、扩充。
BIG5台湾,繁体中文。
注:当编码方式和解码方式不一致时,会出现乱码。

四、字符流:只针对文本数据

字符流字符输出流字符输入流描述
字符抽象类WriterReader字符输出 / 输入流的基类
字符节点流FileWriterFileReader文件字符输出 / 输入流
字符缓冲流BufferedWriterBufferedReader带缓冲区的字节输出 / 输入流,
只有关流或者缓冲区满了,缓冲区的数据才会保存到文件中
打印流PrintWriter没有输入,只有输出,
直接打印数据,是输出信息最方便的类
转换流OutputStreamWriterInputStreamReader前者是把程序中的字符转换成文件中的字节 ,
后者是把文件中的字节转换成程序中的字符,
可以针对不同编码格式的文件进行读写操作

(1)字符抽象类:Reader、Writer

(2)字符节点流:FileReader、FileWriter

1)读取单个字符
public class Test {
    public static void main(String[] args) {
        FileReader fr = null;
        try {
            fr = new FileReader("F:\\File\\File.txt");
            int read = fr.read();
            //因为读取到的数据是ASCALL码,所以要强转为字符型
            System.out.println((char)read);
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            IOUtil.closeAll(fr);
        }
    }
}
2)读取多个字符
public class Test {
    public static void main(String[] args) {
        FileReader fr = null;
        try {
            fr = new FileReader("F:\\File\\File.txt");
            //因为字符流读取的是字符,所以使用char类型数组
            char[] c = new char[100];
            int len;
            while( (len = fr.read(c)) != -1){
                System.out.println(new String(c,0,len));
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            IOUtil.closeAll(fr);
        }
    }
}
3)使用字符流写入数据
public class Test {
    public static void main(String[] args) {
        FileWriter fw = null;
        try {
            fw = new FileWriter("F:\\File\\File.txt");
            fw.write("hello");
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            IOUtil.closeAll(fw);
        }
    }
}
4)字符流的拷贝(只能拷贝文本文件)
//从一个txt文本拷贝到另一个txt文本
public class Demo01 {
    public static void main(String[] args) {
        FileReader fr = null;
        FileWriter fw = null;
        int len;
        char[] ch = new char[100];
        try {
            fr = new FileReader("File.txt");
            fw = new FileWriter("File2.txt",true);
            while ((len = fr.read(ch)) != -1){
                fw.write(ch,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //自定义释放资源工具类
            IOUtil.closeAll(fr,fw);
        }
    }
}

(3)字符缓冲流:BufferedReader、BufferedWriter

1)字节缓冲流的读取
public class Test {
    public static void main(String[] args) throws Exception {
        //1、创建缓冲流
        BufferedReader br=new BufferedReader(new FileReader("File.txt"));
        //2、读取,一行一行的读取
        String str=null;
        while((str= br.readLine()) != null) {
            System.out.println(str);
        }
        //3关流,释放资源
        br.close();
    }
}
2)字节缓冲流的写入
public class Test {
    public static void main(String[] args) throws Exception {
        //1创建BufferedWriter对象
        BufferedWriter bw=new BufferedWriter(new FileWriter("File.txt"));
        //2写入数据
        bw.write("hello");
        //3关流,释放资源
        bw.close();
    }
}
3)字节缓冲流的拷贝
public class Test {
    public static void main(String[] args) throws Exception {
        //带缓冲区的字符输入流
        BufferedReader br = new BufferedReader(new FileReader("IO1.txt"));
        //带缓冲区的字符输出流
        BufferedWriter bw = new BufferedWriter(new FileWriter("IO2.txt"));
        String str;
        //BufferedReader独有的方法 -- 读取一行
        while( (str = br.readLine()) != null){
            bw.write(str);
            //BufferedWriter独有的方法 -- 换行
            bw.newLine();
        }
        //关流,释放资源
        br.close();
        bw.close();
    }
}

(4)打印流:PrintWriter

封装了print() / println()方法,支持写入后换行。
支持数据原样打印。

	public void ccc() throws Exception{
        //1创建打印流
        PrintWriter pw=new PrintWriter("File.txt");
        //2打印,将数据保存到文件中
        pw.println(97);
        pw.println(true);
        pw.println(3.14);
        pw.println('a');
        //3关流,释放资源
        pw.close();
    }

(5)转换流:

1)InputStreamReader:把文件中的字节转换成程序中的字符
2)OutputStreamWriter:把程序中的字符转换成文件中的字节

可将字节流转换为字符流。
可设置字符的编码方式。

	//指定编码格式读取文件
    @org.junit.Test
    public void test03() throws IOException{
        InputStreamReader isr = new InputStreamReader(new FileInputStream("File.txt"),"GBK");
        char[] c = new char[1024];
        int len;
        while((len = isr.read(c)) != -1){
            System.out.println(new String(c,0,len));
        }
        isr.close();
    }

    //指定编码格式写出数据
    @org.junit.Test
    public void test04 ()throws IOException{
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream("File.txt"), "GBK");
        osw.write("hello");
        osw.close();
    }

五、输入和输出的重定向

public class Test{
    //输出重定向
    //控制台输出  --  重新定义方向  --  输出到文件中
    @Test
    public void test01() throws Exception {
        //标准输出流
        System.out.println("hello");
        //改变输出方向
        System.setOut(new PrintStream(new FileOutputStream("File.txt")));
        //标准输出流是输出到控制台的,因为使用setOut()方法改变了输出的方式,使内容保存到"File.txt"文件中
    }

    //输入重定向
    // 控制台输入数据到程序中  --  重新定义方向  --  文本文件输入到程序中
    @Test
    public void test02() throws FileNotFoundException {
        //重新定义方向
        System.setIn(new FileInputStream("File.txt"));
        //标准输入流
        Scanner sc = new Scanner(System.in);
        String str = sc.next();
        System.out.println(str);
        //标准输入流是通过控制台输入并在控制台输出的,因为使用setIn()方法改变了输入的方式,从而使输出流直接从文本文件获取数据并在控制台输出
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值