学习IO流

 

定义:存储和读出数据的解决方案

作用:用于读写文件中的数据

分类

①按照方向划分:

输入输出的方向是相对于程序来说的

输入流:将本地文件中的数据读取到程序中。本地文件——>程序

输出流(写入):将程序中的数据写入到本地文件中。程序——>本地文件

②操作的文件类型

字节流:InputStream、OutputStream。可以操作所有类型的文件。

字符流:Write、Reader。只可以操作纯文本文件。

补充:纯文本文件就是可以使用Windows系统自带的记事本打开且能读懂的文件。比如.txt、.xml、.lrc

字节流

FileOutputStream文件字节输出流

作用:可以把程序中的数据写到本地文件上,是字节流的基本流

使用步骤:

①创建字节输出流对象——在程序和文件之间创建一条数据传输的通道

细节1:参数可以是字符串表示的路径,也可以是File对象

细节2:如果操作的文件不存在,则会创建一个新文件,但是要保证父路径存在

细节3:如果文件已经存在,则会清空文件

②写数据

细节1:write方法的参数是整数,但实际上写到本地文件中的数据是整数在ASCII上对应的字符

③释放资源——关闭数据传输的通道

细节1:每次使用完流都要释放资源

public class ByteStreamDemo02 {
    public static void main(String[] args) throws IOException {
        /**
         * 字节输出流FileOutputStream
         *
         * 需求:写出一段文字到本地文件中
         *
         * 步骤:
         * 1.创建对象
         * 2.写出数据
         * 3.释放资源
         */

        //1.创建对象
        //让程序和文件之间产生一个数据传输的通道
        FileOutputStream fos = new FileOutputStream("IO流\\a.txt");
        //2.写出数据
        fos.write(97);//a
        //3.释放资源
        //将数据传输的通道关闭掉
        fos.close();

    }
}
public class ByteStreamDemo03 {
    public static void main(String[] args) throws IOException {
        /**
         * void write(int b)  一次写一个数据
         * void write(byte[] b)  一次写一个字节组数据
         * void write(byte[] b,int off,int len)  一次写一个字节组的部分数据
         *   参数1:
         *      数组
         *   参数2:
         *      起始索引
         *   参数3:
         *      个数
         */

        //1.创建对象
        FileOutputStream fos = new FileOutputStream("IO流\\a.txt");
        //2.写数据
//        fos.write(97);//a
//        fos.write(98);//b
        byte[] bytes = {97,98,99,100,101};
//        fos.write(bytes);//abcde
        fos.write(bytes,0,3);//abc
        //3.释放资源
        fos.close();

    }
}

方法:

void write(int b)  一次写一个数据
void write(byte[] b)  一次写一个字节组数据
void write(byte[] b,int off,int len)  一次写一个字节组的部分数据

        

public class ByteStreamDemo04 {
    public static void main(String[] args) throws IOException {
        /**
         * 换行写
         *     写个换行符即可
         *     Windows系统:\r\n 回车换行符
         *     Linux系统:  \n
         *     Mac系统:    \r
         *
         *     细节: 在Windows操作系统当中,java对回车换行进行了简化。可以只写\n或者\r,java底层会自动换行
         *
         * 续写
         *     如果想要续写,打开续写开关就行了
         *     开关位置:创建对象的第二个参数
         *     默认为false,表示关闭续写,此时创建对象会清空文件
         *     手动传递true,表示打开续写,此时创建对象不会清空文件
         *
         */

        //1.创建对象
        FileOutputStream fos = new FileOutputStream("IO流\\a.txt",true);
        //2.写数据
        String str = "kankedelaoyezuishuai";
        byte[] bytes = str.getBytes();
        fos.write(bytes);
        String str1 = "666";
        String wrap = "\r\n"; //换行符
        byte[] wrapBytes = wrap.getBytes();
        fos.write(wrapBytes);
        byte[] bytes1 = str1.getBytes();
        fos.write(bytes1);
        //3.释放资源
        fos.close();

    }
}

