JAVA-----IO篇(概念介绍以及FileIputStream)一

JAVA-----IO篇

io主要是对内存以及硬盘之间的输入、输出操作进行定义。

i:即使input。o:即使output。
输入(input)、输入流(inputStream)、读(read):都是将硬盘中的信息传递到内存中。硬盘—>内存。
输出(output)、输出流(outputStream)、写(Write):则是内存---->硬盘。其实可以看做对象序列化的过程(不知道这样说是否确切)。
这两个顺序容易搞混,需要明确记忆。【主角是内存】,所谓输入、输出都是对于内存而言。
对io流进行分类便于理解和记忆

io流的分类:

  1. 按照流的方向进行分类:
    以内存为参照物
    数据往内存中去,即为:输入、输入流、读。
    数据从内存中出,即为:输出、输出流、写。
  2. 按照读取数据方式进行分类:
    有的流按照字节的方式进行读取,一次读取一个字节byte,等同于一次读取8个二进制位。
    这种流是万能的,字节流。 什么类型的文件都能够读取,包括但不限于文本、图片、声音文件、视频文件。
    另外一种即按照字符的方式进行读取,一次读取一个字符,这种流为了方便读取普通文本文件。称为字符流,只能读取纯文本文件,视频、声音都不能被读取,甚至word文件也不能被读取。普通文本文件是指以txt作为后缀名的文件。
    比如文件file.txt中,内容为:a你好世界aaaa
    1. 以字符流的形式读取该文件,第一次读取:'a’字符(在windows系统中,a字符占用一个字节)
      第二次读取:‘中’字符(在windows中,中字符占用2个字节)。
    2. 如果以字节流的形式进行读取,则第一次读a,第二次读’中’字符的一半,第三次就读’中’的另外一半。
      综上所述:流的分类:输出流、输出流。 字符流、字节流。

Java中char类型占用两个字节,windows中是一个字节。

Java中提供了哪些流?相关的方法?每个流的特点是什么?

java中所有的流都是在java.io包下
java.io下有四大家族。分别是;java.io.inputStream(字节输入流),java.io.outputStream(字节输出流)、java.io.Reader(字符输入流)、java.io.Writer(字符输出流)。这四个都是抽象类。具体实现是根据其子类。 所有的流都实现了java.io.closeable接口,都是可关闭的,都有close方法,在对流的操作完毕后,一定要关闭流,流的使用会使用大量的资源。

注意:java中只要类名“以Stream结尾的都是字节流,以Reader/Writer结尾的都是字符流,着重对Stream进行理解学习”

输出流:outputStream以及Writer还拥有一个共同特性,继承了flushable接口,所有的输出流,都是可刷新的,都具有flush()方法,在用完输出流时,一定要进行刷新,表示将流管道中剩余未输出的数据强行输出完,刷新的所用就是清空管道。
注意:如果没有flush()可能会造成数据丢失。

java.io包下需要掌握的16个流(其实有很多,这16个常用)。分别是

文件专属流(4个):
java.io.FileInputStream
java.io.FileOutputStream
java.io.FileReader
java.io.File.Writer
华丽分割线---------------------------------------------------------------------
转换流(将字节流转换为字符流)(2个):
java.io.InputStreamReader
java.io.OutputStreamWriter
华丽分割线---------------------------------------------------------------------
缓冲流专属(4个):
java.io.BufferedReader
java.io…BufferedWriter
java.io…BufferedInputStream
java.io…BufferedOutputStream
华丽分割线---------------------------------------------------------------------
数据流专属(2个):
java.io.DataInputStream
java.io.DataOutputStream
华丽分割线---------------------------------------------------------------------
标准输出流(2个):
java.io.PrintWriter
java.io.PrintStream
华丽分割线---------------------------------------------------------------------
对象专属流(2个):
java.io.ObjectInputStream
java.io.ObjectOutputStream
华丽分割线---------------------------------------------------------------------

java.io.FileInputStream

FileInputStream是对txt文件的读取,第一次读取第一个字符,在读取时会读取第二个字符,在实际应用则不会一下一下读取,一般是使用循环读取。对于读到的字符返回ASCI值,如果读完了,再次读就会返回-1,而对于文件中的空格【 】,会返回32,空格也是一个字符。

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

/**
 * @author cz
 * @date 2020/6/11/011
 * 文件字节输入流,完成的,任何类型文件都能够采用这种方式
 * 从硬盘到内存的输入方式
 **/
