IO流-(File)

day22.IO流

课前回顾:
  1.TreeSet
    a.特点:元素可以排序,元素唯一,无索引,线程不安全
    b.数据结构:红黑树
    c.构造:
      TreeSet()
      TreeSet(Comparator c)
  2.TreeMap
    a.特点:可以对key排序,key唯一,无索引,线程不安全
    b.数据结构:红黑树
    c.构造:
      TreeMap()
      TreeMap(Comparator c)
  3.Hashtable:
    a.特点:key唯一  无序  无索引  线程安全  不能存nullnull值
    b.使用:HashMap一样
  4.Vector:
    a.特点:元素可重复 有序 有索引 线程安全
    b.使用:ArrayList一样
  5.Properties集合
    a.特点:key唯一  无序  无索引  线程安全  不能存nullnull值  key和value都是String
    b.特有方法:
      setProperty(k,v)
      getProperty(k)
      stringPropertyNames():获取所有的key
      load(InputStream in)->将流中的数据信息加载到Properties集合中
 

File创建文件文件夹

 6.File:
    a.静态成员
      static String pathSeparator  ->  与系统有关的路径分隔符    ;
      static String separator-> 与系统有关的默认名称分隔符        \
    b.构造:
      File(String parent,String child)
      File(File parent,String child)
      File(String path)
    c.获取方法:
      getAbsolutePath()获取绝对路径
      getPath()获取的是封装路径
      getName()获取文件或者文件夹名字
      length()获取文件的字节数,不是文件夹
      getParentFile()获取父路径
    d.创建方法:
      createNewFile()创建文件
      mkdirs()创建文件夹
    e.删除方法:
      delete()->不走回收站
    f.判断方法:
      isFile()
      isDirectory()
      exists()
    g.遍历方法:
      list()
      listFiles()
 
今日重点:
    1.要分清IO流流向->什么是输入  什么是输出
    2.会使用所有的流进行写数据(输出)  读数据(输入)

第一章.字节流_字节输出流

1.IO流介绍以及输入输出以及流向的介绍

1.概述:
  I:In-> 输入-> 读进来
  O:Out-> 输出->写出去
2.什么是IO流技术
  将数据从一个设备上传输到另外一个设备上的技术
3.为什么要学IO流
  之前我们学过数组,集合,这两个都是存储数据的,而且是临时存储,程序运行完毕,程序会从内存中释放出来,此时集合和数组中的数据就没了
  我们就想,如何将数据永久保存呢?我们可以将数据放到硬盘的文件中,只要硬盘不废,数据就还在.想用的时候,从硬盘的文件中读出来使用
      
  IO流技术就可以将内存中的数据保存到硬盘上,用的时候还可以从硬盘上将数据读回来使用

2.IO流的流向

1.输出流:从内存出发,将数据写到硬盘的文件中
2.输入流:将数据从硬盘的文件中读到内存中

IO流-(File)_第1张图片

3.IO流分类

1.字节流:一切皆字节,万能流
        复制的话一定要用字节流
    
  字节输出流:OutputStream
  字节输入流:InputStream
      
      
2.字符流:操作文本文档->能用记事本打开,人能看懂的
        .html  .txt  .java .css
        .doc不是->用记事本打开,会乱码
   
  字符输出流:Writer
  字符输入流:Reader
      

3.单词考验
  FileOutputStream:字节输出流
  FileInputStream:字节输入流
  FileWriter:字符输出流
  FileReader:字符输入流
  BufferedOutputStream:缓冲字节输出流
  BufferedInputStream:缓冲字节输入流
  BufferedWriter:缓冲字符输出流
  BufferedReader:缓冲字符输入流
  ObjectOutputStream:序列化流 -> 写数据
  ObjectInputStream:反序列化流-> 读数据
  InputStreamReader:转换流->读数据
  OutputStreamWriter:转换流->写数据
  PrintStream:打印流->输出流->写数据
      
所有的输出流,都统一用write方法,写数据
所有的输入流,都统一用read方法,读数据

4.OutputStream中子类[FileOutputStream]的介绍以及方法的简单介绍

1.字节输出流:OutputStream->抽象类
2.OutputStream是抽象类,不能new对象,所以我们需要学习子类
  FileOutputStream
3.构造:
  FileOutputStream(File file) 
  FileOutputStream(String name) 
  以上两个构造方法,new的时候需要传递文件的路径
4.注意:输出流(所有流)在写数据的时候,如果指定的文件不存在,会自动创建
5.方法:
  void write(int b) -> 一次写一个字节
  void write(byte[] b) -> 一次写一个字节数组
  void write(byte[] b, int off, int len) -> 一次写一个字节数组一部分
             b:代表要写的数组
             off:代表从数组的哪个索引开始写
             len:写多少个
  void close() -> 关闭流对象
                 
public class Demo01_FileOutputStream {
    /**
     * void write(int b) -> 一次写一个字节
     */
    public static void main(String[] args) throws Exception {
        FileOutputStream fos = new FileOutputStream("day22\\io\\fileout.txt");
        fos.write(97);
        //关流
        fos.close();
    }

}
public class Demo02_FileOutputStream {
    /**
     *  void write(byte[] b) -> 一次写一个字节数组
     */
    public static void main(String[] args) throws Exception {
        FileOutputStream fos = new FileOutputStream("day22\\io\\fileout.txt");
        //定义数组
        byte[] bytes = {97,98,99,100};

        fos.write(bytes);
        //关流
        fos.close();
    }

}

public class Demo03_FileOutputStream {
    /**
     *    void write(byte[] b, int off, int len) -> 一次写一个字节数组一部分
     *              b:代表要写的数组
     *              off:代表从数组的哪个索引开始写
     *              len:写多少个
     */
    public static void main(String[] args) throws Exception {
        FileOutputStream fos = new FileOutputStream("day22\\io\\fileout.txt");
        //定义数组
        byte[] bytes = {97,98,99,100};

        fos.write(bytes,0,2);
        //关流
        fos.close();
    }

}

public class Demo04_FileOutputStream {

    public static void main(String[] args) throws Exception {
        FileOutputStream fos = new FileOutputStream("day22\\io\\fileout.txt");
        //定义数组
        //byte[] bytes = "a".getBytes();

        //byte[] bytes = "中国你好".getBytes();

        //byte[] bytes = "97".getBytes();
        //fos.write(bytes);

        fos.write("涛哥和柳岩那个啥的故事".getBytes());
        //关流
        fos.close();
    }

}

IO流-(File)_第2张图片

1.注意
  输出流,默认每次运行都会创建一个新的文件,把之前文件覆盖,无法实现内容追加
2.实现内容追加,不覆盖
  FileOutputStream(String name, boolean append) -> 实现内容追加,不覆盖
                   name:文件路径
                   append:false->不追加,会覆盖
                          true-> 追加,不会覆盖
3.实现换行->换行符
  windows:\r\n -> 毕竟有一个r有一个n组成,所以一个换行符占2个字节
public class Demo05_FileOutputStream {

    public static void main(String[] args) throws Exception {
        FileOutputStream fos = new FileOutputStream("day22\\io\\fileout.txt",true);
        //fos.write("涛哥和那个啥的故事".getBytes());
        //fos.write("\r\n".getBytes());

        fos.write("涛哥和那个啥的故事\r\n".getBytes());
        //关流
        fos.close();
    }
}

