前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java IO知识总结

Java IO知识总结

作者头像
月梦@剑心
发布2023-12-07 18:17:30
1720
发布2023-12-07 18:17:30
举报

IO也就是Input/Output ,数据拿到计算机内存中的过程即为输入,反之,数据从内存输出到外部存储(可以是远程主机、磁盘、数据库等)的过程即为输出。数据传输过程类似于水流,因此称作IO流。IO流在Java中分为输出流和输入流,根据数据的处理方式又分为字节流和字符流。(这里的输入输出是以程序为中心的,输入指程序接收输入,输出指程序把数据输出到外部存储)

Java IO流

Java IO流有四个基类,分别是输入流InputStream(字节输入流),Reader(字符输入流),OutputStream(字节输出流),Writer(字符输出流),其余的IO相关类都是派生于这四个抽象基类。

字节流与字符流

字节流:

  1. 以字节为单位处理数据,适用于处理二进制数据
  2. 直接操作字节,不涉及编码转换,可以处理任何类型的数据

字符流:

  1. 以字符为单位处理数据,适合处理文本数据
  2. 自动处理字符编码和解码(将字节传为字符)
  3. 性能逊于字节流处理,因为还有编解码消耗
  4. 对于不知道编码类型的数据,使用字节流处理会带来乱码问题,而使用字符流就不会出现这样的问题

字节流

InputStream

InputStream用于从源读取字节流到内存中,它是一个抽象类,是所有字节输入流的父类。

常用方法
  1. read():返回输入流中下一个字节的数据,如果未读取任何字节,返回-1,表示结束
  2. read(byte b[]):从输入流中读取一些字节放到字节数组b中,如果数组b的长度为0,则不读取,如果没有可以读取的字节,返回-1。最多可以读b.length个字节,返回读取的字节数
  3. read(byte b[], int off, int len):off是偏移量,len是指定的要读取的最大字节数,其余与read(byte b[])一致(这里的偏移量off是针对字节数组b的,加入偏移为2,则从b的第3个下标开始填充)
  4. skip(long n):忽略输入流中的n个字节,返回实际忽略的字节数
  5. avaliable():返回输入流中可以读取的字节数
  6. close():关闭输入流并释放资源
  7. readAllBytes():读取输入流中的所有字节,返回字节数组
  8. readNBytes(byte[] b, int off, int len):阻塞直到读取len个字节
  9. transferTo(OutputStream out):将所有字节流从一个输入流传递到一个输出流,输出流自动写入

使用的输入文件为text.txt:

代码语言:javascript
复制
hello,world!
sjska
12345678910
qpwoeiruty
代码语言:javascript
复制
String filePath = "text.txt";
FileInputStream file = new FileInputStream(filePath);
System.out.println(file.available());
// 输出输入流中可以读取的字节数 44

byte[] bytes = new byte[10];
file.read(bytes);
for (byte b : bytes){
    System.out.println(b);
    System.out.println(Character.toChars(b));
}
// 输出bytes数组的内容,依次输出 104 h 101 e 108 l 108 l 111 o 44 , 119 w 111 o 114 r 108 l

int read = file.read();
System.out.println(Character.toChars(read));
// 读取了一个字节,输出 d

byte[] bytes1 = new byte[7];
file.read(bytes1, 2,5);
for(byte b : bytes1){
    System.out.println(b);
    System.out.println(Character.toChars(b));
}
// 读取5个字节,并且偏移量为2,输出bytes1数组的内容,依次输出
// 0 0 33 ! 13 10 115 s 106 j
// bytes1数组的前两个字节偏移了,为空,13和10分别表示换行符和回车符

// 跳过4个字节
file.skip(4);
file.read(bytes);
for(byte b : bytes){
    System.out.println(b);
    System.out.println(Character.toChars(b));
}
// 再读取10个字节存在bytes中,其内容为
// 10 49 1 50 2 51 3 52 4 53 5 54 6 55 7 56 8 57 9
// 第一个10是回车符,它之前的换行符已经被skip跳过了
// 之后的1~9为存储的文本,49~57为其对应的ASCII码

String outFilePath = "text1.txt"
OutputStream fileOut = new FileOutputStream("outFilePath");

// 将输入流file中的字节全部放入输出流fileOut
file.transferTo(fileOut);

// 如果没有执行transferTo方法,这里读取输入流中剩余全部字符放在返回的字符数组中
// 但是执行了transferTo,输入流中已经没有字节了,所以什么都没读到
byte[] bytes2 = file.readAllBytes();
for(byte b : bytes2){
    System.out.println(b);
    System.out.println(Character.toChars(b));
}

输出文件text1.txt:

代码语言:javascript
复制
10
qpwoeiruty

OutputStream

字节输出流,将字节输出到指定地方(文件等地),OutputStream是所有字节输出流的父类。

常用方法
  1. write(int b):将特定字节写入到输出流
  2. write(byte b[]):将字节数组b写入到输出流
  3. write(byte b[], int off, int len):增加了off偏移量以及len(要写入的最大字节数),与字节输入流相同,这里的off也是对于字节数组b来说
  4. flush():刷新此输出流并强制写出所有缓冲的输出字节
  5. close():关闭输出流并释放资源

FileOutputStream是使用最多的字节输出流对象,用于将字节写入到文件中,当调用write方法的时候,首先将数据写入到FileOutputStream的内存缓冲区,当缓冲区满、手动调用flush方法、手动调用close方法(其实也是触发了flush方法的调用)、程序退出触发close方法时,才会把数据写入到文件中。

