zoukankan      html  css  js  c++  java
  • JAVA笔记整理-File文件类-IO流

    一、Java的I/O

    1、什么是I/O?

    在生活中,你需要将U盘的文件 ,拷贝到电脑(或者将电脑的文件拷贝到其他设备), 文件是通过数据流的方式依次到达另一个设备中, 文件的拷贝就是一个输入(Input)和输出(Output)的过程

    Java中提供对应的API支持对文件的输入和输出 , java.io.*

    2、什么是流?

    生活中 也存在流的概念,例如 管道中的流水,从管道的入口到达管道出口,一滴水可以从入口流到出口,可以将“水”比作 “字节数据或字符数据”,数据也可以从一端流到另一端。

    输入(Input): Java中,以“应用程序(内存)”为中心,将磁盘文件(设备端)到达内存中的过程 称为 输入

    输出(Output): 以“应用程序(内存)”为中心,将数据从内存到达磁盘文件(设备端)的过程称为 输出

    根据文件操作方式不同可以将IO分为三类

    1、按照读写方向不同: 输入流(InputStream)和输出流(OutputStream)

    2、按照数据类型不同: 字节流(Byte)和字符流(Char)

    3、按照读写效率不同: 单一流和包装流(buffered等缓冲流)

    关于流的分类Java提供 4个顶级抽象类 ,分布构建它们的子类

    输入流 输出流
    字节流 InputStream(字节输入流) OutputStream(字节输出流)
    字符流 Reader(字符输入流) Writer(字符的输出流)

    常见的流

    1、文件字节输入流和文件字节输出流 : FileInputStream 和 FileOutputStream

    2、文件字符输入流和文件字符输出流: FileReader 和 FileWriter

    3、缓存字节输入流和 缓存字节输出流 BufferedInputStream 和 BufferedOutputStream

    4、缓存字符输入流和缓冲字符输出流 BufferedReader 和BuffereWriter

    5、数据输入流和数据输出流: DataInputStream 和 DataOutputStream

    6、字节数组输入流 和 字节数组输出流 : ByteArrayInputStream 和 ByteArrayOutputStream

    7、字符数组输入流 和 字符数组输出流: CharArrayReader 和 CharArrayWriter

    8、转换流: (字节流转成字符流) InputStreamReader 和 OutputStreamWriter

    9、对象流(序列化流): ObjectInputStream 和 ObjectOutputStream

    10、随机访问流(这个流既可以读,也可以写):RandomAccessFIle

    字节流

    定义: 文件的输入输出以一个“字节”为单位,进行流处理

    FileInputStream 和 FileOutputStream

    读入: 将文件中的数据读到内存中

    常用方法:

    ​ int read() : 一个字节的读取 ,返回字节 的asci码 ,对于汉字会分3次读取

    ​ int read(byte) : 按一个数组长度读取, 返回实际读取的字节长度, 数据存放在数组中

    ​ int read(byte , offset , len) : 读取流中指定长度的数据,并存放在指定位置,

    ​ available() :返回流中剩余的字节长度,如果已读完,则返回0

    ​ skip(long n ): 丢弃指定的字节长度,从下一个开始读取

    `**available**()`  
    
          File file = new File("d:/aaa.txt");
            FileInputStream fis = new FileInputStream(file);
           //
    		byte [] b= new byte[10];
            StringBuffer sb = new StringBuffer();
                //每次读取的长度,  b: 存放数据的数组
              int len = 0;
              while((len = fis.read(b)) !=-1){
                  sb.append( new String(b,0,len));
              }
    
            System.out.println(sb);
            fis.close();
    
     public static void read2() throws IOException {
            // InputStream是抽象类
            InputStream is = new FileInputStream("d:/aaa.txt");
            //丢弃前两个字节
            is.skip(2);
            System.out.println((char)is.read());
            System.out.println("还剩下多少个字节:"+ is.available());
            // 将后面的字节继续使用字节数组读
            byte [] b = new byte[10];
            int len = is.read(b,1,4);
            // 显示数组中读取的所有数据
            System.out.println(Arrays.toString(b));
            //将数组的内容转成字符串  对于空内容不会转换
            System.out.println(new String(b));
    
            is.close();
    
    
        }
    

    文件写出: 将内存的数据写出到磁盘中

    构造方法:

    new FileOutputStream(File/String ) : 构造文件对象的写出流, 默认覆盖写出

    new FileOutputStream(File/String , append): 构造文件对象的写出流,

    append:表示在原有文件上追加数据, false : 覆盖

    常用方法:

    ​ void write(int) : 写出一个字节

    ​ void writer(byte []) :写出一个字节数组,这里需要指定数组的编码格式 “UTF-8”

    ​ void writer(byte[] , offerset,len) : 写出一个字节数组,指定数组的长度和下标。 从数组的下标开始写出,len表示写出长度

    ​ flush() :清空缓存,对于使用缓冲流时,将缓冲强制清空。

       //将内存的数据写出到文件   如果文件不存在,会自动创建, 默认覆盖写入  true:追加
            FileOutputStream fos = new FileOutputStream("d://aaa.txt" ,true);
            String str="今天天气还不错";
            fos.write(99);
            //写出一个字符串    字符串可以转成字节数组 或字符数组
            fos.write(str.getBytes("UTF-8"));
            // 写出指定长度
            fos.write(str.getBytes("UTF-8"),0,3); // 写出这个数组的前2个字节
            // 清空缓存
            fos.flush();
            // 关闭流
            fos.close();
            System.out.println("写出成功");
    

    文件复制:

    将文件(图片,文本,视频)从一个目录复制到另一个目录, 其中数据长度不变,通过文件读写的方式完成复制

    复制过程:从源文件读取数据,然后将数据再出到目标文件中。

    /**
         * 单个字节复制
         * @param srcFile 源文件
         * @param disFile 目标文件
         */
        public static void copyFile(File srcFile, File disFile){
            FileInputStream fis=null;
            FileOutputStream fos =null;
            try {
                // 源文件输入流
                 fis = new FileInputStream(srcFile);
                // 目标文件输出流
                 fos = new FileOutputStream(disFile);
                int n=0;
                while( (n =fis.read()) !=-1){
                     //将读到的n写出到 目标文件中
                     fos.write(n);
                 }
                System.out.println("复制成功。。");
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally{
                //无论是否发生异常 都会关闭流
                try {
                    fos.close();
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
    
            }
    
        }
    
        /**
         * 一个字节数组的赋值
         * @param src  源地址
         * @param disc 目标地址
         */
        public static void copyFile(String src,String disc){
            FileInputStream fis = null;
            FileOutputStream fos = null;
            try {
                //创建 字节输入流
                fis=new FileInputStream(src);
                fos = new FileOutputStream(disc);
                int len=0;
                byte [] b = new byte[1024];
                while( (len= fis.read(b)) !=-1){
                    // 写出 实际读取的长度 ,为了避免在最后一次写出时出现多余字节
                    fos.write(b,0,len);
                }
    
                System.out.println("复制成功");
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally{
                try {
                    fos.close();
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
    
            }
        }
    

    练习一: 将d://mywork目录下的文件 赋值到 e://mywork
    ​ // 其中 目录下包含子目录 也按照相同的文件目录复制
    ​ // 思路: 1、先遍历文件夹,递归调用,
    ​ // 如果是文件先获取文件的父路径,如果不存在,就创建
    ​ // 如果存在路径就直接复制文件(调用刚才的赋值方法)
    ​ // 2、 创建父路径使用 mkdirs()
    ​ // 例如 d://mywork/aaa/1.txt
    ​ // 目标: e://mywork/aaa/1.txt 可以使用字符串替换 d:替换e:
    ​ // 先看这个路径是否存在,如果不存在 就创建

    字符流

    ​ 字符流用于读写存储字符的文件, 以一个字符为单位,一依次读取字符 文件, 常用类以 Reader或Writer为父类, 对文件的操作使用 java.io.FileReader 和java.io.FileWriter

    ​ 读文件 :FileReader

    常用方法:

    ​ new FileReader(path): 通过文件路径构建字符输入流

    ​ new FileReader(File):通过文件对象构建字符输入流

    • ​ int read() :读取一个字符 ,返回字符的int类型
    • ​ int read(char ):读取字符数组长度的数据 ,返回实际读取字符长度,数据存放在字符数组中
    • ​ int read(char offerset len):读取指定字符长度的数组,返回 实际读取字符的长度,数据存放在字符数组中
    • ​ mark(int) :标记流中当前位置 (读取到哪里了)
    • ​ markSupported():判断此流是否支持mark操作
    • ​ reset(): 重置流数据,(又可从头开始读取)
    • ​ skip(long) :丢弃指定长度字符

    读字符文件

        // 1、创建字符输入流
            try {
                FileReader reader = new FileReader("d:/myfile.txt");
                // 丢弃字符
                reader.skip(1);
                //读一个字符
                System.out.println((char)reader.read());
                System.out.println((char)reader.read());
                //读一个字符数组长度
                char [] c = new char[10];
                System.out.println("实际长度:"+reader.read(c));
                System.out.println(new String(c));
    
                //继续读
                int len =  reader.read(c,0,5);
                System.out.println("字符数组:"+ Arrays.toString(c));
                System.out.println("读指定长度字符个数:"+new String(c,0,len));
    
                // 将字符流重置
                // reader.reset();
                // System.out.println("重置后继续读:"+ reader.read());
    
                //System.out.println("是否支持标记字符:"+reader.markSupported());
                //关闭流,后面就不能使用该对象
                reader.close();
    
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
    

    写文件: 将内存数据写出到文件中,在写出过程中可以 覆盖写出也可以追加写出,FileWriter类创建对象过程

    ​ new FileWriter(String ):指定写出文件地址

    ​ new FileWriter(String ,append) : 指定写出文件地址,设置是否追加写出,true表示追加,false表示覆盖

    ​ new FileWriter(File)指定写出文件对象

    ​ new FileWriter(File ,append);指向写出文件对象,设置是否可追加

    常用方法:

    ​ writer(int) :写出一个字符

    ​ writer(String):写出一个字符串

    ​ writer(char [] ):写出一个字符数组

    ​ writer(char [] , offerset , len):写出一个指定长度的字符数组

    ​ flush() :刷新缓冲,

    ​ close():关闭缓冲

    ​ append(c) :将指定字符添加到此流中

       // 1、创建文件写出流 FileWriter
            try {
                // 文件不存在,可自动创建,但是不会创建目录
                File file = new File("d://myabc/aaa.txt");
                //判断文件目录不存在, 先创建目录
                if(!file.getParentFile().exists()){
                    //创建该目录
                    file.getParentFile().mkdirs();
                }
    
                FileWriter writer = new FileWriter("d://myabc/aaa.txt");
                // 写一个字符的asci
                writer.write(98);
                //写字符串
                writer.write("hello");
                //写指定长度的字符串
                writer.write("abcdef",0,3); //写abc
                char [] c = {'L','O','L'};
                //写字符数组
                writer.write(c);
                System.out.println("写出成功");
                writer.flush();
                writer.close();
    
            } catch (IOException e) {
                e.printStackTrace();
            }
    
    

    关闭和刷新:

    对于带有缓冲 功能的写出流,需要先刷新缓冲区,才能将数据写出,如果不刷新则最后不能正常写出。写出流如果刷新后还可以继续写,而关闭了则不能继续写。

    面试题 flush 和close的区别?

    flush: 刷新缓冲 ,流可以继续使用

    close: 先刷新缓冲器,然后再释放系统资源, 关闭后不能继续使用

       try {
                FileWriter writer = new FileWriter("1.txt");
                writer.write("刷");
                writer.flush();
                writer.write("新");
                writer.flush();
    
                writer.write("关");
                writer.close();
                writer.write("闭"); // 这里抛出异常 , Stream closed
                writer.close();
    
    
            } catch (IOException e) {
                 e.printStackTrace();
            }
    

    关于换行符

    回车符 和换行符 :
    回车符:回到一行的开头(return)。
    换行符:下一行(newline)。
    系统中的换行:
    Windows系统里,每行结尾是 回车+换行 ,即 ;
    Unix系统里,每行结尾只有 换行 ,即 ;
    Mac系统里,每行结尾是 回车 ,即 。从 Mac OS X开始与Linux统一。

  • 相关阅读:
    HTML5数据推送SSE原理及应用开发
    用Docker构建分布式Redis集群
    开发者必备的12个JavaScript库
    分享:我用一天时间开发的 新年送祝福 微信手机网站(可在线体验附图)(要代码的留下邮箱)
    祝福csdn回望2014,展望2015 大致可以这样总结和展望
    对 云寻觅贴吧(http://tieba.yunxunmi.com/)的简要分析
    开源前夕先给大家欣赏一下我用C语言开发的云贴吧 网站自动兼容-移动、手机、PC自动兼容云贴吧
    舞蹈模特欣欣(六)棚拍私房 大家看看像小龙女(李若彤)吗?
    终于解决了贴吧手机版的一个重大BUG
    比基尼美女_人像摄影吧主题
  • 原文地址:https://www.cnblogs.com/z5452830/p/13944476.html
Copyright © 2011-2022 走看看