Java-10-IO流

Java-10-IO流

概述

大多数应用程序都需要实现与设备之间的数据传输,在Java中,将这种通过不同输入输出设备(键盘,内存,显示器,网络等)之间的数据传输抽象的表述为“流”,输入流和输出流是相对于内存设备而言的,将外设中的数据读取到内存中即输入,将内存的数据写入到外设中即输出。

四点明确

  • 明确指定操作的数据是数据源(读)还是数据目的(写)

    • 源:InputStream Reader

      目的:OutStream Writer

  • 明确要操作的设备上的数据是字节还是文本

    • 源:

      ​ 字节:InputStream

      ​ 文本:Reader

      目的:

      ​ 字节:OutStream

      ​ 文本:Writer

  • 明确数据所在的具体设备

    • 源设备:

      ​ 硬盘:文件File开头

      ​ 内存:数组,字符串

      ​ 键盘:System.in

      ​ 网络:Socket

      目的设备:

      ​ 硬盘:文件File开头

      ​ 内存:数组,字符串

      ​ 显示屏:System.out

      ​ 网络:Socket

  • 明确是否需要额外功能(exam:是否需要转换流,高校流)

File类

java.io.File类与流关,它操作的是文件本身(创建,查找和删除),而不是文件内容

用法

import java.io.File;
import java.io.IOException;

public class TestFile {
    public static void main(String[] args) {
        //=========File类的构造方法==========
        //File类构造方法不会检验这个文件或文件夹是否真实存在,
        //因此无论该路径下是否存在文件或者目录,
        //都不影响File对象的创建。
        //注意路径中的"\"是转义字符"\\"表示转义转义字符="\"
        //注意路径不区分大小写

        //直接传文件路径
        String path = "E:\\testFile.txt";
        File f1 = new File(path);
        // 通过父路径和子路径字符串
        String parent = "E:\\testFile";
        String child = "firstFile.txt";
        File f2 = new File(parent, child);  //等价于E:\\testFile\\fisrtFile.txt
        //通过父类File对象和子路径
        File fatherobj = new File("E:\\testFile");
        String childPath = "secondFile.txt";
        File f3 = new File(fatherobj,childPath);//等价于E:\\testFile\\secondFile.txt

        //=========File类的常用方法=========
        System.out.println("文件的绝对路径:"+f2.getAbsolutePath());//文件的绝对路径:E:\testFile\firstFile.txt
        System.out.println("文件的构造路径:"+f2.getPath());//文件的构造路径:E:\testFile\firstFile.txt
        System.out.println("文件名称:"+f2.getName());//文件名称:firstFile.txt
        System.out.println("文件长度:"+f2.length()+"字节");//文件长度:0字节

        //=========File类的判断方法=========
        //判断File表示的文件/目录是否存在
        System.out.println(f1.exists());//true
        //判断是否为目录
        System.out.println(f1.isDirectory());//false
        //判断是否为文件
        System.out.println(f1.isFile());//true

        //=========创建与删除=========
        //createNewFile() 创建文件  这里会判断是否已经存在 存在:不创建并返回false,不存在:传建并返回true
        try {
            System.out.println(f1.createNewFile());
        } catch (IOException e) {
            e.printStackTrace();
        }
        //mkdir(),mkdirs() 创建目录 返回值同上,
        // 另:mkdir:仅创建一级目录,
        // mkdirs:创建由此File表示的目录,包括任何必需但不存在的父目录。推荐使用
        File f4 = new File("E:\\testFile\\makeDir\\testMakeDirs");
        System.out.println(f4.mkdirs());//true

        //delete() 删除File所表示的目录/文件
        //另:若为目录,必须为空,且删除的是最里层文件/目录
        System.out.println(f1.delete());//true
        System.out.println(f4.delete());//true
        System.out.println(f4.delete());//false 已经不存在了

        //=========目录的遍历=========
        //根据返回的对象不同分为
        //String---list()   名字
        //File-----listFiles() File对象
        //注意listFiles在获取指定目录下的文件或者文件夹时必须满足下面两个条件
        //1,指定的目录必须存在
        //2,指定的必须是目录。否则容易引发返回数组为null,出现NullPointerException异常
        //本例基于本人的电脑 E:\FFOutput目录
        File file = new File("E:\\AAA开发文档");
        for (String name:file.list()) {
            System.out.println(name);
            /*
            589397 《Android Studio开发实战 从零基础到App上线》源码.rar
            631554 Android开发:从0到1.pdf
            654431 Android开发实例大全 第2版.pdf
            Android Studio开发实战:从零基础到App上线.pdf
            第一行代码(附源码)
            */
        }
        for (File f:file.listFiles()) {
            System.out.println(f);
            /*
            E:\AAA开发文档\589397 《Android Studio开发实战 从零基础到App上线》源码.rar
            E:\AAA开发文档\631554 Android开发:从0到1.pdf
            E:\AAA开发文档\654431 Android开发实例大全 第2版.pdf
            E:\AAA开发文档\Android Studio开发实战:从零基础到App上线.pdf
            E:\AAA开发文档\第一行代码(附源码)
            */
        }
    }
}

