IO流概述+字节输出流
1.IO概述
类似于从u盘将文件拷贝到电脑硬盘里,把这种数据传输,看作是一种数据流动,按照流动的方向,以内存为基准,分为输入input和输出out,即流向内存是输入流,流出内存是输出流。
Java中I/O操作主要是指使用java.io包下的内容,进行输入输出操作。输入也叫做读取数据,输出也叫做写出数据。
2.IO分类
知识点回忆:
①ASCII码中,一个英文字母(不分大小写)占一个字节的空间,一个中文汉字占两个字节的空间。一个二进制数字序列,在计算机中作为一个数字单元,一般为8位二进制数,换算为十进制。最小值0,最大值255。
②UTF-8编码中,一个英文字符等于一个字节,一个中文(含繁体)等于三个字节。
③Unicode编码中,一个英文等于两个字节,一个中文(含繁体)等于两个字节。
根据数据的流向分为:输入流和输出流
输入流:把数据从其他设备上读取到内存中的流。
输出流:把数据从内存写出到其他设备上的流。
格局数据的类型分为:字节流和字符流
输入流 | 输出流 | |
---|---|---|
字节流 | 字节输入流 InputStream | 字节输出流 OutputStream |
字符流 | 字符输入流 Reader | 字符输出流 Writer |
3.字节流
一切文件数据(文本、图片、视频)在存储时,都是以二进制数字的形式保存,都一个个的字节,那么传输时一样如此。所以,字节流可以传输任意文件数据。在操作流的时候,要时刻明确,无论使用什么样的样的流对象,底层传输的始终为二进制数据。
3.1字节输出流(OutStream)
java.io.OutputStream抽象类是表示字节输出流的所有类的超类,将指定的字节信息写出到目的地。它定义了字节输出流的基本共性功能方法。
查看API文档:
public void close():关闭此输出流并释放与此流相关联的任何系统资源。
public void flush():刷新此输出流并强制写出所有缓冲的输出字节。
public void write(byte[] b):将b.length字节从指定的字节数组写入此输出流。
public void write(byte[] b,int off,int len):从指定的字节数组写入len字节,从偏移量off开始输出到此输出流。
public abstract void write(int b):将指定的字节输出流。
Tips:close方法,当完成流的操作时,必须调用此方法,释放系统资源。
注意:抽象类无法实例化对象使用,需要实例化子类。
3.2FileOutStream类
outputStream有很多子类,文件字节输出流是最简单的一个子类。
作用:把内存中的数据写入到硬盘的文件中。
查看API文档(红色为常用)
构造方法摘要 | |
---|---|
FileOutputStream(File file) 创建一个向指定 File 对象表示的文件中写入数据的文件输出流。 | |
FileOutputStream(File file, boolean append) 创建一个向指定 File 对象表示的文件中写入数据的文件输出流。 | |
FileOutputStream(FileDescriptor fdObj) 创建一个向指定文件描述符处写入数据的输出文件流,该文件描述符表示一个到文件系统中的某个实际文件的现有连接。 | |
FileOutputStream(String name) 创建一个向具有指定名称的文件中写入数据的输出文件流。 | |
|
参数:写入数据的目的地
Flie file:目的地是一个文件
String name:目的地是一个文件的路径
构造方法的作用:
1.创建一个FileOutputStream对象
2.会根据构造方法中传递的文件/文件路径,创建一个空的文件
3.会把FileOutputStream对象指向创建好的文件
写入数据的原理(内存-->硬盘):
java程序-->JVM(Java虚拟机)-->OS(操作系统)-->OS调用写数据的方法-->把数据写入到文件中
字节输出流的使用步骤:
1.创建一个FileOutputStream对象,构造方法中传递写入数据的目的地
2.调用FileOutputStream对象中的方法write,把数据写入到文件中
3.释放资源(流使用会占用一定内存,使用完毕要把内存清空,提供程序效率)
举例:
public static void main(String[] args) throws IOException { // 声明异常 // 创建一个FileOutStream对象 // 会根据构造方法中传递的文件/文件路径,创建一个空的文件(所以可以写不存在的文件) FileOutputStream fos = new FileOutputStream("D:\\JavaTest\\a.txt"); fos.write(97); fos.close(); }
运行结果截图:
原理:
注意:ASCII码存入一个字母(不分大小写)占一个字节
FileOutputStream fos2 = new FileOutputStream(new File("D:\\JavaTest\\b.txt")); // 在文件中显示100,占用3个字节 fos2.write(49); fos2.write(48); fos2.write(48); fos2.close();
运行结果:(49(十进制)--> 110001(二进制)-->1(ASCII码))
注意此处:查ASCII码是直接看49-->1,但实际内存转换是经历了二进制
同理:ASCII码存入一个数字占一个字节
多行写write()冗余,优化:
字节输出流写多个字节的方法:
public void write(byte[] b):将b.length字节从指定的字节数组写入此输出流。
如果写的第一个字节是正数(0-127),那么会查询ASCII码;如果写的第一个字节是负数,那第一个字节会和和第二个字节,两个字节组成一个中文显示,查询系统默认码表(GBK)。
byte[] bytes = {65,66,67,68}; fos2.write(bytes);
运行截图: 内存属性:
byte[] bytes = {-65,-66,-67,68}; fos2.write(bytes);
运行截图: 内存属性:
同理:ASCII码存入一个中文占两个字节
public void write(byte[] b,int off,int len):从指定的字节数组写入len字节,从偏移量off开始输出到此输出流。
byte[] bytes = {65,66,67,68,69,70}; fos2.write(bytes,2,2); // 偏移量是从0数起
运行截图:
写入字符串方法:可以使用String类中的方getBytes法把字符串转换为字节数组。
String str = "1112345"; byte[] bytes2 = str.getBytes(); fos2.write(bytes2);
数据追加续写
可以注意到每次程序运行,创建输出流对象,都会清空目标文件中的数据,那么如何保留目标文件中数据,还能继续添加新数据?
public FileOutputStream(File file,boolean append):创建文件输出流以写入由指定的File对象表示的文件。
public FileOutputStream(String name,boolean append):创建文件输出流已指定的名称写入文件。
这两个构造方法,参数中都需要传入一个boolean类型的值,true表示追加数据,false表示清空原有数据。这样创建的输出流对象,就可以指定是否追加续写了。
// 追加写 FileOutputStream fos3 = new FileOutputStream(new File("D:\\JavaTest\\b.txt"),true); byte[] bytes = {11,2,3,5,6,7}; fos3.write(bytes);
数据换行
widows:\r\n;Linux:/n;mac:/r
注意:这个换行符也是字符串
for (int i = 0; i < 10; i++) { fos3.write("你好".getBytes()); fos3.write("\r\n".getBytes()); }