public class FileInputStreamTest01 {
    public static void main(String[] args) {
        //创建文件输入流对象,以下采用绝对路径的方式,相对路径也可以
    //    文件路径F:\a.txt,(IDEA中能够自动将\变为\\),因为在java中\表示转义字符fileInputStream = new FileInputStream("F:\\a.txt");
    //    FileInputStream fileInputStream = new FileInputStream("F:\\a.txt");   文件内容asdasdasd
    //    此时存在编译时异常,需要程序员进行手动处理,这里进行try..catch
    //    不写\\而是改为\,也是可以的
        FileInputStream fileInputStream=null;
        try {
            fileInputStream = new FileInputStream("F:\\a.txt");
//            开始读
            int read = fileInputStream.read();  //返回值是读取到的字节本身
            System.out.println(read);  // a返回97,读第一次时指向第一个字符,再次调用read方法,就会指向第二个字符,当什么都没有时返回-1.

            read = fileInputStream.read();  //s返回115
            System.out.println(read); //s返回115
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
//            在finlly中确保流一定要进行关闭,前提是该流不能为空
            if (fileInputStream!=null){  // 当流是空时没必要关闭,避免空指针异常
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}

使用FileInputStream循环读取txt文件。此时文件内容为 a sdasdasd。在while循环(),括号中的条件必须为true或者为false。

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

/**
 * @author cz
 * @date 2020/6/11/011
 * 文件字节输入流,完成的,任何类型文件都能够采用这种方式
 * 从硬盘到内存的输入方式
 **/
public class FileInputStramTest01 {
    public static void main(String[] args) {
        //创建文件输入流
    //    文件路径F:\a.txt,(IDEA中能够自动将\变为\\),因为在java中\表示转义字符fileInputStream = new FileInputStream("F:\\a.txt");
    //    FileInputStream fileInputStream = new FileInputStream("F:\\a.txt"); 
    //    此时存在编译时异常,需要程序员进行手动处理,这里进行try..catch
    //    不写\\而是改为\,也是可以的
        FileInputStream fileInputStream=null;
        try {
            fileInputStream = new FileInputStream("F:\\a.txt");
//            开始读
            while (true){
                int read = fileInputStream.read();  //返回值是读取到的字节本身
                if (read==-1){
                    break;
                }
                System.out.println(read);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
//            在finlly中确保流一定要进行关闭,前提是该流不能为空
            if (fileInputStream!=null){  // 避免空指针异常
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}

在这里插入图片描述
可以对while循环进行改造。

 int readData = 0;
            while ((readData = fileInputStream.read())!=-1){
                System.out.println(readData);
            }

这样代码看起来会简洁一些。
但是这种读取方式效率太低,一次只读取一个字节,内存与硬盘之间的IO会占用极大地系统资源,在具体应用中会采取更加高效的方法。
在FileInputStream中同样提供了另一种方法,能够一次读取多个字节, int read(byte[] b),一次读取b.length个字节,往byte数组当中读取。能够减少内存和硬盘之间的交互次数,提高程序的执行效率。这个方法的返回值是读到的数组长度,当没有读取到内容时也是返回-1。而每一次读取,实际上是将读取到的内容存入byte数组,那么第二次读取到的的内容就会覆盖第一次内容,如果第二次只读取1个字节,那么只有第一个字节会被覆盖,数组后续的字节依然不会被改变

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

/**
 * @author cz
 * @date 2020/6/11/011
 * 文件字节输入流,完成的,任何类型文件都能够采用这种方式
 * 从硬盘到内存的输入方式
 **/
public class FileInputStramTest01 {
    public static void main(String[] args) {
        FileInputStream fileInputStream=null;
        try {
            fileInputStream = new FileInputStream("F:\\a.txt");
//            开始读
           byte[] b = new byte[4];
            int read = fileInputStream.read(b);
            System.out.println(read);  //4
            System.out.println(new String(b));
            read = fileInputStream.read(b);
            System.out.println(read); // 4
            System.out.println(new String(b));   //dasd
            read = fileInputStream.read(b);
            System.out.println(read);  // 3
            System.out.println(new String(b));   //asdd  只读取到3个数,覆盖前3个
            read = fileInputStream.read(b);
            System.out.println(read);  // -1
            System.out.println(new String(b));   //asdd  没有读取到数字,不覆盖
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
//            在finlly中确保流一定要进行关闭,前提是该流不能为空
            if (fileInputStream!=null){  // 避免空指针异常
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

这种输出方法会将数组的全部内容输出,于预期不符,应该是读取到什么,就输出什么。
System.out.println(new String(b,0,read)); 应该这样,从数组0,开始输出,长度为读取的长度,注意当内容结束时,再次读取read返回值就是-1,此时0,-1就会出现数组越界。进行循环输出和之前相同。

byte[] b = new byte[4];
           int readC = 0;
           while ((readC = fileInputStream.read(b))!=-1){
               System.out.print(new String(b,0,readC));
           }

fileInputStream的其他常用方法: int avaliable():返回流当中剩余的字节数量,length skip(long n):跳过几个字节数不读。

使用avaliable()方法,能够知道该文件的(剩余)字节长度,可以创建出该长度的byte数组,直接一次读出,但是不适合大文件,因为byte数组不能太大。

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

/**
 * @author cz
 * @date 2020/6/11/011
 * 文件字节输入流,完成的,任何类型文件都能够采用这种方式
 * 从硬盘到内存的输入方式
 **/
public class FileInputStramTest01 {
    public static void main(String[] args) {
        FileInputStream fileInputStream=null;
        try {
            fileInputStream = new FileInputStream("F:\\a.txt");
//            开始读
            System.out.println("总字节数"+fileInputStream.available());  // 11
//            int read = fileInputStream.read();
//            System.out.println("剩余字节数"+fileInputStream.available());  //10
            byte[] b  = new byte[fileInputStream.available()];
            int readCount = fileInputStream.read(b);
            System.out.println(new String(b,0,readCount));  //a  sdasdasd
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
//            在finlly中确保流一定要进行关闭,前提是该流不能为空
            if (fileInputStream!=null){  // 避免空指针异常
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

skip跳过方法。

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

/**
 * @author cz
 * @date 2020/6/11/011
 * 文件字节输入流,完成的,任何类型文件都能够采用这种方式
 * 从硬盘到内存的输入方式
 **/
public class FileInputStramTest01 {
    public static void main(String[] args) {
        FileInputStream fileInputStream=null;
        try {
            fileInputStream = new FileInputStream("F:\\a.txt");
//            开始读
            System.out.println("总字节数"+fileInputStream.available());  // 11
            fileInputStream.skip(3);
            byte[] b  = new byte[fileInputStream.available()];
            int readCount = fileInputStream.read(b);
            System.out.println(new String(b,0,readCount));  //sdasdasd
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
//            在finlly中确保流一定要进行关闭,前提是该流不能为空
            if (fileInputStream!=null){  // 避免空指针异常
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

以上就是关于FileIputStream的常用方法,和基本使用方式。
欢迎点赞评论,提出问题意见

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章