FileInputStream字节输入流

作用:操作本地文件,可以把本地文件中的数据读取到程序中来。

步骤:

①创建字节输入流对象

细节1:如果文件不存在,则直接报错

②读取数据

细节1:使用read方法读取数据时,一次只读取一个字节,读出来的是数据在ASCII上对应的数字

细节2:多次读,如果读到文件末尾了,read方法返回-1

③释放资源 

public class ByteStreamDemo01 {
    public static void main(String[] args) throws IOException {
        /**
         * 演示字节输入流FileInputStream
         *
         * 需求:读取文件中的数据
         */

        //1.创建对象
        //a.txt的内容abcd
        FileInputStream fis = new FileInputStream("IO流\\a.txt");
        int b1 = fis.read();//97
        int b2 = fis.read();//98
        int b3 = fis.read();//99
        int b4 = fis.read();//100
        int b5 = fis.read();//100
        System.out.println(b1);
        System.out.println((char)b1);
        System.out.println((char)b2);
        System.out.println((char)b3);
        System.out.println((char)b4);
        System.out.println(b5);//-1
        fis.close();
    }
}

当文件中的数据很多的时候,一个一个读很费时,可以采取循环读取。 

public class ByteStreamDemo02 {
    public static void main(String[] args) throws IOException {
        /**
         * 演示字节输入流FileInputStream
         *
         * 需求:循环读取文件中的数据
         */

        //1.创建对象
        //a.txt的内容abcd
        FileInputStream fis = new FileInputStream("IO流\\a.txt");
        //2.循环读取数据
        int b;
        while ((b = fis.read()) != -1){
            System.out.println((char)b);
        }
        //3.释放资源
        fis.close();
    }
}

常用方法:

public int read()  一次读取一个字节的数据
public int read(byte[] buffer)   一次读一个字节数组的数据

注意1:一次读取一个字节数组的数据,每次读取会尽可能把数组装满。

注意2:一般创建数组的长度是1024的整数倍。eg:1024*1024*5

public class ByteStreamDemo03 {
    public static void main(String[] args) throws IOException {
        /**
         * public int read(byte[] buffer)   一次读取一个字节数组的数据
         *
         * 需求:一次读取两个字节
         *
         */

        //1.创建对象
        FileInputStream fis = new FileInputStream("IO流\\a.txt");
        //2.读取数据
        byte[] bytes = new byte[2];
        //一次读取多少个字节的数据,和数组的长度有关
        //返回值表示读取到了多少个字节的数据
        //读取到的数据存储到数组当中
        int len = fis.read(bytes);
        System.out.println(len);
        String str = new String(bytes,0,len);
        System.out.println(str);
        int len1 = fis.read(bytes);
        System.out.println(len1);
        String str1 = new String(bytes,0,len1);
        System.out.println(str1);
        int len2 = fis.read(bytes);
        System.out.println(len2);
        String str2 = new String(bytes,0,len2);
        System.out.println(str2);

        //3.释放资源
        fis.close();
    }
}

产生乱码的原因:

编码和解码的方式不一样

如何产生乱码?

①读取数据时未读完整个汉字

②编码解码时使用同一个码表,同一个编码方式        

字符流

字符流的底层其实就是字节流

字符流=字节流+字符集

特点:

输入流:一次读取一个字节,遇到中文时,一次读取多个字节 

字符输入流

FileReader操作本地文件的字符输入流

步骤:

①创建字符输入流对象

public FileReader(File file)

public FileReader(String pathname) 

②读取数据

public int read()  读取数据,读到末尾返回-1
public int read(char[] buffer)   读取多个数据,读取到末尾返回-1

细节1:按照字节进行读取,遇到中文,一次读取多个字节,读取后解码,返回一个整数

