2021一起学习IO流

1.Io流是什么:

通过字面可以将Io拆解为InputOutput,分别是输入和输出的意思。
比如:我们可以将学习的知识理解为输入到自己大脑,而将所学的知识运用在生活中或者考试这样便是输出。

Java中IO是java.io包下的一些常用类的使用,通过常用类对数据的读取(输入Input)和写出(输出Output)

2.为什么学习Io流:

存在的问题:做快递E栈项目时,自己深有感触,当程序运行时,所有的快递信息都在内存中。关闭程序后,这些快递信息就会丢失。

如何解决:使用Io流将快递信息保存在本地磁盘中,下次启动程序后通过Io操作(反序列化)将快递信息读取到内存。删除、修改、查看快递信息通过Io操作(序列化),重新写入到磁盘中。

2.1.Io流分类:
 按照流动的数据类型可以分为: 字节流、字符流
 按照流动的的方向来可以分为: 输入流、输出流
 通过输入流把硬盘的文件输入到(Java)内存中
 通过输出流把字节写到硬盘中

既然Io流是对数据的读取和写出。那么,数据存储的位置是需要去明确的。

学习File类必不可少,需要通过它去创建存储数据的文件。

2.2File类:

API中有这么一句话:

  • 文件系统可以对实际的文件系统对象上的某些操作实施限制,例如读取,写入和执行。

注意:文件夹包含文件

常用的方法1:

    	 File(String pathname) 
     	通过将给定的路径名字符串创建新的 File实例。 

  	   //判断文件或目录是否存在
		boolean exists() 
		//文件不存在就创建    
		boolean createNewFile() 
    
		//创建单级文件夹    
		boolean mkdir()
		//创建单级文件夹  
		boolean mkdirs()  
    
		//是否是文件
		boolean isFile()  
		//是否是文件夹
		boolean isDirectory() 
		//删除文件或文件夹
		boolean delete()  
		//获取路径
		String  getPath()
		//判断是否是绝对路径
		boolean isAbsolute()
		//获取绝对路径
		String getAbsolutePath()   
		//获取文件件内容从的长度
		long length()
 

举例:

 		File file = new File("d://aaa");
        file.mkdir();
        File file1 = new File(file,"bbb.txt");
        boolean flag = file1.createNewFile();
        System.out.println(flag?"创建成功":"创建失败");//创建成功

        String name = file1.getName();
        System.out.println(name);//bbb.txt

	
 		//先执行mkdir查看能否创建多级目录
		File file1 = new File("d://8-18/study");
        if (!file1.exists()) {
            //虽然if条件为true但是mdkir创建不了多级目录
            file1.mkdir();
            System.out.println("创建成功");
        }else{
            System.out.println("创建失败");
        }
		//mkdirs可以创建多级目录
		File file2 = new File("d://8-18/study");
        if (!file2.exists()) {
            file2.mkdirs();
            System.out.println("创建成功");
        }else{
            System.out.println("创建失败");
        }

常用的方法2:

String[] list()
File[] listFiles()
boolean renameTo(File dest)

遍历所有文件:

 		File file = new File("d://8-18/study");
		//获取文件夹中所有文件信息
        String[] list = file.list();
        for (int i = 0; i < list.length; i++) {
            System.out.println(list[i]);
        }
		//获取带有路径的文件夹中所有文件信息
        File[] files = file.listFiles();
        for (int i = 0; i < files.length; i++) {
            System.out.println(files[i]);
        }

练习:查找后缀是MP4的文件 (假设不知道MP4视频放在那个文件夹里的)

网上下载一些MP4格式(视频)、MP3格式(音乐)、txt、docx等文件,目的是为了增加查找MP4文件的难度。

在这里插入图片描述

代码:

public class ExerTest {
    public static void main(String[] args) {
        File file = new File("D://");
        //获取D盘所有文件夹
        File[] files = file.listFiles();
        queryMp4File(files);
    }

