Day27

今天专注学习大于五个小时,加油OVO

Day27

 

对象流

  • 自定义类需要满足以下的需求,方可序列化

  • 1.实现Serializable的接口。---->标识接口,这个接口没有任何方法。

  • 2.需要当前类,提供一个全局常量:serialVersionUID

  • 3.除了当前Person类需要实现serializable接口之外,还必须保证其内部属性也必须是可序列化的。

    (默认情况下,基本数据类型是可序列的)

serialVersionUID没有显性声明的话,系统会自动分配,但是分配后,修改了类之后,就找不到了。

所以!!!!必须声明serialVersionUID。

 

补充:ObjectInputStream和ObjectOutputStream不能序列化static和transient修饰的成员变量

代码

package com.sorrymaker.IO;

import org.junit.Test;

import java.io.*;

/**
* ObjectInputStream和ObjectOutputStream都是字节流
* 用于存储和读取基本数据类型或对象的数据流。可以把java中的对象写到数据源中,也可以还原回来。
*
* 要想一个java对象是可序列化的,需要满足相应的要求,见Person.java
*/
public class ObjectInputOutputStreamTest {
   /**
    * 序列化过程:将内存中的java对象保存到磁盘中或通过网络传输出去。
    * 使用ObjectOutputStream实现
    */
   @Test
   public void  testObjectOutputStream(){
       ObjectOutputStream oos = null;
       try {
           oos = new ObjectOutputStream(new FileOutputStream("src/com/sorrymaker/IO/object.dat"));

           oos.writeObject(new String("我是个帅哥"));
           oos.flush();//刷新操作

           oos.writeObject(new Person("啥比一个",22));
           oos.flush();

      } catch (IOException e) {
           e.printStackTrace();
      } finally {
           if(oos!=null){
               try {
                   oos.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }
          }
      }
  }
   /**
       反序列化:将磁盘文件中的对象还原为内存中的java对象。
       使用ObjectInputStream
   */
   @Test
   public void  testObjectInputStream(){
       ObjectInputStream ois = null;
       try {
           ois = new ObjectInputStream(new FileInputStream("src/com/sorrymaker/IO/object.dat"));

           Object obj = ois.readObject();
           String str =(String) obj;

           Person p =(Person)ois.readObject();

           System.out.println(str);
           System.out.println(p);
      } catch (IOException e) {
           e.printStackTrace();
      } catch (ClassNotFoundException e) {
           e.printStackTrace();
      } finally {
           if(ois!=null){
               try {
                   ois.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }
          }
      }
  }
}

 

随机存取文件流

RandomAccessFile流、

  1. 既可以是输入流也可以是输出流

  2. 继承于java.io.Object。

  3. 实现了DataInput、DataOutput、Closeable、AutoCloseable接口。

 

 

long getFilePointer():获取文件记录指针的当前位置。

void seek(long pos):将文件记录指针定位到pos位置。

 

使用RandomAccessFile实现数据的插入效果。

/**
* 使用RandomAccessFile实现数据的插入效果。
*/
@Test
public void test3() throws IOException {
   RandomAccessFile raf1 =new RandomAccessFile(new File("src/com/sorrymaker/IO/hello1.txt"),"rw");
   //把指针调到角标为3的位置,
   raf1.seek(3);
   //保存指针3后面的所有数据到StringBuilder中
   StringBuilder builder =new StringBuilder((int) new File("src/com/sorrymaker/IO/hello1.txt").length());
   byte[] buffer =new byte[20];
   int len;
   while ((len = raf1.read(buffer)) != -1) {
       builder.append(new String(buffer,0,len));
  }
   //调回指针,写入“xyz”
   raf1.seek(3);
   raf1.write("xyz".getBytes());

   //将StringBuider中的数据写入到文件中
   raf1.write(builder.toString().getBytes());

   raf1.close();
}

 

网络编程

两个要素:

  1. IP和端口号

  2. 网络通信协议: TCP/IP参考模型。

IP

package com.sorrymaker.Internet;

import java.net.InetAddress;
import java.net.UnknownHostException;