IO的分类

根据数据流向

  • 输入流:设备->内存
  • 输出流:内存->设备

根据数据类型

  • 字节流:以字节为单位,读写数据的流
  • 字符流:以字符为单位,读写数据的流。

对应的超类

输入流输出流
字节流InputStreamOutputStream
字符流ReaderWriter

字节流

任何文件(文字,图片,视频…)都是一个一个字节

字节输出流(OutputStream)

OutputStream作为字节输出流所有子类的超类定义了如下共性方法

close() 关闭此输出流,并释放相关资源

flush() 刷新此输出流并强制任何缓冲输出字节被写出

write(byte[] b) 将b中的字节从指定字节数组写入此输出流

write(byte[] b, int offset, int len) 从指定的字节数组写入len字节,从偏移量offset开始输出到此输出

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

文件输出流(FileOutputStream)

将数据(内存)写出到文件(硬盘)

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

public class TestFileOutStream {
    public static void main(String[] args) throws IOException {
        //===========构造方法============
        /*
        创建输出流对象的时候,
        系统会自动去对应位置创建对应文件,
        如果已经有这个文件,会清空这个文件的数据。
        */

        //根据File对象为参数创建FileOutStream类
        File f1 = new File("E:\\testFile\\testFileOut.txt");
        FileOutputStream fos  = new FileOutputStream(f1);

        //根据名称字符串为参数创建FileOutStream类 推荐
        FileOutputStream fos2 = new FileOutputStream("E:\\testFile\\a.txt");

        //===========写出字节流的方法(重载)=========
        // int b  Ascii码转字节
        fos.write(97);//a
        fos.write(98);//b
        fos.write(99);//c

        //字符串->字节数组
        byte[] b = "hello my friends".getBytes();
        //byte[] b 字节数组
        fos.write(b);
        //字节数组,指定片段
        fos.write(b,6,10);


        //关闭资源
        fos.close();
        fos2.close();
        /*
        * testFileOut.txt:
        * abchello my friendsmy friends
        * */

        //============实现数据追加续写、换行===========
        /*
          由于使用之前的构造方法,创建FileOutStream类总会清除原始数据
          利用以下构造方法实现追加(true 追加)
          FileOutputStream(File file, boolean append)
          FileOutputStream(String name, boolean append)
          Windows换行则是 \n,\r
        */

        FileOutputStream fos3 =new FileOutputStream(f1,true);
        byte[] b2 = "\n我的前面应该有字节".getBytes();
        fos3.write(b2);
        fos3.close();
    }
}

字节输入流(InputStream)

InputStream作为字节输入流所有子类的超类定义了如下共性方法

close() 关闭此输入流并释放相关系统资源。

abstract int read() 从输入流读取数据的下一个字节 抽象类

int read(byte[] b) 该方法返回的int值代表的是读取了多少个字节,读到几个返回几个,读取不到返回-1

文件输入流(FileInputStream)

读取文件(硬盘)内容

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

public class TestFileInputStream {
    public static void main(String[] args) throws IOException {
        //===========文件输入流的构造方法==============
        /*
            创建文件输入流时,如果参数 路径下没有该文件
            会报错FileNotFoundException
        */

        //File对象为参数创建FileInputStream类
        File f1 = new File("E:\\testFile\\testFileIn.txt");
        FileInputStream fis = new FileInputStream(f1);
        //名称字符串为参数创建FileInputStream类 推荐
        FileInputStream fis2 = new FileInputStream("E:\\testFile\\testFileIn.txt");

        //============FileInputStream类读取字节方法===========
        //int read() 每次可读取一个字节的数据,读到末尾返回-1
        int read;
        while ((read = fis2.read())!=-1){
            System.out.print((char) read);//hello my friends
        }
        
        //int read(byte[] b) 每次读取b.lenth个字节到数组b中,返回读取到的有效字节个数,读取到末尾时,返回-1
        int len;//接受返回的有效字节数
        byte[] b = new byte[3];
        while ((len = fis.read(b))!=-1){
            System.out.println(new String(b));
            //System.out.println(new String(b,0,len));可避免如下情况
            /*
                  hel
                  lo
                  my
                  fri
                  end
                  snd //这里,多读了nd,
                  原因时最后一次仅有一个字符,
                  而上一个字符数组end,替换了e
                  还留下了nd
            */
        }
        fis.close();
        fis2.close();
    }
}

字节流综合实例(图片的复制)

创建数据流:

​ 指定数据源

​ 指定目的地