    /**
     * 获取后缀格式是mp3的所有文件
     * @param files D盘所有文件夹
     */
    public static void queryMp4File(File[] files){
       //判断是否是文件 如果是就输出该文件 如果不是就继续筛查
        if (files!=null && files.length>0){
            for (File file : files) {
               if (file.isFile()){
                   if (file.getName().endsWith(".mp3")){
                       System.out.println(file.getAbsolutePath());
                   }
               }else {
                    File[] files1 = file.listFiles();
                    queryMp4File(files1);
                }
            }
        }
    }
}

结果:

d:\收藏\视频\周杰伦\听妈妈的话.mp4
d:\收藏\视频\周杰伦\夜曲.mp4
d:\收藏\视频\周杰伦\红尘客栈.mp4
d:\收藏\视频\周杰伦\给我一首歌的时间.mp4
2.3OutputStream类和InputStream类

源码中可以看出OutputSteam类是一个抽象类所有无法直接使用。

public abstract class OutputStream implements Closeable, Flushable {}

OutputSteam提供了一些子类供我们使用。

字节流
FileOutputStream类

常用是FileOutputStream类,先来看看构造方法。

FileOutputStream(File file) 
创建文件输出流以写入由指定的 File对象表示的文件。  
FileOutputStream(File file, boolean append) 
创建文件输出流以写入由指定的 File对象表示的文件。   
FileOutputStream(String name) 
创建文件输出流以指定的名称写入文件。  
FileOutputStream(String name, boolean append) 
创建文件输出流以指定的名称写入文件。  


//如果c.txt不存在直接创建
FileOutputStream fos = new FileOutputStream("d:c.txt");

public FileOutputStream(File file) throws FileNotFoundException {
    	//调用二个参数的构造器
        this(file, false);
}
//具体实现逻辑这里就不粘贴了
public FileOutputStream(File file, boolean append)
        throws FileNotFoundException
{
}


//如果File文件不存在,直接创建文件
File file = new File("d:aa.txt");
FileOutputStream fos = new FileOutputStream(file);


//通过源码可知通过参数name创建的输出流实际上底层也去创建了一个File对象
public FileOutputStream(String name) throws FileNotFoundException {
    	//这里依然调用的是上面的二参构造器  通过匿名对象初始化name的值。
        this(name != null ? new File(name) : null, false);
}

下面通过具体的代码演示二参构造器,其中 参数 boolean append的意思。

操作代码:

void write(int b)
将指定的字节写入此文件输出流。

//d盘创建一个exer.txt文件
FileOutputStream fos = new FileOutputStream("d:exer.txt");
//为什么可以写入a,是因为字符a对应的ASCII是97 
//对应的二进制(计算机存储的数据都是二进制形式)是0110 0001 一个字节=8 bit
fos.write((int)'a');
fos.write((int)'b');
fos.write((int)'c');
//使用完流必须关闭
fos.close();

//以上代码做个变化 其中true代表的是往exer.txt文件中追加数据
//d盘创建一个exer.txt文件
FileOutputStream fos = new FileOutputStream("d:exer.txt",true);
//为什么可以写入a,是因为字符a对应的ASCII是97 
//对应的二进制(计算机存储的数据都是二进制形式)是0110 0001 一个字节=8 bit
fos.write((int)'a');
fos.write((int)'b');
fos.write((int)'c');
//使用完流必须关闭
fos.close();

void write(byte[] b)
将 b.length个字节从指定的字节数组写入此文件输出流。

//还是往exer.txt文件中写入数据,不追加数据,执行完成后会清空上次的内容。  
FileOutputStream fos = new FileOutputStream("d:exer.txt");
//通过字符串转换为字节数组
byte[] bytes = "abcdefg".getBytes();
fos.write(bytes);  
fos.close();

void write(byte[] b, int off, int len)
将 len字节从位于偏移量 off的指定字节数组写入此文件输出流。

通俗的来讲:参数off代表代表索引,参数len代表长度

 @Test
    public void test2() throws IOException {
        FileOutputStream fos = new FileOutputStream("d:exer.txt");
        //通过字符串转换为字节数组
        byte[] bytes = "abcdefg".getBytes();
        fos.write(bytes,1,2);
        fos.close();
    }
