java IO基础:字节流与字符流

    技术2022-07-11  85

    简介

    java IO操作中,对数据的传输主要是字节流和字符流2种方式,下面我们分别了解一下字节流和字符流的操作和优缺点

    由于下面4个都是抽象类,所以代码例子都是使用对应的文件类(FileXXXX)实现的

    字节流

    顾名思义,就是用字节(byte)的方式传输数据,数据传输自然对应着输入(InputStream)和输出(OutputStream),这里输入和输出对应的对象是服务器(平时,也就是你的电脑),拿文件举例:我们代码中的文字存入磁盘的文件中,就称为输出,反之,则为输入。

    OutputStream

    以字节的方式作为输出是一个抽象类,不能直接实例化,他有众多子类,比如我们常用的FileOutputStream继承了2个接口,分别是Closeable(Closeable又继承了AutoCloseable)、另外一个接口Flushable AutoCloseable:可以利用-try()-实现自动关闭资源Flushable中的flush()方法可以将内存中缓存的数据强制刷新,比如将内存中缓存的数据,在未关闭钱,强制刷新到文件中。
    常用方法
    output.write(int b):输出单个字节output.write(byte[] b):输出一组字节数据output.write(byte[] b,int off,int len):输出一组数据中的部分字节数据下面是FileOutPutString的使用例子,1.7之后,实现了自动关闭 File file = new File("D:" + File.separator + "file" + File.separator + "out" + File.separator + "bridge.txt"); if(!file.getParentFile().exists()){ file.getParentFile().mkdirs(); } //文件不存在,会自动创建 String str = " Hello bridge!"; try(OutputStream out = new FileOutputStream(file,true)){ //追加的方式,添加数据 out.write(str.getBytes()); }catch (IOException e){ e.printStackTrace(); }

    InputStream

    以字节的方式读取数据是一个抽象类,不能直接实例化,他有众多子类,比如我们常用的FileInputStream同样的,它也继承了Closeable,但他没有继承Flushable
    常用方法
    public int read();返回一个字节,当返回值为-1时,表示结束(输入的实际内容是null)public int read(byte[] data);一块一块的读取,返回的值是读取的字节的个数,小于data.length时,则表示读完了public int read(byre[],int off, int len);返回真实读取的个数,同上面一样public byte[] readAllBytes() throws IOException;:一次性,读取全部数据,当输入数据特别大的时候,谨慎使用 File file = new File("D:" + File.separator + "file" + File.separator + "out" + File.separator + "bridge.txt"); if(!file.exists()){ //如果文件或者目录不存在,提醒用户,目录不存在,这里不会报错 System.out.println("没有找到文件"); return ; } //文件不存在,会自动创建 String str = " Hello bridge!"; try(FileInputStream in = new FileInputStream(file)){ //追加的方式,添加数据 byte[] b = new byte[1024]; int length = in.read(b); System.out.println(new String(b,0, length)); }catch (IOException e){ e.printStackTrace(); }

    字符流

    使用字符(char)的方式传输数据,输入(Reader)和输出(Writer),字符流是JDK1.1之后才加上的。

    Writer

    实现了4个接口Closeable, Flushable, AutoCloseable,Appendable。前面3个,上面已经介绍过了Appendable:表示追加的意思,是jdk1.5之后提出来的,可以将字符序列和值追加到之前的对象,在多线下,需要注意线程安全问题
    常用方法
    write​(char[] cbuf):基本的方法和OutputSteam一样,只不过换成了char类型write​(String str):这个比较常用,可以直接存String类型,非常方便

    代码

    File file = new File("D:" + File.separator + "hello" + File.separator + "bridge.txt"); if (!file.getParentFile().exists()) { file.getParentFile().mkdirs(); // 父目录必须存在 } Writer out = new FileWriter(file) ; String str = "正常的内容\r\n" ; out.write(str); out.append("我要追加内容……") ; // 追加输出内容 out.close();

    Reader

    实现了3个接口Closeable, AutoCloseable, Readable。前2个上面已经介绍了,Readable:表示读取的来源可以通过字符读取
    常用方法
    int read​(char[] cbuf):基本的方法和InputSteam一样,只不过换成了char类型public long transferTo​(Writer out):这个jdk10才有的,目前jdk10普及还不高,可以作为了解

    代码

    如果不写关闭,数据将会在内存中,并不会保存到文件中 File file = new File("D:" + File.separator + "hello" + File.separator + "bridge.txt"); if (file.exists()) { // 文件存在则进行读取 Reader in = new FileReader(file) ; char data[] = new char[1024]; int len = in.read(data) ; System.out.println("读取内容:" + new String(data,0,len)); //in.close(); 这里不写的话,内容无法保存到文件中去 } 如果不写close(),我们可以使用flush()处理,但是建议关闭资源 File file = new File("D:" + File.separator + "hello" + File.separator + "bridge.txt"); if (!file.getParentFile().exists()) { file.getParentFile().mkdirs(); // 父目录必须存在 } Writer out = new FileWriter(file) ; String str = "追加的内容" ; out.write(str); out.flush(); // 强制性刷新

    总结

    理解上面4个抽象类,之后的子类就很简单了在处理中文时,字符流比字节流更方便,但是,大部分情况,比如图片、视频传输还是二进制的形式,此时就得使用字节流了接下来,我们可以了解上面4个抽象类的子类了,他们的子类都有父类的特性,针对不同的场景,使用不同的子类。
    Processed: 0.011, SQL: 9