读写数据

​ 定义数组容器

​ 定义长度

​ 循环读取

​ 写出数据

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class TestOutAndIn {
    public static void main(String[] args) throws IOException {
        //确定数据源
        FileInputStream fis = new FileInputStream("E:\\Pictures\\kaisa.jpeg");
        //确定目的地
        FileOutputStream fos = new FileOutputStream("E:\\testFile\\kaisacopy.jpeg");

        //定义接受数组和返回值
        byte[] b = new byte[1024];
        int len;

        while((len=fis.read(b))!=-1){
            fos.write(b,0,len);
        }
        //关闭资源
        fos.close();
        fis.close();

    }
}

字符流

按道理说文件都是字节,字节流应当够用了,但是由于文件的编码不同,字节流直接读取数据(比如中文)会有乱码的问题,所以需要字符流

处理纯文本的数据优先考虑字符流,其他情况用字节流了(图片、视频)。

字符流 = 字节流 + 编码表

字符输出流(Writer)

字符输出流的所有类的超类,将指定的字符信息写出到目的地,共性方法如下

write(int c): 写入单个字符

write(char[] cbuf): 写入字符数组。

abstract void write(char[] cbuf, int off, int len): 写入字符数组的某一部分,off数组的开始索引,len写的字符个数

write(String str) 写入字符串

write(String str, int off, int len) 写入字符串的某一部分,off字符串的开始索引,len写的字符个数

flush() 刷新该流的缓冲

close() 关闭此流,但要先刷新它

import java.io.FileWriter;
import java.io.IOException;

public class TestFileWriter {
    public static void main(String[] args) throws IOException {
        //=======构造方法==========
        /*
            FileWriter(File file): 创建FileWriter,给定要读取的File对象。
            FileWriter(String fileName):创建一个FileWriter,给定要读取的文件的名称。
        * */

        FileWriter fw = new FileWriter("E:\\testFile\\testFileWriter.txt");
        fw.write(97);
        fw.write('b');

        fw.write("\n我是中国人!");
        //关闭资源时,与FileOutputStream不同。 如果不关闭,数据只是保存到缓冲区,并未保存到文件。
        fw.close();
    }
}
close和flush

因为内置缓冲区的原因,如果不关闭输出流,无法写出字符到文件中。但是关闭的流对象,是无法继续写出数据的。如果我们既想写出数据,又想继续使用流,就需要flush方法。

flush() :刷新缓冲区,流对象可以继续使用。
close():先刷新缓冲区,然后通知系统释放资源。流对象不可以再被使用了。

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class TestFlush {
    public static void main(String[] args) throws IOException {
        //数据源
        FileReader fr = new FileReader("E:\\testFile\\a.txt");
        //目的地
        FileWriter fw = new FileWriter("E:\\testFile\\b.txt");

        int len;//接受放回值
        while((len = fr.read())!=-1){
            fw.write(len);
        }
        //这里是没有使用close关闭流
        /*
        * b.txt什么都没有
        * 关闭资源时,与FileOutputStream不同。
        * 如果不关闭,数据只是保存到缓冲区,并未保存到文件。
        * */
        fr.close();
        fw.flush();
        /*
        * flush的作用:
        * 用于清空缓冲区的数据流,进行流的操作时,数据先被读到内存中,
        * 然后再用数据写到文件中,当你数据读完时,我们如果这时调用close()方法关闭读写流,
        * 就可能造成数据丢失,因为读入数据完成时不代表写入数据完成,一部分数据可能会留在缓存区中
        * */
        fw.close();
    }
}
FileWriter的续写和换行同FileOutputStream

字符流综合实例(复制文本)

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class TestRAndW {
    public static void main(String[] args) throws IOException {
        //输入流对象
        FileReader fr = new FileReader("E:\\testFile\\a.txt");
        //输出流对象
        FileWriter fw = new FileWriter("E:\\theCopyOfa.txt");

        char[] c = new char[1024];//容器
        int len;//
        while ((len = fr.read(c))!=-1){
            fw.write(c);
        }
        fw.flush();
        fr.close();
        fw.close();
    }
}

字符输入流(Ritereader)

同理:Reader是字符输入流的所有类的超类,共性方法如下:

close(): 关闭此流并释放相关系统资源。

int read(): 从输入流读取一个字符。

int read(char[] cbuf): 从输入流中读取一些字符,并将它们存储到字符数组cbuf中

FileReader类

读取字符文件的便利类。构造时使用系统默认的字符编码和默认字节缓冲区。

import java.io.FileReader;
import java.io.IOException;