代码语言:javascript
复制
String filePath = "test.txt";
FileOutputStream fis = new FileOutputStream(filePath);
// 将 Z 写入到输出流
fis.write(90);
// 往输出流写入换行符
fis.write(10);
// 网输出流写入回车
fis.write(13);
// 往输出流写入 hello,world!
byte[] bytes = new String("hello,world!").getBytes();
fis.write(bytes);
fis.write(10);
// 偏移量为3,网输出流写入字节数组
fis.write(bytes,3,9);

得到的输出文件`test.txt”:

代码语言:javascript
复制
Z

hello,world!
lo,world!

字符流

基于字节流的IO若不知道编码方式就容易出现乱码问题,字符流对象方便我们对字符进行流操作,对于音频、视频、图片等媒体文件建议使用字节流进行处理,而对于文本文件建议使用字符流进行处理。

字符流默认采用的编码方式是Unicode编码。

Reader

Reader用于从文件读取字符流到内存,它是所有字符输入流的父类。

常用方法
  1. read():从输入流读取一个字符
  2. read(char[] cbuf):用于从输入流读取字符到字符数组cbuf
  3. read(char[] cbuf, int off, int len):用于从输入流读取字符到字符数组cbuf中,并增加了偏移量off以及读取的字符数量len
  4. skip(long n):忽略输入流中的n个字符,返回实际忽略的字符数量
  5. close():关闭输入流并释放资源

FileReader是使用较多的字符输入流。

代码语言:javascript
复制
// 文件使用上面的 test.txt
String filePath = "test.txt";
FileReader fr = new FileReader(filePath);

// 读取一个字符,输出90,也就是Z
System.out.println(fr.read());
char [] cBuf = new char[10];

// 读取一系列字符串到字符数组中
// 依次输出 换行符 回车符 h e l l o , w o
fr.read(cBuf);
for(char c : cBuf){
    System.out.println(c);
}

// 跳过一个字符
fr.skip(1);
char [] cBuf1 = new char[6];

// 读取4个字符串到字符数组中,偏移量为2
// 输出 空 空 l d ! 换行符
fr.read(cBuf1,2,4);
for(char c : cBuf1){
    System.out.println(c);
}

Writer

Writer用于将字符输出到文件中,它是所有字符输出流的父类。

常用方法
  1. write(int c):向输出流写入单个字符
  2. write(char[] cbuf):向输出流写入字符数组
  3. write(char[] cbuf, int off, int len):向输出流写入字符数组,并包含偏移量off以及字符数量len
  4. write(String str):向输出流写入字符串
  5. write(String str, int off, int len):向输出流写入字符串,并且包含偏移量off以及字符数量len
  6. append(CharSequence csq):将指定的字符序列csp附加到指定的Writer对象并返回该Writer对象
  7. append(char c):将指定的字符附加到指定的Writer对象并返回该Writer对象
  8. flush():刷新该输出流,强制输出所有缓冲的输出字符
  9. close():关闭输出流并释放资源
代码语言:javascript
复制
String filePath = "simple.txt";
FileWriter fw = new FileWriter(filePath);

// 向输出流写入字母Z
fw.write(90);

// 写入换行符
fw.write(13);

// 写入字符串 hello,world!
fw.write("hello,world!");

// 写入换行符
fw.write(13);
char[] charArray = "the night".toCharArray();

// 写入字符数组
fw.write(charArray);

// 写入换行符
fw.write(13);

// 写入字符串,偏移量2,写入5个字符
// 因此写入的是 34567
fw.write("123456789",2,5);

// 写入换行符
fw.write(13);

// 写入字符数组,偏移量4,写入2个字符
// 因此写入的是 ni
fw.write(charArray,4,2);

// 写入换行符
fw.write(13);
CharSequence cs = new String("char sequence");

// 写入换行符
fw.write(13);

// 在输出流后追加字符序列 char sequence
Writer append = fw.append(cs);

// 刷新字符输入流
append.flush();

最终得到的simple.txt内容如下:

代码语言:javascript
复制
Z
hello,world!
the night
34567
ni

char sequence

缓冲流

由于IO操作很耗时,所以采用缓冲流,一次写入/读出多个字节,从而避免频繁的IO操作,提高流的传输效率。

字节缓冲流

字节缓冲流采用装饰器模式来增强InputStreamOutputStream子类对象的功能。

Java的输入输出流有自带的内部缓冲区,为什么还需要字节缓冲流?

  1. 内部缓冲区的大小固定且较小,而字节缓冲流可以自定义缓冲区大小,更灵活
  2. 字节缓冲区性能更高
BufferedInputStream

BufferedInputStream从源头读取数据到内存的过程不会一个字节一个字节读取,而是会先将读取到的字节存放在缓冲区,并从内部缓冲区中单独读取字节,大大减少IO次数,提高了读取效率。

未完待续……

版权声明: 如无特别声明,本文版权归 月梦の技术博客 所有,转载请注明本文链接。

(采用 CC BY-NC-SA 4.0 许可协议进行授权)

本文标题:《 Java IO知识总结 》

本文链接:https://ymiir.netlify.app//java/JavaIO.html

本文最后一次更新为 天前,文章中的某些内容可能已过时!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Java IO流
    • 字节流与字符流
    • 字节流
      • InputStream
        • 常用方法
      • OutputStream
        • 常用方法
    • 字符流
      • Reader
        • 常用方法
      • Writer
        • 常用方法
    • 缓冲流
      • 字节缓冲流
        • BufferedInputStream
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档