细节2:读到文件末尾了,read方法返回-1 

细节3:在使用有参的read方法读取数据时,是将读数据、解码、强转三步合一了。把强转后的数据存到数组当中 

③释放资源

字符输出流

FileWriter操作本地文件的字符输出流

步骤:

①创建字符输出流对象

public FileWriter(File file)创建字符输出流关联本地文件
public FileWriter(String pathname)创建字符输出流关联本地文件
public FileWriter(File file,boolean append)创建字符输出流关联本地文件,续写
public FileWriter(String pathname,boolean append)创建字符输出流关联本地文件,续写

②写数据

void write(int c)写出一个字符
void write(String str)写出一个字符
void write(String str,int off,int len)写出一个字符串的一部分
void write(char[] cbuf)写出一个字符数组
void write(char[] cbuf,int off,int len)写出一个字符数组的一部分

细节:如果write方法的参数是整数,但是实际写到本地文件中的是整数在字符集上对应的字符

③释放资源

缓冲流

可以提高读写的效率

字节缓冲流

原理:底层自带了长度为8192的缓冲区提高性能 

BufferedInputStream 字节缓冲输入流

BufferedOutputStream 字节缓冲输入流

步骤:

①创建对象

public BufferedInputStream(InputStream is)

public BufferedOutputStream(OutputStream os)

②读写数据

③释放资源

字符缓冲流

BufferedReader

BufferedWriter

步骤:

①创建字符缓冲流对象

public BufferedReader(Reader r)

public BufferedWriter(Writer w)

②读写数据

特有方法

字符缓冲输入流 public String readLine()读取一行数据,如果没有数据可读了,会返回null
字符缓冲输出流public void newLine()       写一行,会根据操作系统自动更换换行符

转换流

是字节流和字符流之间的桥梁

InputStreamReader

public InputStream(File file,String charsetName)

OutputStreamReader

public OutputStream(File file,String charsetName)

ObjectOutputStream序列化流

作用:可以吧Java中的对象写到本地文件中

public ObjectOutputStream(OutputStream out):把基本流包装成高级流

public final void writeObject(Object obj):把对象序列化到文件中去

注意:要想序列化对象的前提,该对象的类必须实现Serializable接口

ObjectInputStream反序列化流

将序列化到文件中的对象,读取到程序中来

public ObjectInputStream(InputStream out):把基本流包装成高级流

public final void readObject(Object obj):把序列化到本地文件中的对象,读取到程序中

细节1:在序列化流将对象写到文件中时,需要让JavaBean类实现Serialzable接口。否则会出现NotSerialzableException异常。

细节2:序列化流写到文件中的数据是不能修改的,一旦修改就无法再次读回来

细节3:序列化对象后,修改了JavaBean类,再次反序列化,则会报错。会抛出InvalidClassException异常。

        解决方案:给JavaBean类添加serialVerSionUID(序列号、版本号) 

细节4:如果一个对象中的某个成员变量的值不想被序列化,可以给该成员变量加transient关键字修饰(瞬态关键字),该关键字标记的成员变量不参与序列化过程

打印流

PrintStream、PrintWriter

字节打印流

 字符打印流

 

总结:

①打印流不操作数据源,只操作目的地。即只能读不能写

②字节打印流:默认自动刷新,特有的println自动换行

③字符打印流:自动刷新需要开启,特有的prinln自动换行  

解压缩流

压缩包里的每一个文件在java中都是一个ZipEntry对象

解压

public class ZipStreamDemo01 {
    public static void main(String[] args) throws IOException {
        //创建一个File表示要解压的压缩包
        File src = new File("F:\\1heima-test\\ddd.zip");
        //创建一个文件夹表示解压的目的地
        File dest = new File("F:\\1heima-test\\dest");
        unZip(src,dest);
    }