public class TestFileReader {
    public static void main(String[] args) throws IOException {
        //=======构造方法==========
        /*
        * FileReader(File file): 创建一个新的FileReader类,给定要读取的File对象。
        * FileReader(String fileName): 创建一个新的FileReader类,给定要读取的文件的字符串名称。
        * */
        FileReader fr = new FileReader("E:\\testFile\\testFileReader.txt");
        //定义变量,保存数据
        int b;
        while((b=fr.read())!=-1) {
            System.out.println((char) b);
        }
        fr.close();
    }
}

缓冲流

缓冲流,也叫高效流,是对4个基本的 FileXxx 流的增强,所以也是4个流,按照数据类型分类:

  • 字节缓冲流: BufferedInputStream , BufferedOutputStream
  • 字符缓冲流: BufferedReader , BufferedWriter

缓冲流的基本原理,是在创建流对象时,会创建一个内置的默认大小的缓冲区数组,通过缓冲区读写,减少系统IO次数,从而提高读写的效率。

字节缓冲流

构造方法
  • public BufferedInputStream(InputStream in):创建一个新的缓冲输入流,注意参数类型为InputStream
  • public BufferedOutputStream(OutputStream out): 创建一个新的缓冲输出流,注意参数类型为OutputStream

构造举例代码如下:

//构造方式一: 创建字节缓冲输入流【但是开发中一般常用下面的格式申明】
FileInputStream fps = new FileInputStream(b.txt);
BufferedInputStream bis = new BufferedInputStream(fps)

//构造方式一: 创建字节缓冲输入流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream("b.txt"));

///构造方式二: 创建字节缓冲输出流
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("b.txt"));
普通流vs缓冲流
package com.IO;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

//普通流测试
public class TestNormal {
    public static void main(String[] args) {

        long start = System.currentTimeMillis();
        try (//创建文件输入流
             FileInputStream fis = new FileInputStream("E:\\Pictures\\akali.jpg");
             //创建文件输入流
             FileOutputStream fos = new FileOutputStream("E:\\testFile\\copyakali.jpg");
             ){
            //读写数据
            int b;
            while ((b=fis.read())!=-1){
                fos.write(b);
            }
            fis.close();
            fos.close();
        }catch (IOException e) {
            e.printStackTrace();
        }

        long end = System.currentTimeMillis();
        System.out.println("普通流的复制时间:"+(end-start));

    }
}
普通流的复制时间:8896
import java.io.*;

//缓冲流
public class TestBuffered {
    public static void main(String[] args) {
        long start = System.currentTimeMillis();

        try (
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream("E:\\Pictures\\akali.jpg"));
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("E:\\testFile\\copyakali2.jpg"));
        ){
            int b;
            while ((b=bis.read())!=-1){
                bos.write(b);
            }
            bis.close();
            bos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        long end = System.currentTimeMillis();
        System.out.println("缓冲流的复制时间:"+(end-start));

    }
}
缓冲流的复制时间:93

用数组做容器更快

import java.io.*;


public class TestBuffered {
    public static void main(String[] args) {
        long start = System.currentTimeMillis();

        try (
            BufferedInputStream bis = new BufferedInputStream(new FileInputStream("E:\\Pictures\\akali.jpg"));
            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("E:\\testFile\\copyakali2.jpg"));
        ){
            int len;
            byte[] b = new byte[1024];
            while ((len=bis.read(b))!=-1){
                bos.write(b,0,len);
            }
            bis.close();
            bos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        long end = System.currentTimeMillis();
        System.out.println("缓冲流的复制时间:"+(end-start));

    }
}
缓冲流的复制时间:16

字符缓冲流

构造方法
  • public BufferedReader(Reader in) :创建一个 新的缓冲输入流。
  • public BufferedWriter(Writer out) : 创建一个新的缓冲输出流。

构造举例,代码如下:

// 创建字符缓冲输入流
BufferedReader br = new BufferedReader(new FileReader("b.txt"));
// 创建字符缓冲输出流
BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));
字符缓冲流特有方法
  • BufferedReader:public String readLine(): 读一行数据。 读取到最后返回null
  • BufferedWriter: public void newLine(): 换行,由系统属性定义符号。

readLine示例

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class TestBufferReader {
    public static void main(String[] args) throws IOException {
            BufferedReader br = new BufferedReader(new FileReader("E:\\testFile\\a.txt"));
            // 定义字符串,保存读取的一行文字
            String line  = null;
            // 循环读取,读取到最后返回null
            while ((line = br.readLine())!=null) {
                System.out.print(line);
                System.out.println("------");
            }
            br.close();
        }
}

newLine()示例

import java.io.*;

public class TestBufferReader {
    public static void main(String[] args) throws IOException {
        BufferedWriter bw = new BufferedWriter(new FileWriter("E:\\testFile\\testnewLine.txt"));
        // 写出数据
        bw.write("我");
        // 写出换行
        bw.newLine();
        bw.write("是");
        bw.newLine();
        bw.write("中国人");
        bw.newLine();
        // 释放资源
        bw.close();
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值