//最后记得使用完流一定要关闭
void close() 
关闭此文件输出流并释放与此流相关联的任何系统资源。  
FileInputStream类
//int read() 
//从该输入流读取一个字节的数据。
    @Test
    public void test3() throws IOException {
        FileInputStream fis = new FileInputStream("d:exer.txt");
        int read = fis.read();
        int read2 = fis.read();
        int read3 = fis.read();
        int read4 = fis.read();
        System.out.println((char)read);//a
        System.out.println((char)read2);//f
        System.out.println((char)read3);//g
        //读取到末尾返回-1
        System.out.println(read4);//-1
        fis.close();
    }

int read(byte[] b) 
从该输入流读取最多 b.length个字节的数据为字节数组。  

@Test
    public void test4() throws IOException {
        FileInputStream fis = new FileInputStream("d:exer.txt");
        //数据缓冲区 一次缓冲2个字节数据
        byte[] bytes = new byte[2];
        //也就是说一次读取两个字节数据
        fis.read(bytes);
        //读到数组中的数据转化为字符串
        System.out.println(new String(bytes));
        fis.close();
    }
    
 @Test
    public void test5() throws IOException {
        FileInputStream fis = new FileInputStream("d:exer.txt");
        byte[] bytes = new byte[2];
        //循环读取
        while (true){
            //len的值为读取到的字节个数 与数组长度对应
            int len = fis.read(bytes);
            if (len!=-1){
                System.out.println(new String(bytes,0,len));
            }else {
                break;
            }
        }
        fis.close();
    }

完成:对mp3格式的歌曲进行复制

  @Test
    public void test6() throws IOException {
        FileInputStream fis = new FileInputStream("d:\\收藏\\视频\\周杰伦\\你就不要想起我.mp3");
        //将文件复制到桌面
        FileOutputStream fos = new FileOutputStream("C:\\Users\\Lenovo\\Desktop\\你就不要想起我.mp3");
        //一次读5MB大小的数据,缓存到字节数组中
        byte[] bytes = new byte[1024 * 1024 * 5];
        int len = 0;
        while ((len=fis.read(bytes))!=-1){
            //写入到指定路径 从0索引开始,到实际读到的len长度(歌曲的字节数)
            fos.write(bytes,0,len);
        }
        fos.close();
        fis.close();
    }
字节流读取汉字:
 @Test
    public void test7() throws IOException {
        FileInputStream fw = new FileInputStream("d://b.txt");
        int read3 = fw.read();
        int read2 = fw.read();
        int read1 = fw.read();
        int read = fw.read();
        System.out.println((char)read3);
        System.out.println((char)read2);
        System.out.println((char)read1);
        System.out.println((char)read);
        fw.close();
    }

通过可以看出读取到的汉字乱码

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kB32L7Ae-1629897960544)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\1629510931321.png)]

出现乱码原因txt文本与idea的编码格式不一致。

使用字符流解决该问题或者指定文本编码格式。

另外存在另一个问题是读取不到一个完整的汉字。在字符流中解决这个问题

    @Test
    public void test() throws IOException {
        FileInputStream fis = new FileInputStream("d://a.txt");
        //一次读取二十个字节的汉字
        byte[] bytes = new byte[20];
        while (true){
            int len = fis.read(bytes);
            if (len==-1){
                break;
            }
            System.out.println(new String(bytes,0,len));
        }
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3t0jzhyu-1629897960547)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\1629539008893.png)]

2.4Writer类和Reader类
字符流
FileWriter类

API里构造方法:

FileWriter(File file) 
给一个File对象构造一个FileWriter对象。  
FileWriter(File file, boolean append) 
给一个File对象构造一个FileWriter对象。  。  
FileWriter(String fileName) 
构造一个给定文件名的FileWriter对象。  
FileWriter(String fileName, boolean append) 
构造一个FileWriter对象,给出一个带有布尔值的文件名,表示是否附加写入的数据。  

测试:

public void write(int c)throws IOException

