JavaSE笔记--韩顺平(入门详细版)(四)

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
.cn 域名,1个 12个月
简介: JavaSE笔记--韩顺平(入门详细版)(四)

16.3.2.2  BufferedReader


例:

public class BufferedReader_ {
    public static void main(String[] args) throws Exception {
        String filePath = "e:\\a.java";
        //创建bufferedReader
        BufferedReader bufferedReader = new BufferedReader(new FileReader(filePath));
        //读取
        String line; //按行读取, 效率高
        //说明
        //1. bufferedReader.readLine() 是按行读取文件
        //2. 当返回null 时,表示文件读取完毕
        while ((line = bufferedReader.readLine()) != null) {
            System.out.println(line);
        }
        //关闭流, 这里注意,只需要关闭 BufferedReader ,因为底层会自动的去关闭 节点流
        //FileReader。
        /*
            public void close() throws IOException {
                synchronized (lock) {
                    if (in == null)
                        return;
                    try {
                        in.close();//in 就是我们传入的 new FileReader(filePath), 关闭了.
                    } finally {
                        in = null;
                        cb = null;
                    }
                }
            }
         */
        bufferedReader.close();
    }
}



16.3.2.3  InputStreamReader



基本介绍:

  • InputStreamReader:Reader的子类,可以将lnputStream(字节流)包装成Reader(字符流)
  • 当处理纯文本数据时,如果使用宇符流效率重高,井且可以有效解決中文问题,所以建议字节流转换成字符流

例:

public class InputStreamReader_ {
    public static void main(String[] args) throws IOException {
        String filePath = "e:\\a.txt";
        //解读
        //1. 把 FileInputStream 转成 InputStreamReader
        //2. 指定编码 gbk
        //InputStreamReader isr = new InputStreamReader(new FileInputStream(filePath), "gbk");
        //3. 把 InputStreamReader 传入 BufferedReader
        //BufferedReader br = new BufferedReader(isr);
        //将2 和 3 合在一起
        BufferedReader br = new BufferedReader(new InputStreamReader(
                                                    new FileInputStream(filePath), "gbk"));
        //4. 读取
        String s = br.readLine();
        System.out.println("读取内容=" + s);
        //5. 关闭外层流
        br.close();
    }
}



16.4 输出流⭐️



  • 网络异常,图片无法展示
    |

基本介绍:


16.4.1  OutputStream


16.4.1.1  FileOutputStream



  • 网络异常,图片无法展示
    |

常用方法:


使用方法:

public class FileOutputStream01 {
    public static void main(String[] args) {
    }
    /**
     * 演示使用FileOutputStream 将数据写到文件中,
     * 如果该文件不存在,则创建该文件
     */
    @Test
    public void writeFile() {
        //创建 FileOutputStream对象
        String filePath = "e:\\a.txt";
        FileOutputStream fileOutputStream = null;
        try {
            //得到 FileOutputStream对象
            //说明
            //1. new FileOutputStream(filePath) 创建方式,当写入内容是,会覆盖原来的内容
            //2. new FileOutputStream(filePath, true) 创建方式,当写入内容是,是追加到文件后面
            fileOutputStream = new FileOutputStream(filePath, true);
            //写入一个字节
            //fileOutputStream.write('H');//
            //写入字符串
            String str = "hsp,world!";
            //str.getBytes() 可以把 字符串-> 字节数组
            //fileOutputStream.write(str.getBytes());
            /*
            write(byte[] b, int off, int len) 将 len字节从位于偏移量 off的指定字节数组写入此文件输出流
             */
            fileOutputStream.write(str.getBytes(), 0, 3);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                fileOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}



16.4.1.2  BufferedOutputStream



基本介绍:


BufferedOutputstream是字节流,实现缓冲的输出流,可以将多个字节写入底层输出流中,而不必对每次字节写入调用底层
系统



  • 网络异常,图片无法展示
    |

常用方法:


例:

public class BufferedCopy02 {
    public static void main(String[] args) {
//        String srcFilePath = "e:\\Koala.jpg";
//        String destFilePath = "e:\\hsp.jpg";
//        String srcFilePath = "e:\\0245_韩顺平零基础学Java_引出this.avi";
//        String destFilePath = "e:\\hsp.avi";
        String srcFilePath = "e:\\a.java";
        String destFilePath = "e:\\a3.java";
        //创建BufferedOutputStream对象BufferedInputStream对象
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try {
            //因为 FileInputStream  是 InputStream 子类
            bis = new BufferedInputStream(new FileInputStream(srcFilePath));
            bos = new BufferedOutputStream(new FileOutputStream(destFilePath));
            //循环的读取文件,并写入到 destFilePath
            byte[] buff = new byte[1024];
            int readLen = 0;
            //当返回 -1 时,就表示文件读取完毕
            while ((readLen = bis.read(buff)) != -1) {
                bos.write(buff, 0, readLen);
            }
            System.out.println("文件拷贝完毕~~~");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //关闭流 , 关闭外层的处理流即可,底层会去关闭节点流
            try {
                if(bis != null) {
                    bis.close();
                }
                if(bos != null) {
                    bos.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}


16.4.1.3  ObjectOutputStream



基本介绍:

  • Objectoutputstream 提供序列化功能
  • 序列化就是在保存数据时,保存数据的值和数据类型
  • 列化就是在恢复数据时,恢复数据的值和数据类型
  • 需要让某个对象支持序列化机制,则必须让其类是可序列化的,为了让某个类是可序列化的,该类必须实现如下两个接口之一:Serializable和Externalizable

例:

public class ObjectOutStream_ {
    public static void main(String[] args) throws Exception {
        //序列化后,保存的文件格式,不是存文本,而是按照他的格式来保存
        String filePath = "e:\\data.dat";
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(filePath));
        //序列化数据到 e:\data.dat
        oos.writeInt(100);// int -> Integer (实现了 Serializable)
        oos.writeBoolean(true);// boolean -> Boolean (实现了 Serializable)
        oos.writeChar('a');// char -> Character (实现了 Serializable)
        oos.writeDouble(9.5);// double -> Double (实现了 Serializable)
        oos.writeUTF("韩顺平教育");//String
        //保存一个dog对象
        oos.writeObject(new Dog("旺财", 10, "日本", "白色"));
        oos.close();
        System.out.println("数据保存完毕(序列化形式)");
    }
}



注意事项和细节:

  1. 读写顺序要一致
  2. 要求实现序列化或反序列化对象,需要实现 Serializable
  3. 序列化的类中建议添加SerialVersionUID,为了提高版本兼容性
  4. 序列化对象时,默认将里面所有属性都进行序列化,但除了static或transient修饰的成员
  5. 序列化对象时,要求里面属性的类型也需要实现序列化接口
  6. 序列化具备可继承性,也就是如果某类已经实现了序列化,则它的所有子类也己经默认实现了序列化


16.4.1.4  PrintStream



例:

public class PrintStream_ {
    public static void main(String[] args) throws IOException {
        PrintStream out = System.out;
        //在默认情况下,PrintStream 输出数据的位置是 标准输出,即显示器
        /*
             public void print(String s) {
                if (s == null) {
                    s = "null";
                }
                write(s);
            }
         */
        out.print("john, hello");
        //因为print底层使用的是write , 所以我们可以直接调用write进行打印/输出
        out.write("韩顺平,你好".getBytes());
        out.close();
        //我们可以去修改打印流输出的位置/设备
        //1. 输出修改成到 "e:\\f1.txt"
        //2. "hello, 韩顺平教育~" 就会输出到 e:\f1.txt
        //3. public static void setOut(PrintStream out) {
        //        checkIO();
        //        setOut0(out); // native 方法,修改了out
        //   }
        System.setOut(new PrintStream("e:\\f1.txt"));
        System.out.println("hello, 韩顺平教育~");
    }
}



16.4.2  Writer


16.4.2.1  FileWriter



常用方法:

  • new File Writer (File/String):覆盖模式,相当于流的指针在首端
  • new FileWriter (File/String.true):追加模式,相当于流的指针在尾端
  • write(int):写入单个字符
  • write(char[]):写入指定数组
  • write(char[],off len):写入指定数组的指定部分
  • write (string):写入整个字符律
  • write(string,off,len):写入字符串的指定部分

方法使用:

public class FileWriter_ {
    public static void main(String[] args) {
        String filePath = "e:\\note.txt";
        //创建FileWriter对象
        FileWriter fileWriter = null;
        char[] chars = {'a', 'b', 'c'};
        try {
            fileWriter = new FileWriter(filePath);//默认是覆盖写入
//            3) write(int):写入单个字符
            fileWriter.write('H');
//            4) write(char[]):写入指定数组
            fileWriter.write(chars);
//            5) write(char[],off,len):写入指定数组的指定部分
            fileWriter.write("韩顺平教育".toCharArray(), 0, 3);
//            6) write(string):写入整个字符串
            fileWriter.write(" 你好北京~");
            fileWriter.write("风雨之后,定见彩虹");
//            7) write(string,off,len):写入字符串的指定部分
            fileWriter.write("上海天津", 0, 2);
            //在数据量大的情况下,可以使用循环操作.
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //对应FileWriter , 一定要关闭流,或者flush才能真正的把数据写入到文件
            //老韩看源码就知道原因.
            /*
                看看代码
                private void writeBytes() throws IOException {
        this.bb.flip();
        int var1 = this.bb.limit();
        int var2 = this.bb.position();
        assert var2 <= var1;
        int var3 = var2 <= var1 ? var1 - var2 : 0;
        if (var3 > 0) {
            if (this.ch != null) {
                assert this.ch.write(this.bb) == var3 : var3;
            } else {
                this.out.write(this.bb.array(), this.bb.arrayOffset() + var2, var3);
            }
        }
        this.bb.clear();
    }
             */
            try {
                //fileWriter.flush();
                //关闭文件流,等价 flush() + 关闭
                fileWriter.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        System.out.println("程序结束...");
    }
}

文件拷贝:

public class FileCopy {
    public static void main(String[] args) {
        //完成 文件拷贝,将 e:\\Koala.jpg 拷贝 c:\\
        //思路分析
        //1. 创建文件的输入流 , 将文件读入到程序
        //2. 创建文件的输出流, 将读取到的文件数据,写入到指定的文件.
        String srcFilePath = "e:\\Koala.jpg";
        String destFilePath = "e:\\Koala3.jpg";
        FileInputStream fileInputStream = null;
        FileOutputStream fileOutputStream = null;
        try {
            fileInputStream = new FileInputStream(srcFilePath);
            fileOutputStream = new FileOutputStream(destFilePath);
            //定义一个字节数组,提高读取效果
            byte[] buf = new byte[1024];
            int readLen = 0;
            while ((readLen = fileInputStream.read(buf)) != -1) {
                //读取到后,就写入到文件 通过 fileOutputStream
                //即,是一边读,一边写
                fileOutputStream.write(buf, 0, readLen);//一定要使用这个方法
            }
            System.out.println("拷贝ok~");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                //关闭输入流和输出流,释放资源
                if (fileInputStream != null) {
                    fileInputStream.close();
                }
                if (fileOutputStream != null) {
                    fileOutputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}



注意事项:

  • FileWriter使用后,必须要关闭(close)或刷新(flush),否则写入不到指定的文件


16.4.2.2  BufferedWriter



例:

public class BufferedWriter_ {
    public static void main(String[] args) throws IOException {
        String filePath = "e:\\ok.txt";
        //创建BufferedWriter
        //说明:
        //1. new FileWriter(filePath, true) 表示以追加的方式写入
        //2. new FileWriter(filePath) , 表示以覆盖的方式写入
        BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter(filePath));
        bufferedWriter.write("hello, 韩顺平教育!");
        bufferedWriter.newLine();//插入一个和系统相关的换行
        bufferedWriter.write("hello2, 韩顺平教育!");
        bufferedWriter.newLine();
        bufferedWriter.write("hello3, 韩顺平教育!");
        bufferedWriter.newLine();
        //说明:关闭外层流即可 , 传入的 new FileWriter(filePath) ,会在底层关闭
        bufferedWriter.close();
    }
}

文件拷贝:

public class BufferedCopy_ {
    public static void main(String[] args) {
        //1. BufferedReader 和 BufferedWriter 是安装字符操作
        //2. 不要去操作 二进制文件[声音,视频,doc, pdf ], 可能造成文件损坏
        //BufferedInputStream
        //BufferedOutputStream
        String srcFilePath = "e:\\a.java";
        String destFilePath = "e:\\a2.java";
//        String srcFilePath = "e:\\0245_韩顺平零基础学Java_引出this.avi";
//        String destFilePath = "e:\\a2韩顺平.avi";
        BufferedReader br = null;
        BufferedWriter bw = null;
        String line;
        try {
            br = new BufferedReader(new FileReader(srcFilePath));
            bw = new BufferedWriter(new FileWriter(destFilePath));
            //说明: readLine 读取一行内容,但是没有换行
            while ((line = br.readLine()) != null) {
                //每读取一行,就写入
                bw.write(line);
                //插入一个换行
                bw.newLine();
            }
            System.out.println("拷贝完毕...");
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            //关闭流
            try {
                if(br != null) {
                    br.close();
                }
                if(bw != null) {
                    bw.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}



16.4.2.3  OutputStreamWriter



基本介绍:

  • OutputStreamWriter:Writer的子类,实现将Outputstream(字节流)包装成Writer(字符流)
  • 当处理纯文本数据时,如果使用宇符流效率重高,井且可以有效解決中文问题,所以建议格字节流转快成字符流
  • 可以在使用时指定编码格式

例:

public class OutputStreamWriter_ {
    public static void main(String[] args) throws IOException {
        String filePath = "e:\\hsp.txt";
        String charSet = "utf-8";
        OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(filePath), charSet);
        BufferedWriter bw = new BufferedWriter(osw);
        bw.write("hi, 韩顺平教育");
        bw.close();
        System.out.println("按照 " + charSet + " 保存文件成功~");
    }
}
16.4.2.4  PrintWrite
例:
public class PrintWriter_ {
    public static void main(String[] args) throws IOException {
        //PrintWriter printWriter = new PrintWriter(System.out);
        PrintWriter printWriter = new PrintWriter(new FileWriter("e:\\f2.txt"));
        printWriter.print("hi, 北京你好~~~~");
        printWriter.close();//flush + 关闭流, 才会将数据写入到文件..
    }
}



16.5 Properties



基本介绍:

  • 专门用于读号配置文件的集合类配置文件的格式:键=值
  • 键值对不需要有空格,值不需要用引号一起来
  • 默认类型是String


常用方法:

  • load:加载配置文件的键值对到Properties对象
  • list:将数据显示到指定设备
  • getProperty (key):根据键获取值
  • setProperty(key value):设置键值对到Properties对象
  • store:将Properties中的键值对存储到配置文件,在idea 中,保存信息到配置文件,如果含有中文,会存储为unicode码

读取:

public class Properties02 {
    public static void main(String[] args) throws IOException {
        //使用Properties 类来读取mysql.properties 文件
        //1. 创建Properties 对象
        Properties properties = new Properties();
        //2. 加载指定配置文件
        properties.load(new FileReader("src\\mysql.properties"));
        //3. 把k-v显示控制台
        properties.list(System.out);
        //4. 根据key 获取对应的值
        String user = properties.getProperty("user");
        String pwd = properties.getProperty("pwd");
        System.out.println("用户名=" + user);
        System.out.println("密码是=" + pwd);
    }
}



配置:

public class Properties03 {
    public static void main(String[] args) throws IOException {
        //使用Properties 类来创建 配置文件, 修改配置文件内容
        Properties properties = new Properties();
        //创建
        //1.如果该文件没有key 就是创建
        //2.如果该文件有key ,就是修改
        /*
            Properties 父类是 Hashtable , 底层就是Hashtable 核心方法
            public synchronized V put(K key, V value) {
                // Make sure the value is not null
                if (value == null) {
                    throw new NullPointerException();
                }
                // Makes sure the key is not already in the hashtable.
                Entry<?,?> tab[] = table;
                int hash = key.hashCode();
                int index = (hash & 0x7FFFFFFF) % tab.length;
                @SuppressWarnings("unchecked")
                Entry<K,V> entry = (Entry<K,V>)tab[index];
                for(; entry != null ; entry = entry.next) {
                    if ((entry.hash == hash) && entry.key.equals(key)) {
                        V old = entry.value;
                        entry.value = value;//如果key 存在,就替换
                        return old;
                    }
                }
                addEntry(hash, key, value, index);//如果是新k, 就addEntry
                return null;
            }
         */
        properties.setProperty("charset", "utf8");
        properties.setProperty("user", "汤姆");//注意保存时,是中文的 unicode码值
        properties.setProperty("pwd", "888888");
        //将k-v 存储文件中即可
        properties.store(new FileOutputStream("src\\mysql2.properties"), null);
        System.out.println("保存配置文件成功~");
    }
}



17 网络编程


17.1 网络基础



ip地址:

  • 用于唯一标识网络中的每台计算机/主机
  • 查看ip地址:ipconfig
  • ip地址的表示形式:点分十进制 xx.xx.xx.xx
  • 每一个十进制数的范围:0~255
  • ip地址的组成=网络地址+主机地址,比如:192.168.16.69
  • ilPv6是互联网工程任务组设计的用于替代1PV4的下一代IP协议

  • 网络异常,图片无法展示
    |

    网络异常,图片无法展示
    |

ipv4地址分类:


域名:

  • 将ip地址映射成域名

端口号:

  • 用于标识计算机上某个特定的网络程序
  • 表示形式:以整数形式,范围0~65535
  • 0~1024己经被占用,比如ssh 22,ftp 21, smtp 25 http 80
  • 常见的网络程序端口号:
    tomcat :8080
    mysql:3306
    oracle:1521
    sqlserver:1433

网络通信协议:

  • TCP/IP (Transmission Control Protocol/Internet Protocol的简写,中文译名为传输控制协议/因特网互联协议,又叫网络通讯协议,这个协议是internet最基本的协议,internet国际互联网络的基础就是由网络层的IP协议和传输层的TCP协议组成的
    网络异常,图片无法展示
    |

    网络异常,图片无法展示
    |

TCP:

  • 使用TCP协议前,须先建立TCP连接,形成传输数据通道
  • 传输前,采用”三次握手"方式,是可靠的
  • TCP协议进行通信的两个应用进程:客户端、服务端
  • 在连接中可进行大数据量的传输
  • 传输完毕,需释放已建立的连接,效率低

UDP:

  • 格数据源、目的封装成数据包,不需要建立连接
  • 每个数据报的大小限制在64K内
  • 因无需连接,故是不可靠的
  • 发送数据结束时无需释放资源(因为不是面向连接的),速度快


17.2  InetAddress



常用方法:

  • 获取本机InetAddress对象 getLocalHost
  • 根据指定主机名/域名获取ip地址对象 getByName
  • 获取InetAddress对象的主机名 getHostName
  • 获取InetAddress对象的地址 getHostAddress
public class API_ {
    public static void main(String[] args) throws UnknownHostException {
        //1. 获取本机的InetAddress 对象
        InetAddress localHost = InetAddress.getLocalHost();
        System.out.println(localHost);//DESKTOP-S4MP84S/192.168.12.1
        //2. 根据指定主机名 获取 InetAddress对象
        InetAddress host1 = InetAddress.getByName("DESKTOP-S4MP84S");
        System.out.println("host1=" + host1);//DESKTOP-S4MP84S/192.168.12.1
        //3. 根据域名返回 InetAddress对象, 比如 www.baidu.com 对应
        InetAddress host2 = InetAddress.getByName("www.baidu.com");
        System.out.println("host2=" + host2);//www.baidu.com / 110.242.68.4
        //4. 通过 InetAddress 对象,获取对应的地址
        String hostAddress = host2.getHostAddress();//IP 110.242.68.4
        System.out.println("host2 对应的ip = " + hostAddress);//110.242.68.4
        //5. 通过 InetAddress 对象,获取对应的主机名/或者的域名
        String hostName = host2.getHostName();
        System.out.println("host2对应的主机名/域名=" + hostName); // www.baidu.com
    }
}



17.3  Socket



基本介绍:

  • 通信的两端都要有Socket,是两台机器间通信的端点
  • Socket允许程序把网络连接当成一个流,数据在两个Socket间通过IO传输
  • 一般主动发起通信的应用程序属客户端,等待通信请求的为服务端

TCP网络通信编程:

  • 基于客户端——服务端的网络通信
  • 底层使用TCP/IP协议
  • 基于Socket的TCP编程
    网络异常,图片无法展示
    |


17.4  TCP编程⭐️



服务端:

public class SocketTCP03Server {
    public static void main(String[] args) throws IOException {
        //思路
        //1. 在本机 的9999端口监听, 等待连接
        //   细节: 要求在本机没有其它服务在监听9999
        //   细节:这个 ServerSocket 可以通过 accept() 返回多个Socket[多个客户端连接服务器的并发]
        ServerSocket serverSocket = new ServerSocket(9999);
        System.out.println("服务端,在9999端口监听,等待连接..");
        //2. 当没有客户端连接9999端口时,程序会 阻塞, 等待连接
        //   如果有客户端连接,则会返回Socket对象,程序继续
        Socket socket = serverSocket.accept();
        System.out.println("服务端 socket =" + socket.getClass());
        //3. 通过socket.getInputStream() 读取客户端写入到数据通道的数据, 显示
        InputStream inputStream = socket.getInputStream();
        //4. IO读取, 使用字符流, 老师使用 InputStreamReader 将 inputStream 转成字符流
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        String s = bufferedReader.readLine();
        System.out.println(s);//输出
        //5. 获取socket相关联的输出流
        OutputStream outputStream = socket.getOutputStream();
        //   使用字符输出流的方式回复信息
        BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
        bufferedWriter.write("hello client 字符流");
        bufferedWriter.newLine();// 插入一个换行符,表示回复内容的结束
        bufferedWriter.flush();//注意需要手动的flush
        //6.关闭流和socket
        bufferedWriter.close();
        bufferedReader.close();
        socket.close();
        serverSocket.close();//关闭
    }
}
客户端:
public class SocketTCP03Client {
    public static void main(String[] args) throws IOException {
        //思路
        //1. 连接服务端 (ip , 端口)
        //解读: 连接本机的 9999端口, 如果连接成功,返回Socket对象
        Socket socket = new Socket(InetAddress.getLocalHost(), 9999);
        System.out.println("客户端 socket返回=" + socket.getClass());
        //2. 连接上后,生成Socket, 通过socket.getOutputStream()
        //   得到 和 socket对象关联的输出流对象
        OutputStream outputStream = socket.getOutputStream();
        //3. 通过输出流,写入数据到 数据通道, 使用字符流
        BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream));
        bufferedWriter.write("hello, server 字符流");
        bufferedWriter.newLine();//插入一个换行符,表示写入的内容结束, 注意,要求对方使用readLine()!!!!
        bufferedWriter.flush();// 如果使用的字符流,需要手动刷新,否则数据不会写入数据通道
        //4. 获取和socket关联的输入流. 读取数据(字符),并显示
        InputStream inputStream = socket.getInputStream();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
        String s = bufferedReader.readLine();
        System.out.println(s);
        //5. 关闭流对象和socket, 必须关闭
        bufferedReader.close();//关闭外层流
        bufferedWriter.close();
        socket.close();
        System.out.println("客户端退出.....");
    }
}

图片拷贝

public class TCPFileUploadServer {
    public static void main(String[] args) throws Exception {
        //1. 服务端在本机监听8888端口
        ServerSocket serverSocket = new ServerSocket(8888);
        System.out.println("服务端在8888端口监听....");
        //2. 等待连接
        Socket socket = serverSocket.accept();
        //3. 读取客户端发送的数据
        //   通过Socket得到输入流
        BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
        byte[] bytes = StreamUtils.streamToByteArray(bis);
        //4. 将得到 bytes 数组,写入到指定的路径,就得到一个文件了
        String destFilePath = "src\\abc.mp4";
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(destFilePath));
        bos.write(bytes);
        bos.close();
        // 向客户端回复 "收到图片"
        // 通过socket 获取到输出流(字符)
        BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        writer.write("收到图片");
        writer.flush();//把内容刷新到数据通道
        socket.shutdownOutput();//设置写入结束标记
        //关闭其他资源
        writer.close();
        bis.close();
        socket.close();
        serverSocket.close();
    }
}

音乐拷贝:

public class Homework03Server {
    public static void main(String[] args) throws Exception {
        //1 监听 9999端口
        ServerSocket serverSocket = new ServerSocket(9999);
        //2.等待客户端连接
        System.out.println("服务端,在9999端口监听,等待下载文件");
        Socket socket = serverSocket.accept();
        //3.读取 客户端发送要下载的文件名
        //  这里老师使用了while读取文件名,时考虑将来客户端发送的数据较大的情况
        InputStream inputStream = socket.getInputStream();
        byte[] b = new byte[1024];
        int len = 0;
        String downLoadFileName = "";
        while ((len = inputStream.read(b)) != -1) {
            downLoadFileName += new String(b, 0 , len);
        }
        System.out.println("客户端希望下载文件名=" + downLoadFileName);
        //老师在服务器上有两个文件, 无名.mp3 高山流水.mp3
        //如果客户下载的是 高山流水 我们就返回该文件,否则一律返回 无名.mp3
        String resFileName = "";
        if("高山流水".equals(downLoadFileName)) {
            resFileName = "src\\高山流水.mp3";
        } else {
            resFileName = "src\\无名.mp3";
        }
        //4. 创建一个输入流,读取文件
        BufferedInputStream bis =
                new BufferedInputStream(new FileInputStream(resFileName));
        //5. 使用工具类StreamUtils ,读取文件到一个字节数组
        byte[] bytes = StreamUtils.streamToByteArray(bis);
        //6. 得到Socket关联的输出流
        BufferedOutputStream bos =
                new BufferedOutputStream(socket.getOutputStream());
        //7. 写入到数据通道,返回给客户端
        bos.write(bytes);
        socket.shutdownOutput();//很关键.
        //8 关闭相关的资源
        bis.close();
        inputStream.close();
        socket.close();
        serverSocket.close();
        System.out.println("服务端退出...");
    }
}



netstat指令:

  • netstat-an 可以查看当前主机网络情况,包括端口监听情况和网络连接情况
  • netstat -an l more 可以分页显示
  • 要求在dos控制台下执行


17.5  UDP编程



基本介绍:

  • 类 DatagramSocket 和 DatagramPacket 实现了基于 UDP 协议网络程序
  • UDP数据报通过数据报套接字 DatagramSocket 发送和接收,系统不保证UDP数据报一定能够安全送到目的地,也不能确定什么时候可以抵达
  • DatagramPacket 对象封装了UDP数据报,在数据报中包含了发送端的IP地址和端口号以及接收端的IP地址和端口号
  • UDP协议中每个数据报都给出了完整的地址信息,因此无须建立发送方和接收方的连接

基本流程:

  1. 核心的两个类/对象 Datagramsocket与DatagramPacket
  2. 建立发送端,接收端
  3. 建立数据包
  4. 调用DatagramSocket的发送、接收方法
  5. 关网DatagramSocket

注意事项和细节:

  1. 没有明确的服务端和客户端,演变成数据的发送端和接收端
  2. 接收数据和发送数据是通过 DatagramSocket 对象完成
  3. 将数据封装到DatagramPacket 对象/ 装包
  4. 当接收到 DatagramPacket 对象,需要进行拆包,取出数据
  5. DatagramSocket 可以指定在哪个端口接收数据

例:

public class UDPReceiverA {
    public static void main(String[] args) throws IOException {
        //1. 创建一个 DatagramSocket 对象,准备在9999接收数据
        DatagramSocket socket = new DatagramSocket(9999);
        //2. 构建一个 DatagramPacket 对象,准备接收数据
        //   在前面讲解UDP 协议时,老师说过一个数据包最大 64k
        byte[] buf = new byte[1024];
        DatagramPacket packet = new DatagramPacket(buf, buf.length);
        //3. 调用 接收方法, 将通过网络传输的 DatagramPacket 对象
        //   填充到 packet对象
        //老师提示: 当有数据包发送到 本机的9999端口时,就会接收到数据
        //   如果没有数据包发送到 本机的9999端口, 就会阻塞等待.
        System.out.println("接收端A 等待接收数据..");
        socket.receive(packet);
        //4. 可以把packet 进行拆包,取出数据,并显示.
        int length = packet.getLength();//实际接收到的数据字节长度
        byte[] data = packet.getData();//接收到数据
        String s = new String(data, 0, length);
        System.out.println(s);
        //===回复信息给B端
        //将需要发送的数据,封装到 DatagramPacket对象
        data = "好的, 明天见".getBytes();
        //说明: 封装的 DatagramPacket对象 data 内容字节数组 , data.length , 主机(IP) , 端口
        packet =
                new DatagramPacket(data, data.length, InetAddress.getByName("192.168.12.1"), 9998);
        socket.send(packet);//发送
        //5. 关闭资源
        socket.close();
        System.out.println("A端退出...");
    }
}


目录
相关文章
|
存储 Java
【JavaSE】基础笔记 - 图书管理系统(保姆教程,含源码)
【JavaSE】基础笔记 - 图书管理系统(保姆教程,含源码)
311 1
|
6月前
|
IDE Java 测试技术
黑马全套Java教程(十)(一)
黑马全套Java教程(十)
30 0
|
8月前
|
Java 编译器
JavaSE基础精选-1基础语法
JavaSE基础精选-1基础语法
46 0
|
安全 Java 编译器
JavaSE笔记--韩顺平(入门详细版)(五)
JavaSE笔记--韩顺平(入门详细版)(五)
151 4
|
存储 设计模式 算法
JavaSE笔记--韩顺平(入门详细版)(一)
JavaSE笔记--韩顺平(入门详细版)(一)
535 3
|
存储 设计模式 安全
JavaSE笔记--韩顺平(入门详细版)(三)
JavaSE笔记--韩顺平(入门详细版)(三)
206 0
|
存储 XML 安全
JavaSE笔记--韩顺平(入门详细版)(二)
JavaSE笔记--韩顺平(入门详细版)(二)
280 0
|
存储 Oracle IDE
javase基础教程(1)| 青训营笔记
javase基础教程(1)| 青训营笔记
82 0
javase基础教程(1)| 青训营笔记
|
Java API
黑马全套Java教程(六)(下)
黑马全套Java教程(六)
64 0
黑马全套Java教程(六)(下)
|
存储 Java 容器
黑马全套Java教程(三)(下)
黑马全套Java教程(三)
72 0
黑马全套Java教程(三)(下)

热门文章

最新文章