第二章.字节流_字节输入流

1.InputStream子类[FileInputStream]的介绍以及方法的使用

1.概述:字节输入流-> InputStream-> 抽象类
2.子类:FileInputStream->读数据
3.构造:
  FileInputStream(File file) 
  FileInputStream(String name) 
4.注意:读要读已有的文件,不能自动创建文件
5.方法:
  int read() -> 一次读取一个字节,返回的是读取的字节内容 
  int read(byte[] b) -> 一次读取一个字节数组,返回的是读取的字节个数 
  int read(byte[] b, int off, int len) -> 一次读取一个字节数组一部分,返回的是读取的字节个数 
           b:要读取的数组
           off:从数组的哪个索引开始读
           len:读多少个
  void close()  -> 关流

2.一次读取一个字节

public class Demo01_FileInputStream {
    /**
     * int read() -> 一次读取一个字节,返回的是读取的字节内容
     */
    public static void main(String[] args)throws Exception {
        FileInputStream fis = new FileInputStream("day22\\io\\filein.txt");
        /*int read01 = fis.read();
        System.out.println(read01);

        int read02 = fis.read();
        System.out.println(read02);

        int read03 = fis.read();
        System.out.println(read03);

        int read04 = fis.read();
        System.out.println(read04);

        int read05 = fis.read();
        System.out.println(read05);

        int read06 = fis.read();
        System.out.println(read06);*/

        //定义一个变量,接收每次读取的字节
        int len;
        while((len = fis.read())!=-1){
            System.out.println((char) len);
        }
        fis.close();
    }
}

1.循环读取的时候,不要再判断的时候读一次,输出的时候再读一次

2.如果一个流对象被close了,此对象不能再使用了

3.IO流对象,如果将文件中的内容读完了,就不能再次使用此对象读了

IO流-(File)_第3张图片

3.读取-1的问题

1.每个文件最后(末尾),都有一个结束标记,此结束标记看不见,摸不着

IO流-(File)_第4张图片

4.一次读取一个字节数组以及过程

public class Demo03_FileInputStream {
    /**
     * int read(byte[] b) -> 一次读取一个字节数组,返回的是读取的字节个数
     */
    public static void main(String[] args) throws Exception {
        FileInputStream fis = new FileInputStream("day22\\io\\filein.txt");
      /*
        创建byte数组
        数组作用:看做是一个临时存储区,我读取的数据会先放到数组中,然后我们从数组中拿数据

        数组一般长度定为1024或者1024的倍数
       */
        byte[] bytes = new byte[6];
       /* int read01 = fis.read(bytes);
        //System.out.println(read01);//2代表的是读了2个
        //System.out.println(new String(bytes));
        System.out.println(new String(bytes,0,read01));

        int read02 = fis.read(bytes);
        //System.out.println(read02);//2代表的是读了2个
        //System.out.println(new String(bytes));
        System.out.println(new String(bytes,0,read02));

        int read03 = fis.read(bytes);
        //System.out.println(read03);//1代表的是读了1个
        //System.out.println(new String(bytes));
        System.out.println(new String(bytes,0,read03));*/



       //定义一个变量,代表读取的个数
        int len;
        while((len = fis.read(bytes))!=-1){
            //System.out.println(new String(bytes,0,len));
            System.out.println(new String(bytes,0,len));
        }

        //关流
        fis.close();
    }
}

IO流-(File)_第5张图片

5.字节流实现图片复制分析

IO流-(File)_第6张图片

6.字节流实现图片复制代码实现

public class Demo04_Copy {
    public static void main(String[] args)throws Exception {
        //1.创建FileInputStream用于读取文件
        FileInputStream fis = new FileInputStream("E:\\Idea\\io\\5.jpg");
        //2.创建FileOutputStream用于将读取到的文件写到指定位置
        FileOutputStream fos = new FileOutputStream("E:\\Idea\\io\\李成敏.jpg");

        //3.定义一个数组
        byte[] bytes = new byte[1024];
        //4.定义一个变量,接收读取的字节个数
        int len;
        while((len = fis.read(bytes))!=-1){
            //5.将读取到的字节写到指定位置
            fos.write(bytes,0,len);
        }

        //关流-> 先开后关
        fos.close();
        fis.close();
    }
}

第三章.字符流

1.字节流读取中文的问题

public class Demo01_FileReader {
    public static void main(String[] args)throws Exception {
        FileInputStream fis = new FileInputStream("day22\\io\\reader.txt");
        byte[] bytes = new byte[2];

        int len;
        while((len = fis.read(bytes))!=-1){
            System.out.println(new String(bytes,0,len));
        }
        fis.close();
    }
}

1.如果文件中存字母,一个字母占一个字节

2.如果文件中存中文,不用的编码表,一个汉字所在字节数不一样

​ GBK:一个中文占2个字节

​ UTF-8:一个中文占3个字节

3.注意:字节流确实是万能流,但是不要边读边看(输出到控制台)

​ 要是复制,只要字节读不丢,复制完就能正常显示

​ 字符流在操作文本文档时[编码一致的情况下],边读边看,没问题

2.FileReader的介绍以及使用

1.概述:字符输入流:Reader->抽象类
2.子类:FileReader->读字符
3.构造:
  FileReader(File file)
  FileReader(String path)
4.方法:
  int read() -> 一次读取一个字符 
  int read(char[] cbuf)  -> 一次读取一个字符数组
  int read(char[] cbuf, int offset, int length)-> 一次读取一个字符数组一部分
           cbuf:要读取的字符数组
           offset:从数组的哪个索引开始读
           length:读多少个
  void close():关流
public class Demo01_FileReader {
    /**
     * int read() -> 一次读取一个字符
     */
    public static void main(String[] args) throws Exception {
        FileReader fr = new FileReader("day22\\io\\reader.txt");
        /*int read01 = fr.read();
        System.out.println((char) read01);
        int read02 = fr.read();
        System.out.println((char) read02);
        int read03 = fr.read();
        System.out.println((char) read03);
        int read04 = fr.read();
        System.out.println(read04);*/

       int len;
       while((len = fr.read())!=-1){
           System.out.println((char) len);
       }

        fr.close();
    }
}

public class Demo02_FileReader {
    /**
     * int read(char[] cbuf)  -> 一次读取一个字符数组,返回的是读取的个数
     */
    public static void main(String[] args) throws Exception {
        FileReader fr = new FileReader("day22\\io\\reader.txt");
        char[] chars = new char[2];
        /*int read01 = fr.read(chars);
        //System.out.println(read01);
        System.out.println(new String(chars,0,read01));

        int read02 = fr.read(chars);
        //System.out.println(read02);
        System.out.println(new String(chars,0,read02));*/

        //定义变量,接收读取的个数
        int len;
        while((len = fr.read(chars))!=-1){
            System.out.println(new String(chars,0,len));
        }

        fr.close();
    }
}

3.FileWriter的介绍以及使用

1.概述:字符输出流:Writer->抽象类
2.子类:FileWriter
3.构造:
  FileWriter(File file) 
  FileWriter(String fileName) 
  FileWriter(String fileName, boolean append) -> 追加续写
  
