IO流

 

IO流和容器

1. IO流

IO流图

io

1.1. IO概念

流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。

1.2. 数据源

data source. 提供原始数据的原始媒介。常见的:数据库、文件、其他程序、内存、网络连接、IO设备。数据源就像水箱,流就像水管中流着的水流,程序就是我们最终的用户。 流是一个抽象、动态的概念,是一连串连续动态的数据集合

image-20200401193822821

 

1.3. IO流的分类

最长用到的 :


1.3.1. 字节流
  • 输入流(InputStream)
    • 操作步骤

      1. 选择流InputStream

      2. 操作流(写入或写出)

      3. 释放系统资源

    • 示例

    //这里是直接抛出异常
    public class IO_Demo01 {
        public static void main(String[] args) throws IOException {
            //1、创建流
            //FileInputStream 文件字节输入流,专门用来读入文件中数据内容的
            InputStream is01=new FileInputStream("E:/test.txt");
            //2、操作流
            //读入到arr中的字节个数
            int len=-1;
            byte[] arr=new byte[1024*2];//1024的整数倍
            while ((len=is01.read(arr))!=-1){
                System.out.println(new String(arr, 0, len));
            }  
            //3、关闭资源
            is01.close();
        }
    }
    //try...catch 捕获异常,推荐这种做法
    public class CopyFile01 {
        public static void main(String[] args) {
            //1、创建流
            InputStream is=null;
            try {
                is=new FileInputStream("E:/aaa.txt");
                //操作流
                byte[] arr=new byte[1024];//按照1024 批量输入
                int len=-1;
                while ((len=is.read(arr))!=-1){
                    System.out.println(new String(arr, 0, len));
                }
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                //关闭
                if(is!=null){
                    try {
                        is.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
  • 输出流(OutputStream)
    • 操作步骤

      1. 选择流

      2. 操作流

      3. 刷新(flush)

      4. 关闭系统资源

    • 示例

    /*
        FileOutputStream(String name)   
            创建一个向具有指定名称的文件中写入数据的输出文件流。 
        FileOutputStream(String name, boolean append) 
            创建一个向具有指定 name 的文件中写入数据的输出文件流。 
        FileOutputStream(File file) 
            创建一个向指定 File 对象表示的文件中写入数据的文件输出流。 
        FileOutputStream(File file, boolean append)  
    */
    public class IODemo02 {
        public static void main(String[] args) throws IOException {
            //1.选择流
            //输出流指向的文件,不存在,系统会自动创建,但是不会创建文件夹
            OutputStream os=new FileOutputStream("E:/AAA.txt",true); 
            //2.写出 write(int) 写出一个字节
            byte[] arr = "今天是周二,开会不要忘记了!!!".getBytes();
            os.write(arr);
            //3.刷出
            os.flush();
            //4.关闭
            os.close();
        }
    }
    • 输入流和输出流

    //将E盘下aaa.txt的内容拷贝到D盘下aaa.txt中
    public class CopyFile01 {
        public static void main(String[] args) {
            //1、创建流
            InputStream is=null;
            OutputStream os=null;
            try {
                is=new FileInputStream("E:/aaa.txt");
                os=new FileOutputStream("D:/aaa.txt");
                //2、操作流
                byte[] arr=new byte[1024];
                int len=-1;
                while ((len=is.read(arr))!=-1){
                    os.write(arr,0,len);
                }
                //3、刷新
                os.flush();
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                //4、关闭
                //先打开的后关闭
                if(os!=null){
                    try {
                        os.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if(is!=null){
                    try {
                        is.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
1.3.2. 字符流
  • 字符输入流(Reader)

    只能读纯文本文件

    • 操作步骤

      1. 选择流

      2. 操作流

      3. 关闭系统资源

    • 示例

    public class IO_RWer {
        public static void main(String[] args) throws IOException {
            //1、创建流
            Reader rd=new FileReader("E:/aaa.txt");
            //2、操作流(读入)
            char[] arr=new char[1024];
            int len=-1;
            while ((len=rd.read(arr))!=-1){
                System.out.println(new String(arr,0,len));
            }
            //3、关闭
            wt.close();
            rd.close();
        }
    }
    public class IO_RWer {
        public static void main(String[] args) throws IOException {
            //1、创建流
            Reader rd=new FileReader("E:/aaa.txt");
            Writer wt=new FileWriter("E:/BBB.txt");
            //2、读入和写出
            char[] arr=new char[1024];
            int len=-1;
            while ((len=rd.read(arr))!=-1){
                wt.write(arr);
            }
            //3、刷新
            wt.flush();
            //4、关闭
            wt.close();
            rd.close();
        }
    }
1.3.3. 缓冲流

BufferedInputStream

缓冲提高性能: 字节流直接套上即可;字符缓冲流 +新增方法(不能使用多态):

//1、创建源,建立联系 
File src =new File("test.txt");
//2、选择缓冲流 
InputStream is =new BufferedInputStream(new FileInputStream(src)); 
//3、操作 : 多个读取    
byte[] car =new byte[2];
int len =0;   
while(-1!=(len=is.read(car))){     
  //获取数组的内容  字节数组转字符串 new String(字节数组,0,length)
  System.out.println(new String(car,0,len));     
}
//4、释放资源
is.close();
1.3.4. 转换流

转换流:将字节流转为字符流 处理乱码(编码集、解码集)。

//读取文件
File src =new File("test.txt");
//转换流
BufferedReader br =new BufferedReader(
  new InputStreamReader(new BufferedInputStream(new FileInputStream(src)),"utf-8" ) 
 );
//行读取
String msg =null;
while(null!=(msg =br.readLine())){
  System.out.println(msg);
}
br.close();
View Code
1.3.5. 数据处理流

可以处理基本类型+String,保留数据的类型。前提是读取顺序与写出顺序一致,否则读取数据不正确

/**
* 数据+类型 输出到文件
*/
public static void write(String destPath) throws IOException{
  int point = 2;
  long num = 100L;
  String str = "数据类型";
  //创建源
  File dest = new File(destPath);
  //选择流
  DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new
FileOutputStream(dest)));
  //操作 写出的顺序 为读取作准备
  dos.writeInt(point);
  dos.writeLong(num);
  dos.writeUTF(str);
  //刷新
  dos.flush();
  //释放资源
  dos.close();
}
View Code
1.3.6. 对象流

以前我们学过的流都只能读写字节,字符形式的数据,而java中非常重要并且常见的对象类型的数据,如果想要存储到文件中应该怎么操作呢?这个时候就使用到了对象流。

  • 序列化:是一个用于将对象状态转换为字节流的过程,可以将其保存到磁盘文件中或通过网络发送到任何其他程序
  • 反序列化:从字节流创建对象的相反的过程称为 反序列化
  • 对象处理流(反序列化):ObjectInputStream:
    1. ObjectInputStream能够让你从输入流中读取Java对象,而不需要每次读取一个字节。你可以把InputStream包装到ObjectInputStream中,然后就可以从中读取对象了

    2. 首先在使用ObjectInputStream和ObjectOutputStream的时候,放置在此IO中的对象,必须要实现Serializable

    3. 序列化接口(Serializable实现了此接口,代表我们的对象支持序列化)但是实现了Serializable接口之后,其中并没有实现任何方法,对于这种接口,我们称之为标记接口。

  • 反序列化:

    1. 先写入再读取

    1. 读取对象需要知道具体类型,依次读取

  • 注意:

    • 1)不是所有的对象都可以序列化 Serializable

    • 2)不是所有的属性都需要序列化 transient

    public static void read(String srcPath) throws FileNotFoundException, IOException,
    ClassNotFoundException{
    //创建源
    File src=new File(srcPath);
    //选择流 OjbectInputStream
    ObjectInputStream dis=new ObjectInputStream(
    new BufferedInputStream(
    new FileInputStream(src)
    )
    );
    //操作 读取的顺序与写出的顺序一致 必须存在才能读取
    Object obj=dis.readObject();
    if(obj instanceof Employee){
    Employee emp=(Employee)obj;
    System.out.println(emp.getName());
    System.out.println(emp.getSalary());
    }
    obj=dis.readObject();
    int[]arr=(int[])obj;
    System.out.println(Arrays.toString(arr));
    //释放资源
    dis.close();
    }
    View Code
  • ObjectOutputStream(序列化) 注意: 要先序列化后反序列化

    //创建源
    File dest=new File(destPath);
    //选择流 OjbectOutputStream
    ObjectOutputStream dos=new ObjectOutputStream(
      new BufferedOutputStream(new FileOutputStream(dest))
    );
    //操作 读取的顺序与写出的顺序一致 必须存在才能读取
    Employee obj=new Employee ("yinwei",1500);
    dos.writeObject(obj);
    //刷出
    dos.flush();
    //释放资源
    dos.close();
    View Code

     

1.4. commons-IO

commons-IO是apache的一个开源的工具包,封装了IO操作的相关类,使用Commons IO可以很方便的读写文件,url 源代码等。commons-IO 需要加入classpath 的第三方 jar 包内的 class 文件才能在项目中使用

  1. 导入 commons-io jar包

image-20200401212902732


  • commons-io-2.4.jar 就是需要导入到项目中的 jar 包,里面存放的是class文件

  • commons-io-2.4-sources.jar 工具类中原代码

  • docs 是帮助文档

  1. 导入 commons-io build path->add to build path

  2. commons-io 的使用

    3.1. IO 工具类 FilenameUtils 这个工具类是用来处理文件名(文件路径)的,可以轻松解决不同操作系统文件名称规范不同的问题,里面的方法都是静态的,直接用类进行调用

    • 常用方法:

      • getName():获取文件名 getExtension(String path):获取文件的扩展名 isExtension(String fileName,String ext):判断fileName是否是ext后缀名

    3.2. 工具类 FileUtils

    提供文件操作,如移动文件、读取文件、检查文件是否存在等的方法

    • 常用方法:

      • readFileToString(File file,String charset):读取文件内容,并返回一个String writeStringToFile(File file,String content, String charset):将内容content写入到file中

      • copyDirectoryToDirectory(File srcDir,File destDir):文件夹复制 copyFile(File srcFile,File destFile):文件复制

2. 容器

2.1. 容器的概念

之前我们学习过数组,数组是相同数据类型的有序集合,可以在其中放置对象或基本类型数据,说白了就是容器。 数组是一种简单的线性序列,可以快速的访问数组元素,效率高

image-20200401214441128

2.2. Collection接口

Collection 表示一组对象,它是集中,收集的意思,就是把一些数据收集起来,Collection 接口的两个子接口:

  • Set 中的数据没有顺序,不可重复

  • List 中的数据有顺序,可重复

2.2.1. List接口
  • <E> 泛型

    增强程序的可读性和稳定性。

  • ArrayList

    ArrayList 是 List 的子类,允许存放重复元素,因此有序。集合中元 素被访问的顺序取决于集 合的类型。如果对 ArrayList 进行访问,迭代器将从索引 0 开始, 每迭代一次,索引值加 1。

  • List集合遍历

    • 普通for循环方式

    • 增强for循环方式

    • 迭代器

    • Stream流遍历

    public class LIstDemo03 {
        public static void main(String[] args) {
            List<Integer> ls= new ArrayList();
            ls.add(3);
            ls.add(1);
            ls.add(2);
            ls.add(7);
            ls.add(6);
            ls.add(5);
            //void add(int index, E element) 
            ls.add(3,3);
            System.out.println(ls);
            // E get(int index) 
            System.out.println(ls.get(0));
            // int indexOf(Object o)  
            System.out.println(ls.indexOf(2));
            
            //remove(int index)
            ls.remove(2);
            System.out.println(ls);
            // E set(int index, E element)  
            System.out.println(ls.set(2,2));
            System.out.println(ls);
            //遍历方式:
            System.out.println("--------for普通-------");
            for(int i = 1;i<ls.size();i++) {
                System.out.println(ls.get(i));
            }
            System.out.println("--------for..each-------");
            for(int i:ls) {
                System.out.println(i);
            }   
            System.out.println("--------iterator-------");
            Iterator<Integer> it = ls.iterator();
            while(it.hasNext()) {
                System.out.println(it.next());
            }
        }
    }
    View Code
  • LinkedList

    LinkedList 是一种可以在任何位置进行高效地插入和删除操作的有序序列。底层用双向链表实现的 List。特点:查询效率低,增删效率高,线程不安全。

    ArrayList:底层用数组实现的 List。特点:查询效率高,增删效率低,线程不安全。

    public class LInkedList {
        public static void main(String[] args) {
            LinkedList<Person> linklist=new LinkedList<Person>();
            linklist.add(new Person(33,"李小龙"));
            linklist.add(new Person(23,"李连杰"));
            linklist.add(new Person(33,"李广"));
            linklist.add(new Person(33,"李世民"));
            System.out.println(linklist.size());
            linklist.add(2,new Person(45,"李逍遥"));
            System.out.println(linklist);
            linklist.remove(2);
            System.out.println(linklist);
            linklist.set(0,new Person(18,"李小龙"));
            System.out.println(linklist);
        }
    }
    View Code
posted @ 2020-04-01 22:05  smile马伊子  阅读(164)  评论(0)    收藏  举报