一次写一个字符


@Test
public void test8() throws IOException {
    FileWriter fw = new FileWriter("d://a.txt");
    fw.write('中');
    fw.write('国');
    fw.write('加');
    fw.write('油');
    fw.close();
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qO0CsaTg-1629897960550)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\1629535683306.png)]

public void write(String str) throws IOException {

写入字符串

测试代码:

   @Test
    public void test9() throws IOException {
        FileWriter fw = new FileWriter("d://a.txt");
        fw.write("abcdefgh");
        fw.close();
    }

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iPmaM9gi-1629897960553)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\1629536097390.png)]

public Writer append(CharSequence csq) throws IOException

追加内容:

StringBuffer与FileWriter append方法比较:

相同点:
StringBuffer返回的是调用该方法的对象
FileWriter  返回的也是调用该方法的对象

不同地点:
StringBuffer append()返回值类型是StringBuffer
FileWriter   append()返回值类型是Writer(多态的形式)
    @Test
    public void test10() throws IOException {
        FileWriter fw = new FileWriter("d://a.txt");
        fw.append("每天都是充实的一天").append("开开心心最重要!");
        fw.close();
    }
FileReader类

public int read(char cbuf[]) throws IOException

将字符读入数组。

@Test
    public void test2() throws IOException {
        FileReader fr = new FileReader("d://a.txt");
        //一次读取10个字符
        char[] chars = new char[10];
        while (true){
            int len = fr.read(chars);
            if (len==-1){
                break;
            }
            System.out.println(new String(chars,0,len));
        }
        fr.close();

    }

注意:字符输出流操作完后记得关闭,或者fr.flush();

字节转字符流

字节输出流—>字符输出流

    @Test
    public void test3() throws IOException {
      FileOutputStream fos = new FileOutputStream("d://a.txt");
      OutputStreamWriter osw = new OutputStreamWriter(fos);
      osw.write("梅花香自苦寒来");
      osw.write("宝剑锋从磨砺出");
      osw.close();
    }

字节输入流—>字符输入流

@Test
    public void test4() throws IOException {
        FileInputStream fos = new FileInputStream("d://a.txt");
        InputStreamReader is = new InputStreamReader(fos);
        //一次读取七个字符
        char[] chars = new char[7];
        int len  = 0;
        while ((len=is.read(chars))!=-1){
            System.out.println(new String(chars,0,len));
        }
    }
Print与BufferedReader

PrintStream类和PrintWriter类

    @Test
    public void test5() throws IOException {
        PrintStream ps = new PrintStream("d://c.txt");
        ps.print("啊哈哈哈哈哈");
        ps.print("呵呵呵呵呵呵");
  
        PrintWriter pw = new PrintWriter("d://c.txt");
        pw.println("床前明月光");
        pw.println("疑是地上霜");
        //记得刷新流或者直接调用close() 否则没有数据
        pw.flush();
        pw.close();
    }

BufferedReader缓存读取流

缓存读取流,将字符 输入流转换为带有缓存,可以一次读取一行的缓存的字符流

 @Test
    public void test6() throws IOException {
        FileReader fw = new FileReader("d://c.txt");
        BufferedReader buffer = new BufferedReader(fw);
        String text = buffer.readLine();
        System.out.println(text);
    }
       PrintStream ps = new PrintStream("d://c.txt");
        ps.print("啊哈哈哈哈哈");
        ps.print("呵呵呵呵呵呵");
  
        PrintWriter pw = new PrintWriter("d://c.txt");
        pw.println("床前明月光");
        pw.println("疑是地上霜");
        //记得刷新流或者直接调用close() 否则没有数据
        pw.flush();
        pw.close();
    }

BufferedReader缓存读取流

缓存读取流,将字符 输入流转换为带有缓存,可以一次读取一行的缓存的字符流

 @Test
    public void test6() throws IOException {
        FileReader fw = new FileReader("d://c.txt");
        BufferedReader buffer = new BufferedReader(fw);
        String text = buffer.readLine();
        System.out.println(text);
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值