4.方法:
  void write(int c) -> 一次写一个字符 
  void write(char[] cbuf)  -> 一次写一个字符数组
  void write(char[] cbuf, int off, int len)  -> 一次写一个字符数组一部分
  void write(String str)  -> 直接写字符串
  void write(String str, int off, int len)-> 一次写一个字符串一部分 
  void flush() -> 刷新缓冲区
  void close()  ->关流
      
5.注意:
  字符流:底层自带一个缓冲区
  我们要是写数据的话,写的数据会先放到缓冲区中,我们需要将数据从缓冲区中刷到硬盘上
public class Demo01_FileWriter {
    public static void main(String[] args)throws Exception {
        FileWriter fw = new FileWriter("day22\\io\\writer.txt");
        // void write(char[] cbuf)  -> 一次写一个字符数组
        char[] chars = {'你','好','柳','岩'};
        fw.write(chars);
        //刷新缓冲区
        //fw.flush();

        /*
          关流-> close方法自带刷新功能,先刷新,后关流
         */
        fw.close();
    }
}
public class Demo02_FileWriter {
    public static void main(String[] args)throws Exception {
        FileWriter fw = new FileWriter("day22\\io\\writer.txt",true);
        fw.write("夏商与西周");
        fw.write("\r\n");
        fw.write("东周分两段");
        fw.write("\r\n");
        fw.write("春秋和战国");
        fw.write("\r\n");
        fw.write("一统秦两汉");
        fw.write("\r\n");
        fw.write("三分魏蜀吴");
        fw.write("\r\n");
        fw.write("二晋前后延");
        fw.write("\r\n");
        fw.write("南北朝并立");
        fw.write("\r\n");
        fw.write("隋唐五代传");
        fw.write("\r\n");
        fw.write("宋元明清后");
        fw.write("\r\n");
        fw.write("王朝至此完");
        fw.write("\r\n");

        //关流
        fw.close();

    }
}

4.FileWriter的刷新功能和关闭功能

1.flush:刷新,刷新完之后,流对象还能使用
2.close:先刷新,后关流,close之后流对象不能使用了
public class Demo03_FileWriter {
    public static void main(String[] args)throws Exception {
        FileWriter fw = new FileWriter("day22\\io\\writer.txt");
        fw.write("夏商与西周");
        //刷新
        fw.flush();
        fw.write("东周分两段");
        fw.flush();

        //关流
        fw.write("涛哥和柳岩");
        fw.close();
        //fw.write("那一夜,你没有拒绝我");此处报错,因为流已经被关闭,不能再使用了
    }
}

5.IO异常处理的方式