/**
* 两个要素:
* 1.IP地址和端口号
* 2.网络通信协议: TCP/IP参考模型。
*
* 1.IP地址:InetAdress
* 2.IP:唯一的标识Internet上的计算机(通信实体)
* 3.IP分类:IPv4 和 IPv6 ; 万维网 和 局域网
* 4.域名: www.baidu.com
* 5.本地回路地址:127.0.0.1 对应的是:localhost
* 6.实例化InetAddress:两个方法:getByName(String host)、getLocalHost()
*         两个常用方法:getHostName()---->获取域名
*                   getHostAddress()---->获取域名解析后的地址。
*
*/
public class InetAddressTest {

   public static void main(String[] args){
       try {
           InetAddress inet1 = InetAddress.getByName("10.12.168.155");

           System.out.println(inet1);
           //解析了域名所对应的IP地址。
           InetAddress inet2 = InetAddress.getByName("www.baidu.com");

           System.out.println(inet2);

           InetAddress inet3 = InetAddress.getByName("127.0.0.1");

           System.out.println(inet3);

           //获取本机IP。
           InetAddress inet4 = InetAddress.getLocalHost();
           System.out.println(inet4);
           //getHostName()---->获取域名
           System.out.println(inet2.getHostName());

           //getHostAddress()---->
           System.out.println(inet2.getHostAddress());

      } catch (UnknownHostException e) {
           e.printStackTrace();
      }
  }
}

端口号

端口号标识正在计算机上运行的进程(程序)

要求:不同的进程有不同的端口号

端口被规定为一个16位的整数0~65535

端口分类:

公认端口:0~1023。被预先定义的服务通信占用。

注册端口:1024~49151。分配给用户进程或应用程序。

动态/私有端口:49152~65535。

IP 与端口号的组合得出一个网络套接字:Socket

 

TCP网络编程

例题1.

客户端发送内容给服务端,服务端将内容打印到控制台上

package com.sorrymaker.Internet;

import org.junit.Test;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

/**
* 实现TCP的网络编程
* 例子1:客户端发送信息给服务端,服务端将数据显示在控制台上
*         先启动服务器,再启动客户端。
*         先启动服务器,再启动客户端。
* 客户端总体步骤:
*         1.创建Socket对象,指明服务器端的ip和端口号。
*         2.获取一个输出流,用于输出数据。
*         3.写出数据的操作。
*         4.资源的关闭(socket也要关闭)
* 服务器端总体步骤:
*         1.创建服务器端的ServerSocket,指明字节的端口号。
*         2.调用accept()表示接收来只自于客户端的socket
*         3.获取输入流
*         4.读取输入流的数据
*
*/
public class TCPTest {
   //客户端
   @Test
   public void client() {
       //这里的IP指明为对象的(服务器端的)
       Socket socket = null;
       OutputStream os = null;
       try {
           //1.创建Socket对象,指明服务器端的ip和端口号。
           InetAddress inet = InetAddress.getByName("127.0.0.1");
           socket = new Socket(inet, 8899);
           // 2.获取一个输出流,用于输出数据。
           os = socket.getOutputStream();
           //3.写出数据的操作。
           os.write("我是客户端".getBytes());
      } catch (IOException e) {
           e.printStackTrace();
      } finally {
           //资源关闭,流要关闭,socket也要关闭。
           //4.资源的关闭(socket也要关闭)
           if (os != null) {
               try {
                   os.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }
          }
           if (socket != null) {
               try {
                   socket.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }
          }
      }
  }

   //服务端
   @Test
   public void server() {
       ServerSocket ss = null;
       Socket socket = null;
       InputStream is = null;
       ByteArrayOutputStream baos = null;
       try {
           //1.创建服务器端的ServerSocket,指明字节的端口号。
           ss = new ServerSocket(8899);
           //2.调用accept()表示接收来只自于客户端的socket
           socket = ss.accept();
           //3.获取输入流
           is = socket.getInputStream();

           //不建议这样子写,会乱码
//       byte[] buffer =new byte[1024];
//
//       int len;
//       while ((len = is.read(buffer)) != -1) {
//           String str = new String(buffer, 0, len);
//           System.out.println(str);
//       }

           //4.读取输入流的数据
           baos = new ByteArrayOutputStream();
           byte[] buffer = new byte[5];
           int len;
           while ((len = is.read(buffer)) != -1) {
               baos.write(buffer, 0, len);
          }
           //把所有字节读入后,再toString(),就不会出现乱码的问题了。
           System.out.println(baos.toString());

           System.out.println("收到了来自于:"+socket.getInetAddress().getHostAddress());
      } catch (IOException e) {
           e.printStackTrace();
      } finally {
           if(baos!=null){
               try {
                   baos.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }
          }
           if(is!=null){
               try {
                   is.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }
          }
           if(socket!=null){
               try {
                   socket.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }
          }
           if(ss!=null){
               try {
                   ss.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }
          }
      }
  }
}

