【Java-----IO流(一)之字节流详解】

IO流概述和分类

IO流概述

  • IO:输入/输出(Input/Output)
  • 流:是一种抽象概念,对数据传输的总称,也就是说数据在设备间的传输成为流,流的本质是数据传输
  • IO流:用来处理设备间数据传输问题的,常见的应用如:文件复制,文件上传,文件下载

IO流分类

按照数据的流向(以内存作为参照物)

  • 输入流:往内存中去,叫做输入(Input),或者叫做读(Read)
  • 输出流:从内存中出来,叫做输出(Output),或者叫做写(Write)

按照数据类型来分

  • 字节流:字节输入流,字节输出流
  • 字符流:字符输入流,字符输出流

一般来说,IO流的分类是按照数据类型来分的

字节流概述

字节流是按照字节的方式读取数据,一次读取一个字节,也就是8个二进制位,这种流是万能的,什么类型的文件都可以读取,包括:文本文件,图片,声音文件,视频文件等。通常如果文件能通过记事本打开,我们还可以读懂里面的内容,就使用字符流,否则使用字节流。如果不知道该使用哪种类型的流,就使用字节流。

字节流抽象基类

  • InputStream:这个抽象类是表示字节输入流的所有类的超类
  • OutputStream:这个抽象类是表示字节输出流的所有类的超类
  • 子类名特点:子类名称都是以其父类名作为子类名的后缀

字节输出流写数据

OutputStream抽象类功能是将指定的字节信息写出到目的地,它定义了字节输出流的基本共性功能方法。

  • 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):将指定的字节写入此输出流

注意:close方法,当完成流的操作时,必须调用此方法,释放系统资源

FileOutputStream类

OutputStream有很多子类,以最简单常用的FileOutputStream为例:FileOutputStream类是文件输出流,用于将数据写出到文件

构造方法

public FileOutputStream(File file):创建文件输出流以写入由指定的file对象表示的文件

File file=new File("D:\\aaa\\helloworld.txt");	
FileOutputStream fos=new FileOutputStream(file);

public FileOutputStream(String name):创建文件输出流以写入指定名称的文件

FileOutputStream fos=new FileOutputStream("D:\\aaa\\helloworld.txt");

当你创建一个流对象时,必须传入一个文件路径,该路径下如果没有这个文件,会创建该文件,如果有这个文件,会清空这个文件的数据。

写出字节数据到文件

使用字节输出流写数据的步骤:

  1. 创建字节输出流对象(调用系统功能创建文件,创建字节输出流对象,让字节输出流对象指向创建好的文件)
  2. 调用字节输出流对象的写数据方法
  3. 释放资源(关闭此文件输出流并释放与此流相关联的任何系统资源)

1  write(int b):写出字节方法,每次可以写出一个字节数据

File file=new File("D:\\aaa\\helloworld.txt");	
FileOutputStream fos=new FileOutputStream(file);
fos.write(65);
fos.write(66);
fos.write(67);
fos.close();
//文件中写入:ABC

2  write(byte[] b):写出字节数组,每次可以写出数组中的数据

byte[] b="abcde".getBytes();
FileOutputStream fos=new FileOutputStream("D:\\aaa\\helloworld.txt");
fos.write(b);
fos.close();
//文件中写入:abcde

3  write(byte[] b,int off,int len):写出指定长度字节数组,每次写出从off索引开始,len个字节

byte[] b="12345".getBytes();
FileOutputStream fos=new FileOutputStream("D:\\aaa\\helloworld.txt");
fos.write(b,1,3);
fos.close();
//文件中写入:234

数据追加续写

上面的构造方法,每次程序运行创建输出流对象,都会清空目标文件中的数据,如何保留目标文件中的数据,还能继续添加新数据呢?看下面两个构造方法:

public FileOutputStream(File file,boolean append):创建文件输出流以写入由指定的file对象表示的文件

public FileOutputStream(String name,boolean append):创建文件输出流以写入指定名称的文件

这两个构造方法,参数中都需要传入一个boolean类型的值,true表示追加数据,false表示清空原有数据,这样创建的输出流对象,就可以指定是否追加续写了。示例代码如下:

byte[] b="12345".getBytes();
FileOutputStream fos1=new FileOutputStream("D:\\aaa\\helloworld.txt");
fos1.write(b,1,3);
fos1.close();
FileOutputStream fos2=new FileOutputStream("D:\\aaa\\helloworld.txt",true);
fos2.write(97);
fos2.write(98);
fos2.write(99);
fos2.close();
//文件中内容为:234abc

写出换行

回车符\r和换行符\n

  • 回车符:回到一行的开头(return)
  • 换行符:下一行(nextline)

系统中的换行

  • windows系统里:每行结尾是回车+换行,即\r\n
  • unix系统里:每行结尾只有换行,即\n
  • mac系统里:每行结尾是回车,即\r。从mac OS X开始与linux统一

写出换行,示例代码如下:

byte[] b="12345".getBytes();
FileOutputStream fos=new FileOutputStream("D:\\aaa\\helloworld.txt");
for(int i=0;i

字节输入流读数据

InputStream抽象类可以读取字节信息到内存中,它定义了字节输入流的基本共性功能方法。

  • public void close():关闭此输入流并释放与此流相关联的任何系统资源
  • public abstract int read():从输入流读取数据的下一个字节
  • public int read(byte[] b):从输入流中读取一些字节数,并将它们存储到字节数组b中

注意:close方法,当完成流的操作时,必须调用此方法,释放系统资源

FileInputStream类

InputStream有很多子类,以最简单常用的FileInputStream为例:FileInputStream类是文件输入流,从文件中读取字节

FileInputStream(File file):通过打开与实际文件的连接来创建一个FileInputStream对象,该文件由文件系统中的File对象指定

File file=new File("D:\\aaa\\helloworld.txt");	
FileInputStream fis=new FileInputStream(file);

FileInputStream(String name):通过打开与实际文件的连接来创建一个FileInputStream对象,该文件由文件系统中的路径名name指定

FileInputStream fis=new FileInputStream("D:\\aaa\\helloworld.txt");

当你创建一个流对象时,必须传入一个文件路径,该路径下,如果没有该文件,会抛出FileNotFoundException

从文件中读取字节数据

使用字节输入流读取数据的步骤:

  1. 创建字节输入流对象
  2. 调用字节输入流对象的读数据方法
  3. 释放资源

1  int read():读取字节,每次可以读取一个字节的数据,读取到文件末尾,返回-1

File file=new File("D:\\aaa\\helloworld.txt");	
FileOutputStream fos=new FileOutputStream(file);
fos.write(65);
fos.write(66);
fos.write(67);
fos.close();

FileInputStream fis=new FileInputStream("D:\\aaa\\helloworld.txt");
int r;
while((r=fis.read())!=-1) {
	System.out.println((char)r);
}
fis.close();
/*输出:A
        B
        C
*/

注意:

  • 虽然读取了一个字节,但是会自动提升为int类型
  • 流操作完毕后,必须调用close方法,释放系统资源

2  int read(byte[] b):使用字节数组读取,每次读取b.length个字节到数组中,返回读取到的有效字节个数,读取到末尾时,返回-1

byte[] b="abcde".getBytes();
FileOutputStream fos=new FileOutputStream("D:\\aaa\\helloworld.txt");
fos.write(b);
fos.close();
FileInputStream fis=new FileInputStream("D:\\aaa\\helloworld.txt");
int len;
byte[] bb=new byte[2];
while((len=fis.read(bb))!=-1) {
	System.out.println(new String(bb));	
}
fis.close();
/*输出:ab
        cd
        ed
*/

最后一次输出了ed是由于最后一次读取时,只读取一个字节e,数组中上次读取的数据没有被完全替换,所以要通过len获取有效的字节,改进代码如下:

byte[] b="abcde".getBytes();
FileOutputStream fos=new FileOutputStream("D:\\aaa\\helloworld.txt");
fos.write(b);
fos.close();
FileInputStream fis=new FileInputStream("D:\\aaa\\helloworld.txt");
int len;
byte[] bb=new byte[2];
while((len=fis.read(bb))!=-1) {
	System.out.println(new String(bb,0,len));
}
fis.close();
/*输出:ab
        cd
        e
*/

使用数组读取,每次读取多个字节,减少了系统间的IO操作次数,从而提高了读写的效率,建议开发中使用。

你可能感兴趣的:(Java,java,jvm,开发语言,后端,架构)