    public static void unZip(File src,File dest) throws IOException {
        //解压的本质就是把压缩包中的每个文件读取出来,然后按照层级拷贝到目的地

        //创建一个解压流 读取压缩包中的数据
        ZipInputStream zip = new ZipInputStream(new FileInputStream(src));
        //获取压缩包中的每个文件 ZipEntry
        ZipEntry zipEntry;
        while ((zipEntry = zip.getNextEntry())!=null){
            System.out.println(zipEntry);
            //判断获取到数据是文件还是文件夹
            if (zipEntry.isDirectory()){
                //是文件夹的话,在目的地dest创建一个同样的文件夹
                //dest为父路径,zipEntry名字为子路径
                File file = new File(dest,zipEntry.toString());
                file.mkdirs();
            }else {
                //是文件的话。需要读取文件,并把它存放到目的地dest文件夹中
                FileOutputStream fos = new FileOutputStream(new File(dest,zipEntry.toString()));
                int b;//按字节读取
                while ((b = zip.read())!=-1){
                    fos.write(b);
                }
                fos.close();
                //表示在压缩包中的一个文件处理完毕了
                zip.closeEntry();

            }
        }
        zip.close();
    }
}

压缩单个文件 

public class ZipStreamDemo02 {
    public static void main(String[] args) throws IOException {
        /**
         * 压缩单个文件
         */
        //1.创建File对象表示要压缩的文件
        File src = new File("F:\\1heima-test\\a.txt");
        //2.要压缩到哪里
        File dest = new File("F:\\1heima-test");
        //3.调用方法
        toZip(src,dest);
    }

    public static void toZip(File src,File dest) throws IOException {
        //创建压缩流对象
        ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(new File(dest,"a.zip")));
        //创建ZipEntry对象,表示压缩包中的每个文件和文件夹
        ZipEntry zipEntry = new ZipEntry("a.txt");
        //把ZipEntry对象放到压缩包中
        zos.putNextEntry(zipEntry);
        //把src文件中的数据写到压缩包中
        FileInputStream fis = new FileInputStream(src);
        int b;
        while ((b = fis.read())!=-1){
            zos.write(b);
        }
        zos.closeEntry();
        zos.close();
    }
}

压缩多个文件

public class ZipStreamDemo03 {
    public static void main(String[] args) throws IOException {
        /**
         * 压缩文件夹
         */
        //创建文件 表示要压缩的文件夹
        File src = new File("F:\\1heima-test\\aaa");
        //创建文件 表示要压缩到哪里
        File destParent = src.getParentFile();
        //创建文件 表示压缩包的路径
        File dest = new File(destParent,src.getName()+".zip");
        //创建压缩流关联压缩包
        ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(dest));
        //获取src里面的每一个文件,变成ZipEntry对象,放到压缩包中
        toZip(src,zos,src.getName());

        //释放资源
        zos.close();


    }

    /**
     *
     * @param src 数据源
     * @param zos 压缩流
     * @param name  压缩包内部路径
     * @throws FileNotFoundException
     */

    public static void toZip(File src,ZipOutputStream zos,String name) throws IOException {
        //获取被压缩文件中的所有文件和文件夹
        File[] files = src.listFiles();
        for (File file : files) {
            if (file.isFile()){
                //是文件  变成ZipEntry对象,放到压缩包中
                ZipEntry zipEntry = new ZipEntry(name +"\\"+file.getName());
                //放到压缩包中
                zos.putNextEntry(zipEntry);
                //将数据源中的数据写入
                FileInputStream fis = new FileInputStream(file);
                int b;
                while ((b = fis.read())!= -1){
                    zos.write(b);
                }
                fis.close();
                zos.closeEntry();
            }else {
                //是文件夹的话 递归
                toZip(file,zos,name+"\\"+file.getName());
            }
        }
    }
}

Commons-io工具包

下载地址: Apache Commons – Apache Commons

 

Hutool工具包

Hutool — 🍬A set of tools that keep Java sweet.

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值