public class Demo04_FileWriter {
    public static void main(String[] args) {
        FileWriter fw = null;
        try {
            fw = new FileWriter("day22\\io\\writer.txt");
            fw.write("静静和晓楠");
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            /*
              如果fw对象没有new出来,fw就是null
              如果fw是null,就不用我们自己close了
              只有fw对象new出来了,我们才要自己close
             */
            if (fw!=null){
                try {
                    fw.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

6.JDK7之后io异常处理方式->(扩展)

1.格式:
  try(IO流对象){
      可能出现异常的代码
  }catch(异常对象 对象名){
      
  }
2.注意:用以上格式处理IO异常,jvm会自动管理IO流对象
public class Demo05_FileWriter {
    public static void main(String[] args) {
        try(FileWriter fw = new FileWriter("day22\\io\\writer.txt");) {
            fw.write("静静和晓楠");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

第四章.字节缓冲流

1.缓冲流和普通流有什么区别:
  a.缓冲流底层有缓冲区,缓冲区默认大小为8192
  b.缓冲流在读写的时候,都会将数据先放到缓冲区中,所以缓冲区的读写动作,不是直接调用的native方法,而是在内存中进行读写,内存中的读写要比跟系统做交互的读写效率要高,而且缓冲流的读写方法都不是native的
  c.我们使用缓冲流可以尽量减少直接对系统进行读写操作,也减少了系统资源的占用
      

2.字节缓冲输出流:BufferedOutputStream
  a.构造:
    BufferedOutputStream(OutputStream out) 
                         OutputStream:抽象类,所以需要传递子类对象
                         如果想利用字节缓冲输出流做追加,可以利用FileOutputStream来实现
                             
  b.用法:FileOutputStream一毛一样

3.字节缓冲输入流:BufferedInputStream
  a.构造:
    BufferedInputStream(InputStream in) 
                        InputStream:抽象类,所以需要传递子类对象
                            
  b.用法:FileInputStream一毛一样
public class Demo01_Copy {
    public static void main(String[] args)throws Exception {
        //method01();
        method02();
    }

    private static void method02() throws Exception{
        long start = System.currentTimeMillis();



        //1.创建FileInputStream用于读取文件
        FileInputStream fis = new FileInputStream("E:\\Idea\\io\\集合.avi");

        BufferedInputStream bis = new BufferedInputStream(fis);

        //2.创建FileOutputStream用于将读取到的文件写到指定位置
        FileOutputStream fos = new FileOutputStream("E:\\Idea\\io\\新集合.avi");
        BufferedOutputStream bos = new BufferedOutputStream(fos);


        //3.定义一个数组
        byte[] bytes = new byte[1024];
        //4.定义一个变量,接收读取的字节个数
        int len;
        while((len = bis.read(bytes))!=-1){
            //5.将读取到的字节写到指定位置
            bos.write(bytes,0,len);
        }

        long end = System.currentTimeMillis();

        System.out.println(end-start);

        //关流-> 先开后关
        bos.close();
        bis.close();
    }

    private static void method01() throws IOException {
        long start = System.currentTimeMillis();


        //1.创建FileInputStream用于读取文件
        FileInputStream fis = new FileInputStream("E:\\Idea\\io\\集合.avi");
        //2.创建FileOutputStream用于将读取到的文件写到指定位置
        FileOutputStream fos = new FileOutputStream("E:\\Idea\\io\\新集合.avi");

        //3.定义一个数组
        byte[] bytes = new byte[1024];
        //4.定义一个变量,接收读取的字节个数
        int len;
        while((len = fis.read(bytes))!=-1){
            //5.将读取到的字节写到指定位置
            fos.write(bytes,0,len);
        }

        long end = System.currentTimeMillis();

        System.out.println(end-start);

        //关流-> 先开后关
        fos.close();
        fis.close();
    }
}

第五章.字符缓冲流

1.字符缓冲输出流_BufferedWriter

1.构造:
  BufferedWriter(Writer out) 
                 Writer:抽象类,需要传递子类
2.方法:FileWriter一毛一样
3.特有方法:
  newLine()->换行

public class Demo02_BufferedWriter {
    public static void main(String[] args)throws Exception {
        BufferedWriter bw =
                new BufferedWriter(new FileWriter("day22\\io\\buffered.txt",true));

        bw.write("离离原上草");
        bw.newLine();
        bw.write("一岁一枯荣");
        bw.newLine();
        bw.write("野火烧不尽");
        bw.newLine();
        bw.write("春风吹又生");
        bw.newLine();
        bw.close();
    }
}


2.字符缓冲输入流_BufferedReader

1.构造:
  BufferedReader(Reader r)
                 Reader:抽象类,需要传递子类对象
2.方法:FileReader一毛一样
3.特有方法:
  String readLine()-> 一次读一行

public class Demo03_BufferedReader {
    public static void main(String[] args)throws Exception {
        BufferedReader br = new BufferedReader(new FileReader("day22\\io\\buffered.txt"));
       /* String s1 = br.readLine();
        System.out.println(s1);

        String s2 = br.readLine();
        System.out.println(s2);

        String s3 = br.readLine();
        System.out.println(s3);

        String s4 = br.readLine();
        System.out.println(s4);

        String s5 = br.readLine();
        System.out.println(s5);//null*/

       //定义一个变量,接收读取的内容
        String line;
        while((line = br.readLine())!=null){
            System.out.println(line);
        }
        br.close();
    }
}


3.字符缓冲流练习

将in.txt中的内容排好序,写到另外一个新文件中

c.侍中、侍郎郭攸之、费祎、董允等,此皆良实,志虑忠纯,是以先帝简拔以遗陛下。愚以为宫中之事,事无大小,悉以咨之,然后施行,必得裨补阙漏,有所广益。
h.愿陛下托臣以讨贼兴复之效,不效,则治臣之罪,以告先帝之灵。若无兴德之言,则责攸之、祎、允等之慢,以彰其咎;陛下亦宜自谋,以咨诹善道,察纳雅言,深追先帝遗诏,臣不胜受恩感激。
d.将军向宠,性行淑均,晓畅军事,试用之于昔日,先帝称之曰能,是以众议举宠为督。愚以为营中之事,悉以咨之,必能使行阵和睦,优劣得所。
b.宫中府中,俱为一体,陟罚臧否,不宜异同。若有作奸犯科及为忠善者,宜付有司论其刑赏,以昭陛下平明之理,不宜偏私,使内外异法也。
a.先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。然侍卫之臣不懈于内,忠志之士忘身于外者,盖追先帝之殊遇,欲报之于陛下也。诚宜开张圣听,以光先帝遗德,恢弘志士之气,不宜妄自菲薄,引喻失义,以塞忠谏之路也。
i.今当远离,临表涕零,不知所言。
f.臣本布衣,躬耕于南阳,苟全性命于乱世,不求闻达于诸侯。先帝不以臣卑鄙,猥自枉屈,三顾臣于草庐之中,咨臣以当世之事,由是感激,遂许先帝以驱驰。后值倾覆,受任于败军之际,奉命于危难之间,尔来二十有一年矣。
g.先帝知臣谨慎,故临崩寄臣以大事也。受命以来,夙夜忧叹,恐付托不效,以伤先帝之明,故五月渡泸,深入不毛。今南方已定,兵甲已足,当奖率三军,北定中原,庶竭驽钝,攘除奸凶,兴复汉室,还于旧都。此臣所以报先帝而忠陛下之职分也。至于斟酌损益,进尽忠言,则攸之、祎、允之任也。
e.亲贤臣,远小人,此先汉所以兴隆也;亲小人,远贤臣,此后汉所以倾颓也。先帝在时,每与臣论此事,未尝不叹息痛恨于桓、灵也。侍中、尚书、长史、参军,此悉贞良死节之臣,愿陛下亲之信之,则汉室之隆,可计日而待也。

实现步骤:
  1.创建BufferedReader,用于读取in.txt的内容
  2.创建ArrayList集合,用于存储读取出来的内容
  3.调用Collections.sort,进行排序
  4.创建BufferedWriter,用于将集合中排好序的内容写到out.txt中
  5.遍历ArrayList集合,边遍历,边写
  6.关流

public class Demo04_Test {
    public static void main(String[] args)throws Exception {
        //1.创建BufferedReader,用于读取in.txt的内容
        BufferedReader br = new BufferedReader(new FileReader("day22\\io\\in.txt"));
        //2.创建ArrayList集合,用于存储读取出来的内容
        ArrayList<String> list = new ArrayList<>();
        String line;
        while((line = br.readLine())!=null){
            list.add(line);
        }
        //3.调用Collections.sort,进行排序
        Collections.sort(list);
        //4.创建BufferedWriter,用于将集合中排好序的内容写到out.txt中
        BufferedWriter bw = new BufferedWriter(new FileWriter("day22\\io\\out.txt"));
        //5.遍历ArrayList集合,边遍历,边写
        for (String s : list) {
            bw.write(s);
            bw.newLine();
        }
        //6.关流

        bw.close();
        br.close();
    }
}


第六章.转换流

1.字符编码

计算机中储存的信息都是用二进制数表示的,而我们在屏幕上看到的数字、英文、标点符号、汉字等字符是二进制数转换之后的结果。[按照某种规则,将字符存储到计算机中,称为编码] 。反之,将存储在计算机中的二进制数按照某种规则解析显示出来,称为解码 。比如说,按照A规则存储,同样按照A规则解析,那么就能显示正确的文本f符号。反之,按照A规则存储,再按照B规则解析,就会导致乱码现象。

  • 字符编码Character Encoding : 就是一套自然语言的字符与二进制数之间的对应规则。

2.字符集

  • 字符集 Charset:也叫编码表。是一个系统支持的所有字符的集合,包括各国家文字、标点符号、图形符号、数字等。

计算机要准确的存储和识别各种字符集符号,需要进行字符编码,一套字符集必然至少有一套字符编码。常见字符集有ASCII字符集、GBK字符集、Unicode字符集等。

IO流-(File)_第7张图片

可见,当指定了编码,它所对应的字符集自然就指定了,所以编码才是我们最终要关心的。

  • ASCII字符集
    • ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统,用于显示现代英语,主要包括控制字符(回车键、退格、换行键等)和可显示字符(英文大小写字符、阿拉伯数字和西文符号)。
    • 基本的ASCII字符集,使用7位(bits)表示一个字符,共128字符。ASCII的扩展字符集使用8位(bits)表示一个字符,共256字符,方便支持欧洲常用字符。
  • ISO-8859-1字符集
    • 拉丁码表,别名Latin-1,用于显示欧洲使用的语言,包括荷兰、丹麦、德语、意大利语、西班牙语等。
    • ISO-8859-1使用单字节编码,兼容ASCII编码。
  • GBxxx字符集
    • GB就是国标的意思,是为了显示中文而设计的一套字符集。
    • GB2312:简体中文码表。一个小于127的字符的意义与原来相同。但两个大于127的字符连在一起时,就表示一个汉字,这样大约可以组合了包含7000多个简体汉字,此外数学符号、罗马希腊的字母、日文的假名们都编进去了,连在ASCII里本来就有的数字、标点、字母都统统重新编了两个字节长的编码,这就是常说的"全角"字符,而原来在127号以下的那些就叫"半角"字符了。
    • GBK:最常用的中文码表。是在GB2312标准基础上的扩展规范,使用了双字节编码方案,共收录了21003个汉字,完全兼容GB2312标准,同时支持繁体汉字以及日韩汉字等。
    • GB18030:最新的中文码表。收录汉字70244个,采用多字节编码,每个字可以由1个、2个或4个字节组成。支持中国国内少数民族的文字,同时支持繁体汉字以及日韩汉字等。
  • Unicode字符集
    • Unicode编码系统为表达任意语言的任意字符而设计,是业界的一种标准,也称为统一码、标准万国码。
    • 它最多使用4个字节的数字来表达每个字母、符号,或者文字。有三种编码方案,UTF-8、UTF-16和UTF-32。最为常用的UTF-8编码。
    • UTF-8编码,可以用来表示Unicode标准中任何字符,它是电子邮件、网页及其他存储或传送文字的应用中,优先采用的编码。互联网工程工作小组(IETF)要求所有互联网协议都必须支持UTF-8编码。所以,我们开发Web应用,也要使用UTF-8编码。它使用一至四个字节为每个字符编码,编码规则:
      1. 128个US-ASCII字符,只需一个字节编码。
      2. 拉丁文等字符,需要二个字节编码。
      3. 大部分常用字(含中文),使用三个字节编码。
      4. 其他极少使用的Unicode辅助字符,使用四字节编码。
1.如果想要不出现乱码问题,编码和解码遵循的编码规则要一样
2.在GBK中,一个中文占2个字节
3.在UTF-8,一个中文占3个字节

3.转换流_InputStreamReader

1.作用:在读取的时候,可以指定按照什么编码去读
2.构造:
  InputStreamReader(InputStream in, String charsetName) 
                    in:抽象类,传递子类
                    charsetName:指定的编码表,不区分大小写的
3.使用:FileReader一样

public class Demo01_InputStreamReader {
    public static void main(String[] args) throws Exception{
        InputStreamReader isr = new InputStreamReader(new FileInputStream("E:\\Idea\\io\\a.txt"),"gbk");
        int read = isr.read();
        System.out.println((char)read);
        isr.close();
    }
}

4.转换流_OutputStreamWriter

1.作用:按照指定的编码规则去写数据,指定什么规则,就按照什么规则去保存数据
2.构造:
  OutputStreamWriter(OutputStream out, String charsetName) 
                    out:抽象类,传递子类
                    charsetName:指定的编码表,不区分大小写的
3.使用:FileWriter一样

public class Demo02_OutputStreamWriter {
    public static void main(String[] args)throws Exception {
        OutputStreamWriter osr = new OutputStreamWriter(new FileOutputStream("E:\\Idea\\io\\b.txt"),"GBK");
        osr.write("你");
        osr.close();
    }
}


第七章.打印流(了解)

1.PrintStream打印流基本使用

1.概述:
  PrintStream:打印流
2.方法:
  println():原样输出,输出之后自动换行
  print():原样输出,输出之后不会换行
3.构造:
  PrintStream(String fileName) 
              fileName:文件路径

public class Test02 {
    public static void main(String[] args)throws Exception {
        PrintStream ps = new PrintStream("day22\\io\\print.txt");
        ps.println("柳岩");
        ps.println("涛哥");
        ps.close();
    }
}

使用场景:
  可以用于将运行结果,过程打印到日志文件中

2.改变输出语句流向

System中的setOut方法
setOut(PrintStream ps)

所谓的改变流向:System.out.println()输出不在控制台上,转到指定的文件中

public class Test03 {
    public static void main(String[] args)throws Exception {
        PrintStream ps = new PrintStream("day22\\io\\print.txt");
        System.out.println("select * from category");

        System.setOut(ps);

        System.out.println("select * from category");
        ps.close();
    }
}

回顾

IO流-(File)_第8张图片

day23.IO流_网编

今日重点:
  1.会使用序列化流读写对象
  2.会使用Properties集合中的load方法解析properties配置文件
  3.会手动导jar包,使用Commons-io
  4.会使用Lombok完成一个标准的javabean
  5.知道客户端和服务端之间的交互过程

第一章.序列化流

1.序列化流和反序列化流介绍

1.作用:读写对象
2.写对象(序列化流):ObjectOutputStream
3.读对象(反序列化流):ObjectInputStream    

IO流-(File)_第9张图片

2.序列化流_ObjectOutputStream

1.序列化流:ObjectOutputStream -> 写对象
2.构造:
  ObjectOutputStream(OutputStream out) 
                     OutputStream:抽象类,需要传递子类
3.方法:
  void writeObject(Object obj)  -> 写对象
4.注意:
  想将一个对象序列化到文件中,此对象需要实现Serializable接口
public class Person implements Serializable {
    private String name;
    private Integer age;

    public Person() {
    }

    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

public class Demo01_Serializable {
    public static void main(String[] args) throws Exception{
        //创建序列化流对象
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("day23/io/person.txt"));
        oos.writeObject(new Person("柳岩",36));
        oos.close();

    }
}

3.反序列化_ObjectInputStream

1.反序列化:ObjectInputStream -> 读对象
2.构造:
  ObjectInputStream(InputStream in) 
                    InputStream:抽象类,所以需要传递子类对象
3.方法:
  Object readObject() -> 读对象
 public class Demo02_Serializable {
    public static void main(String[] args) throws Exception{
        //创建反序列化流对象
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("day23/io/person.txt"));
        Object o = ois.readObject();
        //向下转型
        Person p = (Person)o;
        System.out.println(p);

        ois.close();
    }
}

4.不想被序列化操作(了解)

1.将成员变成静态的
2.瞬态关键字:transient

比如:
  private transient Integer age

5.反序列化时出现的问题以及分析以及解决

1.问题描述:
  如果对象的源码改动了,但是没有重新序列化,直接反序列化,就会爆出序列号冲突异常:InvalidClassException
解决:
 方式1:源码改动,重新序列化一下子
 方式2:直接将序列号定死:
      在要被序列化的类中加上:private static final long serialVersionUID = 42L;

IO流-(File)_第10张图片

6.扩展(经验值)

1.问题描述:
  如果序列化多个对象,当反序列化时不知道反序列化多少次才能全部将对象读出来时,容易出现:EOFException(文件意外到达结尾异常)
      
2.解决:
  将多个对象放到一个集合中,然后将集合对象放到文件中
  然后反序列化这一个集合,然后再遍历集合,获取集合中的对象
public class Demo01_Serializable {
    public static void main(String[] args) throws Exception{
        //创建序列化流对象
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("day23/io/person.txt"));
        //oos.writeObject(new Person("柳岩",36));
        //oos.writeObject(new Person("涛哥",18));
        //oos.writeObject(new Person("晓楠",16));

        //创建ArrayList集合
        ArrayList<Person> list = new ArrayList<>();
        list.add(new Person("柳岩",36));
        list.add(new Person("涛哥",18));
        list.add(new Person("晓楠",16));

        oos.writeObject(list);

        oos.close();
    }
}
public class Demo02_Serializable {
    public static void main(String[] args) throws Exception{
        //创建反序列化流对象
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("day23/io/person.txt"));

        //读取集合
        ArrayList<Person> list = (ArrayList<Person>) ois.readObject();

        for (Person person : list) {
            System.out.println(person);
        }

        ois.close();
    }
}

第二章.Properties集合结合IO使用(扩展)

1.Properties结合IO流使用方法

1.Properties中的load方法:
  void load(InputStream inStream) -> 将流中的数据加载到Properties集合中
2.使用场景:
  读取properties配置文件的
3.注意:
  将来我们写代码要追求高内聚,低耦合
  耦合度:类和类之间的联系紧密程度
4.解决:
  我们可以将硬数据放到文件中,然后我们用代码动态解析文件中的数据,获取文件中的数据
  这样做,到时候修改硬数据直接去文件中改,源码不用动,有效地减低了耦合度
1.创建一个properties配置文件
    
2.怎么创建这个properties配置文件?
  右键->new->file->取名xxx.properties->ok
    
3.properties文件中的内容怎么写:
  a.内容数据都是key=value形式
  b.key和value都是String,但是不能加""
  c.不能有空格
  d.一个键值对写完之后,要换行,才能写下一个键值对
  e.尽量不要写中文

IO流-(File)_第11张图片

username=root
password=1234
public class Test02_Properties {
    public static void main(String[] args)throws Exception {
        /*

          void load(InputStream inStream) -> 将流中的数据加载到Properties集合中

         */

        //1.创建Properties集合
        Properties properties = new Properties();
        //2.创建字节输入流
        FileInputStream in = new FileInputStream("day23\\io\\pro.properties");

        //3.将流中的数据加载到Properties集合中
        properties.load(in);

        //4.遍历
        System.out.println(properties.getProperty("username"));
        System.out.println(properties.getProperty("password"));
    }
}

第三章.Commons-io工具包(扩展)

1.介绍

IO技术开发中,代码量很大,而且代码的重复率较高。如果我们要遍历目录,拷贝目录就需要使用方法的递归调用,也增大了程序的复杂度。
Apache软件基金会,开发了IO技术的工具类`commonsIO`,大大简化IO开发。

2.添加第三方jar包

Apahce软件基金会属于第三方,(Oracle公司第一方,我们自己第二方,其他都是第三方)我们要使用第三方开发好的工具,需要添加jar包。

1.jar包的介绍:
  jar包就是一个压缩包,只不过后缀名叫xxx.jar,压缩包中都是第三方开发好的工具类,都是以class文件存在
 
2.jar包怎么导:
  a.在当前模块下创建文件夹,取名为lib
  b.将要使用的jar粘贴到lib下
  c.将jar包中的class文件解压到当前模块环境下(只有解压出来,才能使用jar包中的工具类)
    对着lib包或者jar包->右键->add as library->level(选择module)->name会变空,不要管->点ok

3.工具包的使用

IOUtils- 静态方法:IOUtils.copy(InputStream in,OutputStream out)传递字节流,实现文件复制。
- 静态方法:IOUtils.closeQuietly(任意流对象)悄悄的释放资源,自动处理close()方法抛出的异常。
public class Test01_IOUtils {
    public static void main(String[] args) throws FileNotFoundException {
        /*
          - 静态方法:IOUtils.copy(InputStream in,OutputStream out)传递字节流,实现文件复制。
          - 静态方法:IOUtils.closeQuietly(任意流对象)悄悄的释放资源,自动处理close()方法抛出的异常。
         */

        //IOUtils.copy(new FileInputStream("E:\\Idea\\io\\1.jpg"),new FileOutputStream("E:\\Idea\\io\\柳岩.jpg"));

        System.out.println("============================");

        FileWriter fw = null;
        try {
            fw = new FileWriter("day23\\io\\writer.txt");
            fw.write("静静和晓楠");
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            /*
              如果fw对象没有new出来,fw就是null
              如果fw是null,就不用我们自己close了
              只有fw对象new出来了,我们才要自己close
             */
            if (fw!=null){
               IOUtils.closeQuietly(fw);
            }
        }
    }
}

FileUtils- 静态方法:FileUtils.copyDirectoryToDirectory(File src,File dest);
           传递File类型的目录,进行整个目录的复制,自动进行递归遍历。
           
           参数:
             src:要复制的文件夹路径
             dest:要将文件夹粘贴到哪里去
             
- 静态方法:writeStringToFile(File file,String str)写字符串到文本文件中。
- 静态方法:String readFileToString(File file)读取文本文件,返回字符串。
public class Test02_FileUtils {
    public static void main(String[] args)throws Exception {
        /*
         - 静态方法:FileUtils.copyDirectoryToDirectory(File src,File dest);
                    传递File类型的目录,进行整个目录的复制,自动进行递归遍历。

                    参数:
                    src:要复制的文件夹路径
                    dest:要将文件夹粘贴到哪里去
         */

        //FileUtils.copyDirectoryToDirectory(new File("E:\\Idea\\io\\aa"),new File("E:\\Idea\\io\\haha"));

        //- 静态方法:writeStringToFile(File file,String str)写字符串到文本文件中。

        //FileUtils.writeStringToFile(new File("day23\\io\\commons.txt"),"涛哥和柳岩那个啥的故事");

        //- 静态方法:String readFileToString(File file)读取文本文件,返回字符串。

        String s = FileUtils.readFileToString(new File("day23\\io\\commons.txt"));
        System.out.println(s);
    }
}

第四章.Lombok使用(扩展)

1.lombok介绍

Lombok通过增加一些“处理程序”,可以让java变得简洁、快速。

Lombok能以注解形式来简化java代码,提高开发效率。开发中经常需要写的javabean,都需要花时间去添加相应的getter/setter,也许还要去写构造器、equals等方法,而且需要维护。

Lombok能通过注解的方式,在编译时自动为属性生成构造器、getter/setter、equals、hashcode、toString方法。出现的神奇就是在源码中没有getter和setter方法,但是在编译生成的字节码文件中有getter和setter方法。这样就省去了手动重建这些代码的麻烦,使代码看起来更简洁些。

5.2 lombok使用

  • 添加lombok的jar包:lombok-1.18.8.jar。

  • 为IDEA添加lombok插件(连接网络使用)

  • 安装完毕后,重启IDEA。

2.lombok常用注解

@Getter和@Setter

  • 作用:生成成员变量的get和set方法。
  • 写在成员变量上,指对当前成员变量有效。
  • 写在类上,对所有成员变量有效。
  • 注意:静态成员变量无效。

IO流-(File)_第12张图片

@ToString

  • 作用:生成toString()方法。
  • 注解只能写在类上。

IO流-(File)_第13张图片

@NoArgsConstructor和@AllArgsConstructor

  • @NoArgsConstructor:无参数构造方法。
  • @AllArgsConstructor:满参数构造方法。
  • 注解只能写在类上。

IO流-(File)_第14张图片

@EqualsAndHashCode

  • 作用:生成hashCode()和equals()方法。
  • 注解只能写在类上。

IO流-(File)_第15张图片

@Data

  • 作用:生成get/set,toString,hashCode,equals,无参构造方法
  • 注解只能写在类上。

IO流-(File)_第16张图片

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Person {
    private String name;
    private int age;
}

public class Test01 {
    public static void main(String[] args) {
        Person person = new Person();
        person.setName("涛哥");
        person.setAge(16);

        System.out.println(person.getName()+"..."+person.getAge());

        System.out.println("=========================");

        Person person1 = new Person("三上",26);
        System.out.println(person1.getName()+"..."+person1.getAge());
    }
}

第五章.网络编程

1.软件结构

  • C/S结构 :全称为Client/Server结构,是指客户端和服务器结构。常见程序有QQ、红蜘蛛、飞秋等软件。

IO流-(File)_第17张图片

B/S结构 :全称为Browser/Server结构,是指浏览器和服务器结构。常见浏览器有IE、谷歌、火狐等。

IO流-(File)_第18张图片

两种架构各有优势,但是无论哪种架构,都离不开网络的支持。网络编程,就是在一定的协议下,实现两台计算机的通信的程序。

2.服务器概念

是安装了服务器软件的计算机

网络通信协议:两台计算机在做数据交互时要遵守的规则,协议会对数据的格式,速率等进行规定,只有都遵守了这个协议,才能完成数据交互

两台计算机想完成数据交互,需要遵守网络通信协议

IO流-(File)_第19张图片

3.通信三要素

[IP地址]:计算机的唯一标识,用于两台计算机之间的连接

      a.概述:指互联网协议地址(Internet Protocol Address),俗称IP
            计算机的唯一标识
      b.作用:可用于计算机和计算机之间的连接
      c.IPV4
        32位的二进制数,通常被分为4个字节,表示成a.b.c.d 的形式,例如192.168.65.100 。其中a、b、c、d都是0~255之间的十进制整数,那么最多可以表示42亿个。
        IPV6
        为了扩大地址空间,拟通过IPv6重新定义地址空间,采用128位地址长度,每16个字节一组,分成8组十六进制数,表示成ABCD:EF01:2345:6789:ABCD:EF01:2345:6789->号称能给地球上的每一粒沙子分配一个IP地址
        
      d.查看ip的命令:ipconfig
        测试是否能连接其他计算机的命令:ping ip地址
        
      e:特殊的网址:代表的是本机地址,到了哪里都不会变,代表自己
        127.0.0.1
        localhost
        
        localhost:端口号/项目名/资源
        

[协议]
     TCP:面向连接协议
         需要先确认连接,才能进行数据交互
         三次握手:
            - 第一次握手,客户端向服务器端发出连接请求,等待服务器确认。
            - 第二次握手,服务器端向客户端回送一个响应,通知客户端,服务端收到了连接请求。
            - 第三次握手,客户端再次向服务器端发送确认信息,确认连接。
            
         好处:数据安全,能给数据的传输提供一个安全的传输环境
         坏处:效率低
     
     UDP:面向无连接协议
         好处:效率高
         坏处:传输的数据不安全,容易丢失数据包

[端口号]
   每一个应用程序的唯一标识
  
  用两个字节表示的整数,它的取值范围是0~65535。其中,0~1023之间的端口号用于一些知名的网络服务和应用,普通的应用程序需要使用1024以上的端口号。如果端口号被另外一个服务或应用所占用,会导致当前程序启动失败。

TCP协议中的三次握手和四次挥手

三次握手:
- 第一次握手,客户端向服务器端发出连接请求,等待服务器确认。
- 第二次握手,服务器端向客户端回送一个响应,通知客户端收到了连接请求。
- 第三次握手,客户端再次向服务器端发送确认信息,确认连接。
四次挥手:
- 第一次挥手:客户端向服务器端提出结束连接,让服务器做最后的准备工作。此时,客户端处于半关闭状态,即表示不再向服务器发送数据了,但是还可以接受数据。
- 第二次挥手:服务器接收到客户端释放连接的请求后,会将最后的数据发给客户端。并告知上层的应用进程不再接收数据。
- 第三次挥手:服务器发送完数据后,会给客户端发送一个释放连接的报文。那么客户端接收后就知道可以正式释放连接了。
- 第四次挥手:客户端接收到服务器最后的释放连接报文后,要回复一个彻底断开的报文。这样服务器收到后才会彻底释放连接。这里客户端,发送完最后的报文后,会等待2MSL,因为有可能服务器没有收到最后的报文,那么服务器迟迟没收到,就会再次给客户端发送释放连接的报文,此时客户端在等待时间范围内接收到,会重新发送最后的报文,并重新计时。如果等待2MSL后,没有收到,那么彻底断开。

IO流-(File)_第20张图片

4.实现简单客户端和服务端的交互

IO流-(File)_第21张图片

IO流-(File)_第22张图片

4.1.编写客户端

步骤:
  1.创建Socket对象,指明要连接的服务端的ip和端口号
  2.调用Socket对象中的getOutputStream,获取OutputStream,用于往服务端发请求(写数据)
  3.调用Socket对象中的getInputStream,获取InputStream,用于读取服务端发送过来的数据(读数据)
  4.关流
public class Client {
    public static void main(String[] args)throws Exception {
        //1.创建Socket对象,指明要连接的服务端的ip和端口号
        Socket socket = new Socket("127.0.0.1", 6666);
        //2.调用Socket对象中的getOutputStream,获取OutputStream,用于往服务端发请求(写数据)
        OutputStream os = socket.getOutputStream();
        os.write("我想现在一个片儿".getBytes());
        //3.调用Socket对象中的getInputStream,获取InputStream,用于读取服务端发送过来的数据(读数据)
        InputStream in = socket.getInputStream();
        byte[] bytes = new byte[1024];
        int len = in.read(bytes);
        System.out.println(new String(bytes,0,len));
        //4.关流
        in.close();
        os.close();
        socket.close();
    }
}

4.2.编写服务端

步骤:
  1.创建ServerSocket对象,设置端口号
  2.调用ServerSocket中的accept方法,等待和获取客户端连接,返回Socket
  3.调用Socket中的getInputStream,用于读取客户端发过来的请求
  4.调用Socket中的getOutputStream,用于往客户端写响应信息
  5.关流
public class Server {
    public static void main(String[] args)throws Exception {
        //1.创建ServerSocket对象,设置端口号
        ServerSocket ss = new ServerSocket(6666);
        //2.调用ServerSocket中的accept方法,等待和获取客户端连接,返回Socket
        Socket socket = ss.accept();
        //3.调用Socket中的getInputStream,用于读取客户端发过来的请求
        InputStream in = socket.getInputStream();
        byte[] bytes = new byte[1024];
        int len = in.read(bytes);
        System.out.println(new String(bytes,0,len));
        //4.调用Socket中的getOutputStream,用于往客户端写响应信息
        OutputStream os = socket.getOutputStream();
        os.write("我给你一个片儿,金瓶梅拿走".getBytes());
        //5.关流
        os.close();
        in.close();
        socket.close();
        ss.close();
    }
}

5.文件上传

IO流-(File)_第23张图片

5.1.文件上传客户端以及服务端实现

public class Client {
    public static void main(String[] args)throws Exception {
        //1.创建Socket对象
        Socket socket = new Socket("127.0.0.1", 6666);
        //2.创建FileInputStream,读取本地上的图片
        FileInputStream fis = new FileInputStream("E:\\Idea\\io\\24.jpg");
        //3.调用socket中的getOutputStream,将读取过来的图片写到服务器端
        OutputStream os = socket.getOutputStream();
        //4.边读边写
        byte[] bytes = new byte[1024];
        int len;
        while((len = fis.read(bytes))!=-1){
            os.write(bytes,0,len);
        }

        //给服务端写一个结束标记,不让服务端等着了
        socket.shutdownOutput();

        System.out.println("=============以下代码是读取响应===========");

        //5.调用socket中的getInputStream,用于读取服务端发过来的响应
        InputStream in = socket.getInputStream();
        byte[] bytes1 = new byte[1024];
        int read = in.read(bytes1);
        System.out.println(new String(bytes1,0,read));

        //6.关流
        in.close();
        os.close();
        fis.close();
        socket.close();
    }
}

public class Server {
    public static void main(String[] args)throws Exception {
        //1.创建ServerSocket对象
        ServerSocket ss = new ServerSocket(6666);
        //2.调用accept方法,监听,获取连接的客户端对象
        Socket socket = ss.accept();
        //3.调用getInputStream.读取客户端发过来的文件
        InputStream in = socket.getInputStream();
        //4.创建FileOutputStream,用于将读取过来的图片写到服务端本地


        String name = System.currentTimeMillis()+""+new Random().nextInt()+".jpg";
        FileOutputStream fos = new FileOutputStream("E:\\Idea\\io\\upload\\"+name);
        //5.边读边写
        byte[] bytes = new byte[1024];
        int len;
        while((len = in.read(bytes))!=-1){
            fos.write(bytes,0,len);
        }

        System.out.println("=========以下代码是往客户端响应数据========");

        //6.响应数据
        OutputStream os = socket.getOutputStream();
        os.write("上传成功".getBytes());

        //7.关流
        os.close();
        fos.close();
        in.close();
        socket.close();
        ss.close();

    }
}


IO流-(File)_第24张图片

5.2.文件上传服务端实现(多线程)

public class Server {
    public static void main(String[] args) throws Exception {
        //1.创建ServerSocket对象
        ServerSocket ss = new ServerSocket(6666);


        while (true) {
            //2.调用accept方法,监听,获取连接的客户端对象
            Socket socket = ss.accept();
            new Thread(new Runnable() {
                @Override
                public void run() {
                    InputStream in = null;
                    FileOutputStream fos = null;
                    OutputStream os = null;
                    try {
                        //3.调用getInputStream.读取客户端发过来的文件
                        in = socket.getInputStream();
                        //4.创建FileOutputStream,用于将读取过来的图片写到服务端本地
                        String name = System.currentTimeMillis() + "" + new Random().nextInt() + ".jpg";
                        fos = new FileOutputStream("E:\\Idea\\io\\upload\\" + name);
                        //5.边读边写
                        byte[] bytes = new byte[1024];
                        int len;
                        while ((len = in.read(bytes)) != -1) {
                            fos.write(bytes, 0, len);
                        }

                        System.out.println("=========以下代码是往客户端响应数据========");

                        //6.响应数据
                        os = socket.getOutputStream();
                        os.write("上传成功".getBytes());
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        //7.关流
                        CloseUtils.closeQuietly(os,fos,in,socket);
                    }
                }
            }).start();
        }

    }
}

异常回顾:

父类中的方法没有抛异常,子类重写之后不能抛

父类中的方法抛异常了,子类重写之后可抛可不抛

5.3.关流工具类

public class CloseUtils {
    public static void closeQuietly(OutputStream os, FileOutputStream fos, InputStream in, Socket socket){
        if (os != null) {
            try {
                os.close();
            } catch (IOException e) {
                e.printStackTrace();
            }

        }

        if (fos != null) {
            try {
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        if (in != null) {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        if (socket != null) {
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}


第六章.标准javabean

1.javabean的介绍

1.所谓的标准javabean其实就是指的是自己定义的实体类
2.一个标准的javabean包含:
  私有属性
  无参构造
  有参构造
  get/set方法   

1.在开发中,我们是分包分层的,其实分层就是依靠创建不同的package,不同的类要放到不同的包下,好维护
2.在开发中如何分包分层:
  com.atguigu.web -> 专门放和前端打交道的类
  com.atguigu.service-> 专门放和业务打交道的类
  com.atguigu.dao-> 专门放和数据库打交道的类
  com.atguigu.javabean-> 专门放实体类
  com.atguigu.utils-> 专门放工具类

2.javabean在开发中有啥用

javabean如何产生:一个javabean的出现,需要根据数据库中的表来确定

IO流-(File)_第25张图片

第七章.Lambda表达式

1.函数式编程思想和Lambda表达式定义格式

1.面向对象思想:强调的是对象,调用对象中的方法帮我们去做事儿,侧重点在找对象
2.函数式编程思想:对面向对象思想进一步简化,不注重过程,只注重结果
 
3.Lambda表达式格式:
  ()->{}
  
  ():代表的是重写方法的参数列表
  ->:将参数传递到方法体中
  {}:代表的是重写方法的方法体

public class Test01_Lambda {
    public static void main(String[] args) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("我到达朝鲜了");
            }
        }).start();

        System.out.println("====================");

        new Thread(()-> {
                System.out.println("我到达朝鲜了");
        }).start();

        System.out.println("====================");

        new Thread(()-> System.out.println("我到达朝鲜了")).start();
    }
}


2.Lambda表达式使用前提

1.必须有重写方法
2.必须有函数式接口做方法参数传递
  函数式接口:接口中必须有且只有一个抽象方法的接口
  检测函数式接口:在接口上面,加上@FunctionalInterface

3.新手怎么写Lambda表达式

1.观察是否是函数式接口做方法参数传递
2.如果是,可以考虑搞成Lambda表达式
3.先写一个匿名内部类
4.new接口开始到重写方法的方法名结束,选中,删除,别忘记删除右半个大括号
5.在重写方法的参数后面,加上->
6.再看看根据省略规则,能不能进一步删除

4.Lambda表达式的省略规则

1.重写方法的参数类型可以省略
2.如果重写方法的参数只有一个,所在的小括号可以干掉
3.如果方法体中只有一句代码,所在的大括号可以干掉,分号干掉
4.如果方法体中只有一句代码,而且还是带return,那么return,方法体大括号,分号都直接干掉

public class Test02_Lambda {
    public static void main(String[] args) {

        /*
          Thread(Runnable r)
          
         */
        
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("哈哈哈");
            }
        }).start();

        System.out.println("========Lambda表达式=========");
        
        new Thread(() -> {
            System.out.println("哈哈哈哈");
        }).start();

        System.out.println("==========最终写法=============");

        new Thread(() -> System.out.println("哈哈哈哈")).start();

    }
}


/*@Data
@AllArgsConstructor
@NoArgsConstructor*/
public class Person {
    private String name;
    private int age;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}


public class Test03_Lambda {
    public static void main(String[] args) {
        ArrayList<Person> list = new ArrayList<>();
        list.add(new Person("柳岩",36));
        list.add(new Person("涛哥",18));
        list.add(new Person("晓楠",16));

        Collections.sort(list, new Comparator<Person>() {
            @Override
            public int compare(Person o1, Person o2) {
                return o1.getAge()-o2.getAge();
            }
        });

        System.out.println("============Lambda表达式=============");

        Collections.sort(list, (Person o1, Person o2)-> {
                return o1.getAge()-o2.getAge();
        });

        System.out.println("============Lambda表达式最终写法=============");

        Collections.sort(list, (o1,o2)-> o1.getAge()-o2.getAge());

        System.out.println(list);

    }
}

5.Lambda表达式练习

@FunctionalInterface
public interface USB {
    public void open(String s);
}


public class Test01 {
    public static void main(String[] args) {
       method(new USB() {
           @Override
           public void open(String s) {
               System.out.println(s+"开启了");
           }
       });

        System.out.println("==========Lambda表达式=========");
        method((String s)-> {
                System.out.println(s+"开启了");
        });

        System.out.println("==========Lambda表达式=========");

        method(s-> System.out.println(s+"开启了"));
    }

    public static void method(USB usb){
        usb.open("鼠标");
    }
}


你可能感兴趣的:(#,JavaSE-Code,java)