例题2.

客户端发送文件给服务端,服务端将文件保存在本地。

package com.sorrymaker.Internet;

import org.junit.Test;

import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

/**
* 例题2.客户端发送文件给服务端,服务端将文件保存在本地。
*/
public class TCPTest2 {
   @Test
   public void client() {
       Socket socket = null;
       OutputStream os = null;
       FileInputStream fis = null;
       try {
           socket = new Socket(InetAddress.getByName("127.0.0.1"), 9090);
           os = socket.getOutputStream();

           fis = new FileInputStream(new File("src/com/sorrymaker/IO/01.png"));

           byte[] buffer = new byte[10];
           int len;
           while ((len = fis.read(buffer)) != -1) {
               os.write(buffer, 0, len);
          }
      } catch (IOException e) {
           e.printStackTrace();
      } finally {
           if(fis!=null){
               try {
                   fis.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }
          }
           if(os!=null){
               try {
                   os.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }
          }
           if(socket!=null){
               try {
                   socket.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }
          }
      }
  }

   @Test
   public void server(){
       ServerSocket ss = null;
       Socket socket = null;
       InputStream is = null;
       FileOutputStream fos = null;
       try {
           ss = new ServerSocket(9090);

           socket = ss.accept();

           is = socket.getInputStream();

           fos = new FileOutputStream(new File("src/com/sorrymaker/Internet/01.png"));

           byte[] buffer = new byte[20];
           int len;
           while ((len = is.read(buffer)) != -1) {
               fos.write(buffer, 0, len);
          }
      } catch (IOException e) {
           e.printStackTrace();
      } finally {
           if (fos != null) {
               try {
                   fos.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }
          }
           if (is != null) {
               try {
                   is.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }
          }
           if (socket != null) {
               try {
                   socket.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }
          }
           if (ss != null) {
               try {
                   ss.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }
          }
      }
  }
}

例题3.

从客服端发送文件给服务端,服务端保存到本地,并返回"发送成功"给客户端。

重点: socket.shutdownOutput();

fis.read()是一个阻塞器的方法,没有明确的指示,所以一直在while循环中出不来,用了shutdownnOutput()强制停止。

package com.sorrymaker.Internet;

import org.junit.Test;

import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

/**
* 例题3.从客服端发送文件给服务端,服务端保存到本地,并返回"发送成功"给客户端。
*/
public class TCPTest3 {
   @Test
   public void client() {
       Socket socket = null;
       OutputStream os = null;
       FileInputStream fis = null;
       try {
           //1.
           socket = new Socket(InetAddress.getByName("127.0.0.1"), 9090);
           //2.
           os = socket.getOutputStream();
           //3.
           fis = new FileInputStream(new File("src/com/sorrymaker/IO/01.png"));
           //4.
           byte[] buffer = new byte[10];
           int len;
           while ((len = fis.read(buffer)) != -1) {
               os.write(buffer, 0, len);
          }
           socket.shutdownOutput();

           //5.接受来自于服务器端的数据,并显示到控制台上。
           InputStream is = socket.getInputStream();
           ByteArrayOutputStream baos =new ByteArrayOutputStream();
           byte[] buffer1 =new byte[10];
           int len1;
           while ((len1 = is.read(buffer1)) != -1) {
               baos.write(buffer1,0,len1);
          }
           System.out.println(baos.toString());
      } catch (IOException e) {
           e.printStackTrace();
      } finally {
           //6.
           if(fis!=null){
               try {
                   fis.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }
          }
           if(os!=null){
               try {
                   os.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }
          }
           if(socket!=null){
               try {
                   socket.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }
          }
      }
  }

