一、什么是IO流?
以内存作为参照物:
往内存中去:叫做输入(Input)。或者叫做读(Read)。
从内存中出来:叫做输出(Output)。或者叫做写(Write)。 流就代表数据像水流一样进行传输;
二、IO流的分类
根据流向IO流可以分为:
输入流:程序 -->文件 输出流:文件 -->程序;
根据读取数据方式的不同进行分类:
①按照字节的方式读取数据,一次读取1个字节,这种流是万能的可以读取任何类型的文件,例如文本文件,图片,声音文件,视频文件等等;
②按照字符的方式进行读取,一次读取一个字符;
这种读取方式专门是为了读取普通的文本文件而存在的,它只能读取纯文本文件(只能用记事本正常打开的文件),不能读取视频,音频,照片文件,甚至连word文件也不能读取
大致的分类如图,以字节流输入为例每种方法的命名也是有依据的大致是以这种方式进行命名的;
三、常用的IO方法;
①FIleOutPuStream("文本的位置")写出数据
方法名称 | 说明 |
void write(int b); | 一次写入一个字节的数据 |
void write(byte[] b) | 一次写入一个字节数组的数据 |
void write(byte[] b,int off,int len) | 一次写入一个字节数组的部分数据 |
FileOutputStream fos=new FileOutputStream("D:\\JetBrains\\IDEA\\Java Program\\SuperMControlSys\\src\\main\\java\\IO\\a.txt");
fos.write(97);
fos.close();
在a.txt这个文本中的打印的结果为一个字符a;
字节输出流的细节:
1.创建字节输出流对象;
细节1:参数可以是文件的路径,也可以是File对象
细节2:如果文件不存在会创建一个新的文件,但必须保证父级路径必须存在
细节3:如果文件已经存在,则会清空文件(因为FileOutPutStream的第二个参数默认为false);如果想要续写则要在FileOutPutStream的第二个参数上写上true。
FileOutputStream fos=new FileOutputStream("D:\\JetBrains\\IDEA\\Java Program\\SuperMControlSys\\src\\main\\java\\IO\\a.txt",true);
2.写数据;
细节:write方法的参数是整数,但是在本地文件中写入的是该整数对应的ASCII上对应的数字;
3.释放资源(close())
每次使用完之后都要释放资源,举个反例
FileOutputStream fos=new FileOutputStream("D:\\JetBrains\\IDEA\\Java Program\\SuperMControlSys\\src\\main\\java\\IO\\a.txt");
fos.write(97);
还是刚才那个代码,但是没有close释放资源,当我们再次找到写的文件,删除它
会出现如图的结果,因为该资源正在被占用(即没有被释放),所以我们无法删除它;
FileOutputStream fos=new FileOutputStream("D:\\JetBrains\\IDEA\\Java Program\\SuperMControlSys\\src\\main\\java\\IO\\a.txt");
byte[] b={97,98};
fos.write(b);
fos.close();
打出字符ab;但是这样打印的速度很慢,如果想要打出很多字符那么我们就要把每个字符的ASCII查一遍,太麻烦了,那么有没有方便一点的方法呢?答案肯定是有的,比如我们像打出woshiikun这个字符串,可以用以下代码
FileOutputStream fos=new FileOutputStream("D:\\JetBrains\\IDEA\\Java Program\\SuperMControlSys\\src\\main\\java\\IO\\a.txt");
String str="woshiikun";
byte[] b=str.getBytes();
fos.write(b);
fos.close();
打印结果如图;
换行同理,用String记录\r\n再用getbyte即可;
FileOutputStream fos=new FileOutputStream("D:\\JetBrains\\IDEA\\Java Program\\SuperMControlSys\\src\\main\\java\\IO\\a.txt");
String str="woshiikun";
byte[] b=str.getBytes();
fos.write(b);
String wrap="\r\n";
byte[] b1=wrap.getBytes();
fos.write(b1);
String str2="chicken you are so beautiful";
byte[] b2=str2.getBytes();
fos.write(b2);
fos.close();
运行结果如图;
②FileInPutStream("文件的位置")把本地文件中的数据读取到程序中来;
实现步骤:
创建对象;
读取数据;
释放资源;
当文本还是刚才那个文本的时候用以下代码
FileInputStream fos=new FileInputStream("D:\\JetBrains\\IDEA\\Java Program\\SuperMControlSys\\src\\main\\java\\IO\\a.txt");
int b1= fos.read();
System.out.println(b1);
fos.close();
只输出了第一个字符的ASCII码值;
如果该文本中只有一个w字符,我们连续读取两次会发生什么?
FileInputStream fos=new FileInputStream("D:\\JetBrains\\IDEA\\Java Program\\SuperMControlSys\\src\\main\\java\\IO\\a.txt");
int b1= fos.read();
System.out.println(b1);
int b2=fos.read();
System.out.println(b2);
fos.close();
会输出-1,也就是读到了文件尾;
字节输入流的细节:
1.创建字节输入流对象
细节1:如果文件不存在,就直接报错。 Java为什么会这么设计呢?输出流:不存在,创建
把数据写到文件当中
输入流:不存在,而是报错呢?
因为创建出来的文件是没有数据的,没有任何意义。
所以Java就没有设计这种无意义的逻辑,文件不存在直接报错。
程序中最重要的是:数据。
2.写数据
细节1:一次读一个字节,读出来的是数据在ASCII上对应的数字细节2:读到文件末尾了,read方法返回-1。
3.释放资源
细节:每次使用完流之后都要释放资源
但是一个一个读取数据的过程很缓慢,这时我们就可以用字节流循环读取
FileInputStream fos=new FileInputStream("D:\\JetBrains\\IDEA\\Java Program\\SuperMControlSys\\src\\main\\java\\IO\\a.txt");
int b;
while((b= fos.read())!=-1){
System.out.print(b+" ");
}
fos.close();
当文本中的数据是asdfghjkl时,会输出如下结果
read方法没调用一次都会往下移动一位,所以以下代码是有问题的
FileInputStream fos=new FileInputStream("D:\\JetBrains\\IDEA\\Java Program\\SuperMControlSys\\src\\main\\java\\IO\\a.txt");
while((fos.read())!=-1){
System.out.print(fos.read()+" ");
}
fos.close();
因为它每一次循环会位移两次,所以输出结果如图
文件拷贝
FileInputStream fis=new FileInputStream("D:\\JetBrains\\IDEA\\Java Program\\SuperMControlSys\\src\\main\\java\\IO\\movie.mp4");
FileOutputStream fos=new FileOutputStream("D:\\JetBrains\\copy.mp4");
int b;
while((b=fis.read())!=-1){
fos.write(b);
}
fos.close();
fis.close();
利用FileInPutStream和FileOutPutStream可以来拷贝文件,但该文件仅限于较小的文件。在关闭释放资源时,应该先关闭后开的,后关闭先开的;