I:负责把磁盘和网络中的数据读到程序内存中去。
O:负责把程序内存中的数据写到网络或者磁盘中。
按照流的内容,IO流分为字节流和字符流。
字节流:最小单位是字节。适合操作所有类型的文件。比如音频、视频、图片文本等的复制,转移。
字符流:只适合操作纯文本文件。比如读写txt,java文件等。
结合IO和字节流字符流,可分为下面4种。
- 字节输入流 InputStream
- 字节输出流 OutputStream
- 字符输入流 Reader
- 字符输出流 Writer
字节输入流 |
字节输出流 |
字符输入流 |
字符输出流 |
InputStream |
OutputStream |
Reader |
Writer |
FileInputStream |
FileOutputStream |
FileReader |
FileWriter |
BufferedInputStream |
BufferedOutputStream |
BufferedReader |
BufferedWriter |
|
|
InputStreamReader |
|
|
PrintStream |
|
PrintWriter |
DataInputStream |
DataOutputStream |
|
|
字节流
抽象类 |
对应的实现类 |
字节输入流 InputStream |
文件字节输入流 FileInputStream |
字节输出流 OutputStream |
文件字节输出流 FileOutputStream |
作用:以内存为基准,可以把磁盘文件中的数据以字节的形式读入到内存中去。
使用构造器创建文件字节输入流
创建字节输入流管道与源文件接通。
| public FileInputStream(File file) |
| public FileInputStream(String pathName) |
| InputStream is = new FileInputStream("good.txt"); |
字节输入流管道对象的read()方法
方法 |
说明 |
public int read() |
每次读取一个字节返回,如果发现没有数据可读会返回-1 |
public int read(byte[] buffer) |
每次用一个字节数组去读取数据,返回字节数组读取了多少个字节,如果发现没有数据可读会返回-1 |
| |
| InputStream is = new FileInputStream("111.txt"); |
| |
| byte[] buffer = new byte[1024]; |
| |
| int len; |
| |
| while( (len = is.read(buffer)) != -1) { |
| String str = new String(buffer, 0 ,len); |
| System.out.print(str); |
| } |
| |
| is.close(); |
文件字节输出流 FileOutputStream
作用:以内存为基准,把内存中的数据以字节的形式写出到文件中去。
使用构造器创建文件字节输出流
构造器 |
说明 |
public FileOutputStream(File file) |
创建字节输出流管道与源文件对象接通 |
public FileOutputStream(String filepath) |
创建字节输出流管道与源文件路径接通 |
public FileOutputStream (File *file, boolean append) |
创建字节输出流管道与源文件对象接通,可追加数据 |
public FileOutputStream(String filepath, boolean append) |
创建字节输出流管道与源文件路径接通,可追加数据 |
字节输出流管道对象的write()方法
方法名称 |
说明 |
public void write(int a) |
写一个字节出去 |
public void write(byte[] buffer) |
写一个字节数组出去 |
public void write(byte[] buffer, int pos , int len) |
写一个字节数组的一部分出去 |
public void close() throws IOExcention |
关闭流 |
| byte[] bytes = "我爱你中国666".getBytes(); |
| os.write(bytes); |
| os.write(bytes,0,3); |
| os.close(); |
换行符一般使用 "\r\n"
。
使用完流之后,需要马上关闭,因为这个管道占用的是硬件总线资源。
字节流的应用——文件复制
任何文件的底层都是字节,字节流做复制,是一字不漏的转移完全部字节,复制前后的文件格式一致就没问题!
复制过去必须要带文件名!
| InputStream fis = new FileInputStream(srcPath); |
| OutputStream fos = new FileOutputStream(destPath); |
| |
| byte[] buffer = new byte[1024]; |
| int len; |
| while((len = fis.read(buffer)) != -1){ |
| fos.write(buffer,0,len); |
| } |
| |
| fis.close(); |
| fos.close(); |
管道资源的释放方案
如何确保流一定能够被释放?如果发生意外,导致代码没有执行close()
方法,怎么办?
方案一:使用finally代码区(不推荐)
finally代码区的特点:无论try中的程序是正常执行了,还是出现了异常,最后都一定会执行finally区,除非JVM终止。
| |
| InputStream fis = null; |
| Outputstream fos = null; |
| try { |
| fis = new FileInputStream(srcPath); |
| fos = new FileOutputStream(destPath); |
| |
| byte[] buffer = new byte[1024]; |
| int len; |
| while((len = fis.read(buffer))!= -1) { |
| fos.write(buffer, 0, len); |
| } |
| System.out.println("复制成功!"); |
| } catch (Exception e) { |
| e.printStackTrace(); |
| } finally { |
| |
| try { |
| if(fos != null) fos.close(): |
| } catch (Exception e) { |
| e.printStackTrace; |
| } |
| try { |
| if(fis != null) fis.close; |
| } catch (Exception e) { |
| e.printStackTrace; |
| } |
| } |
方案二:使用try-with-resource(推荐)
JDK7开始提供的更简单的资源释放方案。
| try ( |
| |
| InputStream fis = new FileInputStream(scPath); |
| OutputStream fos = new FileOutputStream(destPath); |
| ){ |
| |
| byte[] buffer = new byte[1024]; |
| int len; |
| while((len = fis.read(buffer))!= -1) { |
| fos.write(buffer, 0, len); |
| } |
| system.out.println("复制成功!"); |
| } catch (Exception e) { |
| e.printStackTrace); |
| } |
- 资源不一定是管道资源,资源一般指的是最终实现了
AutoCloseable
接口的资源。
- 资源使用完毕后,会自动调用其
close()
方法,完成对资源的释放。
字符流
抽象类 |
对应的实现类 |
字符输入流 Reader |
文件字符输入流 FileReader |
字符输出流 Writer |
文件字符输出流 FileWriter |
文件字符输入流 FileReader
作用:以内存为基准,可以把文件中的数据以字符的形式读入到内存中去。
使用构造器创建文件字符输入流
创建字符输入流管道与源文件接通。
| public FileReader(File file) |
| public FileReader(String pathName) |
字符输入流管道对象的read()方法
方法 |
说明 |
public int read() |
每次读取一个字符返回,如果发现没有数据可读会返回-1 |
public int read(byte[] buffer) |
每次用一个字符数组去读取数据,返回字符数组读取了多少个字节,如果发现没有数据可读会返回-1 |
文件字符输入流每次读取多个字符,性能较好,而且读取中文是按照字符读取,不会出现乱码!这是一种读取中文很好的方案。
- 创建文件字符输入流管道。
- 定义一个字符数组,每次读多个字符。
- 定义一个变量记录读取长度。
- 循环读取。
文件字符输出流 FileWriter
使用构造器创建文件字符输出流
构造器 |
说明 |
public FileWriter(File file) |
创建字符输出流管道与源文件对象接通 |
public Filewriter(String filepath) |
创建字符输出流管道与源文件路径接通 |
public FileWriter (File file, boolean append) |
创建字符输出流管道与源文件对象接通,可追加数据 |
public FileWriter(String filepath, boolean append) |
创建字符输出流管道与源文件路径接通,可追加数据 |
字符输出流管道对象的write()方法
方法名称 |
说明 |
void write(int c) |
写一个字符 |
void write(String str) |
写一个字符串 |
void write(String str, int off, int len) |
写一个字符串的一部分 |
void write(char[] cbuf) |
写入一个字符数组 |
void write(char[] cbuf, int off, int len) |
写入字符数组的一部分 |
字符输出流管道对象的刷新与关闭
方法名称 |
说明 |
public void flush() throws IOException |
刷新流,就是将内存中缓存的数据立即写到文件中去生效! |
public void close() throws IOException |
关闭流的操作,包含了刷新 |
为什么要刷新?
在管道里有内存缓冲区,不是每个字符都要和磁盘进行耦合,而是在内存缓冲区先集中一波,只做一次IO统一刷新到磁盘中。
刷新就是通知内存赶紧将缓冲区的数据全部写出去。
关闭包含了刷新!
缓冲流-提高性能 Buffered
作用:可以提高字节输入流读取数据的性能
原理:缓冲字节输入流自带了8KB缓冲池;缓冲字节输出流也自带了8KB缓冲池。
public BufferedInputStream (InputStream is)
把低级的字节输入流包装成一个高级的缓冲字节输入流,从而提高读数据的性能。
public BufferedoutputStream (OutputStream os)
把低级的字节输出流包装成一个高级的缓冲字节输出流,从而提高写数据的性能。
public BufferedReader (Reader r)
把低级的字符输入流包装成字符缓冲输入流管道,从而提高字符输入流谈字符数据的性能。public String readLine()
读取一行数据返回,如果没有数据可读了,返回null。
public BufferedWriter (Writer r)
把低级的字符输出流包装成一个高级的缓冲字符输出流管道,从而提高字符输出流写数据的性能。public void newline()
换行。
作用:解决不同编码时,字符流读取文本内容乱码的问题。
解决思路:先获取文件的原始字节流,再将其按真实的字符集编码转成字符输入流,这样字符输入流中的字符就不乱码了。
构造器 |
说明 |
public InputStreamReader (InputStream is) |
把原始的字节输入流,按照代码默认编码转成字符输入流(与直接用FileReader的效果一样) |
public InputStreamReader (InputStream is , String charset) |
把原始的字节输入流,按照指定字符集编码转成字符输入流(重点) |
| |
| InputStream is = new FileInputStream("111.txt"); |
| |
| Reader isr = new InputStreamReader(is, "GBK"); |
| |
| BufferedReader br = new BufferedReader(isr); |
打印流 PrintStream | PrintWriter(实用)
非常实用,如果要输出使用这个就行。
构造器 |
说明 |
public PrintStream(OutputStream/File/String) |
打印流直接通向字节输出流/文件/文件路径 |
public PrintStream (String fileName, Chgrset charset) |
可以指定写出去的字符编码 |
public PrintStream(OutputStream out, boolean autoFlush) |
可以指定卖现自动刷新 |
publis Printstream(Outputstream out, boolean autoFlush,String encoding) |
可以指定实现自动刷新,并可指定字符的编码 |
打印流提供的方法 |
说明 |
public void printin(xxx xx) |
打印任意类型的数据出去 |
public void write(int/byte[]/byte[]一部分) |
可以支持写字节数据出去 |
打印流本身不支持追加,如果要追加需要包装低级管道。
| try ( |
| PrintStream ps = new PrintStream(new FileOutputStream("111.txt"), true); |
| ){ |
| ps.print(97); |
| ps.println('a'); |
| }catch (Exception e){ |
| e.printStackTrace(); |
| } |
两者成对出现。通信经常需要这个,项目经常用到。
作用:允许把数据和其类型一并写出去。
构造器 |
说明 |
public DataInputStream(InputStream out) |
创建特殊数据输入流包装基础的字节输入流 |
public DataOutputStream(OutputStream out) |
创建特殊数据输出流包装基础的字节输出流 |
方法 |
说明 |
public final void writeByte(int v) throws IOException |
将byte类型的数据写入基础的字节输出流 |
public final void writeInt(int v) throws IOException |
将int类型的数据写入基础的字节输出流 |
public final void writeDouble(Double v) throws IOException |
将double类型的数据写入基础的字节输出流 |
public final void writeUTF(String str) throws IOException |
将字符串数据以UTF-8编码成字节写入基础的字节输出流 |
public void write(int/byte[]/byte[]的一部分) |
支持写字节数据出去 |
本文作者:subeipo
本文链接:https://www.cnblogs.com/subeipo/p/18681979/java-chu-xue-zhe-bi-ji08io-liu
版权声明:本作品采用署名—非商业性使用—相同方式共享 4.0 协议许可协议进行许可。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步