   @Test
   public void server(){
       ServerSocket ss = null;
       Socket socket = null;
       InputStream is = null;
       FileOutputStream fos = null;
       try {
           //1.
           ss = new ServerSocket(9090);
           //2.
           socket = ss.accept();
           //3.
           is = socket.getInputStream();
           //4.
           fos = new FileOutputStream(new File("src/com/sorrymaker/Internet/02.png"));
           //5.
           byte[] buffer = new byte[20];
           int len;
           while ((len = is.read(buffer)) != -1) {
               fos.write(buffer, 0, len);
          }
           System.out.println("图片传输成功。");
           //6.服务器端给客户端反馈
           OutputStream os = socket.getOutputStream();
           os.write("我已经收到照片了,啊哈哈哈".getBytes());

      } catch (IOException e) {
           e.printStackTrace();
      } finally {

           //7.
           if (fos != null) {
               try {
                   fos.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }
          }
           if (is != null) {
               try {
                   is.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }
          }
           if (socket != null) {
               try {
                   socket.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }
          }
           if (ss != null) {
               try {
                   ss.close();
              } catch (IOException e) {
                   e.printStackTrace();
              }
          }
      }
  }
}

 

两道练习

练习1.

服务端读取图片发送给客户端,客户端保存图片到本地。

方便我读代码,没有使用try-catch-finally来处理异常。

package com.sorrymaker;

import org.junit.Test;

import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

/**
* 练习1.
*     服务端读取图片发送给客户端,客户端保存图片到本地。
*/
public class Day27Test1 {
   @Test
   public void client() throws IOException {
       //1.创建Socket对象,指明服务器端的ip和端口号。
       Socket socket = new Socket(InetAddress.getByName("127.0.0.1"),9090);
       //2.从服务端接受数据
       InputStream is = socket.getInputStream();
       //3.保存图片
       FileOutputStream fos =new FileOutputStream(new File("src/com/sorrymaker/02.png"));
       byte[] buffer =new byte[10];
       int len;
       while ((len = is.read(buffer)) != -1) {
           fos.write(buffer,0,len);
      }
       //4.关闭资源
       is.close();
       fos.close();
       socket.close();
  }

   @Test
   public void server() throws IOException {
       //1.new ServerSocket
       ServerSocket ss = new ServerSocket(9090);
       Socket socket = ss.accept();
       //2.读取文件
       FileInputStream fis =new FileInputStream(new File("src/com/sorrymaker/Internet/02.png"));
       //3.传输数据
       OutputStream os = socket.getOutputStream();
       byte[] buffer =new byte[10];
       int len;
       while ((len = fis.read(buffer)) != -1) {
           os.write(buffer,0,len);
      }
       //4.资源关闭
       os.close();
       fis.close();
       socket.close();
       ss.close();
  }
}

练习2.

客户端给服务端发送文本,服务端会将文本转成大写在发送给客户端。

package com.sorrymaker;

import org.junit.Test;

import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;

/**
* 练习2.
* 客户端给服务端发送文本,服务端会将文本转成大写在发送给客户端。
*/
public class Day27Test2 {
   @Test
   public void client() throws IOException {
       Socket socket = new Socket(InetAddress.getByName("127.0.0.1"),9090);
       OutputStream os = socket.getOutputStream();
       os.write("abcdefght".getBytes());
       socket.shutdownOutput();
       InputStream is = socket.getInputStream();
       byte[] buffer =new byte[10];
       int len;
       while ((len = is.read(buffer)) != -1) {
           String  str =new String(buffer,0,len);
           System.out.println("我是客户端,收到的数据为="+str);
      }
       is.close();
       os.close();
       socket.close();
  }

   @Test
   public void server() throws IOException {
       ServerSocket ss = new ServerSocket(9090);
       Socket socket = ss.accept();
       InputStream is = socket.getInputStream();
       OutputStream os = socket.getOutputStream();

       byte[] buffer =new byte[10];
       int len;
       String str =null;
       while ((len = is.read(buffer)) != -1) {
           str =new String(buffer,0,len);
           System.out.println("我是服务端,收到的数据为="+str);
           str = str.toUpperCase();
           os.write(str.getBytes());
      }
       os.close();
       is.close();
       socket.close();
       ss.close();
  }
}

 

posted @ 2021-04-07 22:20  独眼龙  阅读(63)  评论(0)    收藏  举报