基于java的在线小说阅读系统

提示:

文章目录

前言

一、项目介绍

1.项目目的

2.任务需求

二、技术介绍

三、代码展示

1.文件格式

2. 封装类

3.客户端特有类

4.服务端特有类

任务一:客户端和服务器端通信连接

任务二:登录、注册、退出功能

任务三:小说查询列表功能

任务四:在线阅读小说功能

任务五:上传小说功能

任务六:下载小说功能

 5.错误提示

6.效果展示

总结


前言

        经过一段时间的Java知识学习,对这一段学习进行检验,因此做一个在线小说阅读系统项目,看自己的知识是否巩固。

        随着信息技术水平的空前提高,大众对于获取信息的方式有了越来越高的要求。作为一种新兴的阅读载体,电子书刊因其方便快捷的特性日益普及。图书馆作为搜集、整理图书文化资料的公共文化机构,势必要紧跟这一时代步伐以谋求进一步发展。传统的图书借阅方式虽重要且暂时不可替代,却无法完全满足读者的进一步需求。这时,将电子书纳入日常的借阅体系,为读者提供多样化的选择,不失为一个好的解决办法。

一、项目介绍

1.项目目的

        本系统的主要目标是设计并实现一个基于Java的在线阅读小说。项目需要实现关于服务端和客户端的连接,在此基础上,用户可以进行登录注册,并在登录注册后进行如阅读小说、下载小说、上传小说等功能。

2.任务需求

任务1:创建客户端、服务器端,完成简单通信

任务2:完成登录、注册、退出、返回功能

任务3:完成小说查询列表的功能

任务4:完成在线阅读小说功能

任务5:完成下载小说功能

任务6:完成上传小说功能

二、技术介绍

  • 应用面向对象的思想编写简单项目

  • 熟练操作Socket编程

  • 熟练操作文件I/O读写的操作

  • 了解配制文件的解析方式

  • 了解多线程的应用

  • 了解xml文件作为轻量级的存储,以及使用dom4j解析xml文件

三、代码展示

1.文件格式

我的整个项目分为两个部分——Client和Server

Client存放客户端方法

其中Contain方法和MessageEntity方法以及UserEntity方法是用来封装常量和变量的 ClientTest方法是客户端运行的代码

UserService方法用来判断登录与注册的成功与否

ResultUtil方法处理二级菜单

Server存放服务端方法 与Cilent方法的Contain方法和MessageEntity方法以及UserEntity方法作用一样

ServerApp方法是服务端运行的代码

UserService方法用来判断登录与注册的成功与否

XMLUtil方法用来处理xml的相关

2. 封装类

上面提到,项目中有很多共用的封装类,用来封装客户端和服务端都会用到的,或者代码需要经常用到的,就会单独封装

Contain类:用来存放经常使用的常量

//客户端的Contain
public class Contain {
   public static final String downloadPath="D:\\feisi_Java\\stream\\book";  //存放下载小说的路径
   public static final String bookPath  = "D:\\feisi_Java\\stream\\Server\\book"; //存放全部小说

    public static final String REGISTERSUCRESULT="100"; //注册成功
    public static final String REGISTERFAIRESULT="101"; //注册失败

    public static final String LOGINSUCRESULT="200";  //登录成功
    public static final String LOGINFAIRESULT="201";  //登录失败

    public static final String FLAGSTR = "j#";
}
//服务端的Contain
public class Contain {
    //服务器上存放小说的路径
    public static final String bookPath  = "D:\\feisi_Java\\stream\\Server\\book";
    public static final String FLAGSTR = "j#";
}

MessageEntity类:用来存放用户端和服务端都需要用到的交互信息

一定要实现Serializable接口

public class MessageEntity implements Serializable {
   
    private String bookName;
    private String content;
    private int page;

    public int getPage() { return page; }

    public void setPage(int page) { this.page = page; }

    public String getBookName() {
        return bookName;
    }

    public void setBookName(String bookName) {
        this.bookName = bookName;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    private int oprator;
    private UserEntity userEntity;

    public int getOprator() {
        return oprator;
    }

    public void setOprator(int oprator) {
        this.oprator = oprator;
    }

    public UserEntity getUserEntity() {
        return userEntity;
    }

    public void setUserEntity(UserEntity userEntity) {
        this.userEntity = userEntity;
    }
}

UserEntity方法:用户的信息定义

一定要实现Serializable接口

public class UserEntity implements Serializable {
    private String username;
    private String password;
    private Integer id;


    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }
}

3.客户端特有类

BookClientService类:用来查询服务器上的小说列表

public class BookClientService {
    public List<String> queryPrintAllBook(DataUtil dataUtil) throws IOException {
        List<String> list = new ArrayList<>();
        MessageEntity messageEntity =new MessageEntity();
        //只需要带一个操作
        messageEntity.setOprator(5);
        dataUtil.sendData(messageEntity);
        //阻塞
        String s = dataUtil.receiveData();
        String[] split = s.split("-");
        for (String s1 : split) {
            list.add(s1);
        }
        return list;
    }
}

DataUtil类:用来接收和发送服务端数据

public class DataUtil {
    static  byte[] bs  = new byte[512];
    Socket socket;
    ObjectOutputStream oos = null;
    public DataUtil(Socket socket){
        this.socket=socket;
    }

    public void sendData(MessageEntity messageEntity) throws IOException {
        OutputStream os = socket.getOutputStream();
        if(oos==null){
           oos= new ObjectOutputStream(os);
        }
        //写到服务器
        oos.writeObject(messageEntity);
    }

    //接受数据
    public String receiveData() throws IOException {
        InputStream is = socket.getInputStream();
        int total = is.read(bs);
        //把服务器相应的消息 判断一下
        String result = new String(bs,0,total);
        return result;
    }
}

UserCilentSercive类:专门用来记录登录和注册的输入

public class UserClientService {
    DataUtil dataUtil;
    ResultUtil resultUtil;
    public UserClientService(DataUtil dataUtil,ResultUtil resultUtil){
        this.dataUtil =dataUtil;
        this.resultUtil = resultUtil;
    }
    Scanner sc =new Scanner(System.in);
    public void login() throws IOException, InterruptedException {

        System.out.println("请输入登录的用户名:");
        String username = sc.nextLine();
        System.out.println("请输入登录的密码:");
        String password = sc.nextLine();
        UserEntity userEntity = new UserEntity();
        userEntity.setPassword(password);
        userEntity.setUsername(username);

        MessageEntity messageEntity = new MessageEntity();
        messageEntity.setOprator(1);
        messageEntity.setUserEntity(userEntity);


        dataUtil.sendData(messageEntity);

        //接受数据
        String s = dataUtil.receiveData();
        //根据服务器返回的结果取完成不同的处理
        resultUtil.postUserResult(s);
    }

    public void register() throws IOException, InterruptedException {

        System.out.println("请输入注册的用户id:");
        String userId = sc.nextLine();
        System.out.println("请输入注册的用户账号:");
        String username = sc.nextLine();
        System.out.println("请输入注册的密码:");
        String password = sc.nextLine();

        UserEntity userEntity = new UserEntity();
        userEntity.setUsername(username);
        userEntity.setId(Integer.parseInt(userId));
        userEntity.setPassword(password);

        MessageEntity messageEntity= new MessageEntity();
        messageEntity.setOprator(2);
        messageEntity.setUserEntity(userEntity);

        dataUtil.sendData(messageEntity);
        String s = dataUtil.receiveData();
        resultUtil.postUserResult(s);
    }
}

ResultUtil类:客户端的二级菜单代码

public class ResultUtil {
    ClientTest ct;
    DataUtil dataUtil;

    byte[] bs = new byte[512];

    BookClientService bookClientService = new BookClientService();

    Scanner sc = new Scanner(System.in);


    public ResultUtil(ClientTest ct, DataUtil dataUtil) {
        this.ct = ct;
        this.dataUtil = dataUtil;
    }

    public void postUserResult(String result) throws IOException, InterruptedException {
        if (result.equals(Contain.LOGINSUCRESULT)) {
            System.out.println("登录成功");
            String info = ct.menu();
            postBookResult(info);
        } else if (result.equals(Contain.LOGINFAIRESULT)) {
            System.out.println("登录失败--重写操作");
            ct.welcome();
        } else if (result.equals(Contain.REGISTERSUCRESULT)) {
            System.out.println("注册成功");
            String info = ct.menu();
            postBookResult(info);
        } else if (result.equals(Contain.REGISTERFAIRESULT)) {
            System.out.println("注册失败");
            ct.welcome();
        }
    }

    //统一处理二级菜单的 操作序号
    public void postBookResult(String info) throws IOException {
        if (info.equals("1")) {
            //查询小说列表
            //提示--输入小说名字进行阅读
            //把小说名字发送给服务器
            //服务器:通过IO流读取小说内容---字符流
            List<String> list = bookClientService.queryPrintAllBook(dataUtil);
            list.stream().forEach(s -> System.out.println(s));
            System.out.println("请选择你要阅读的小说:");
            //输入小说名
            String bookName = sc.nextLine();
            //用来记录有页数
            int page = 1;
            while (true) {
                //每一次都向服务器发送要执行的操作和书的页码,让服务器根据页码来读取相应的内容
                MessageEntity messageEntity = new MessageEntity();
                messageEntity.setBookName(bookName);
                messageEntity.setOprator(6);
                messageEntity.setPage(page);
                //向服务器发送书名,和阅读小说的操作
                dataUtil.sendData(messageEntity);
                //接受读取到的内容
                String content = dataUtil.receiveData();
                //打印到控制台
                System.out.println(content);
                System.out.println("第"+page+"页");
                System.out.println("1.上一页  2.下一页");
                System.out.println("其他数字退出");
                String choose = sc.nextLine();
                if (choose.equals("2")){//如果客户端选择下一页,就把页码数加一
                    page++;
                }else if(choose.equals("1")){//如果客户端要阅读上一页,就把页码数减一
                    //先要判断当前页数是不是第一页
                    if(page == 1){
                        System.out.println("当前已经为第一页");
                    }else{
                        page--;
                    }
                }else if (page!=1 &&page!=2){
                    break;
                }
                if(content.equals("end")){
                    break;
                }
            }
            String s = ct.menu();
            postBookResult(s);
        } else if (info.equals("2")) {
            System.out.println("请输入小说路径和名字");
            //D:\feisi_Java\stream\book\\天龙八部.txt
            String bookPathName = sc.nextLine();

            //为了获取文件的大小 ---百分比
            File file = new File(bookPathName);
            //整个文件的字节数
            long length = file.length();

            System.out.println("文件长度=" + length + "个字节");

            //上传----先读到内容---写出去网络
            FileInputStream fis = new FileInputStream(file);

            //服务器那边不知道你的文件名 ---告诉服务器文件名
            String bookName = bookPathName.substring(bookPathName.lastIndexOf("\\\\"));
            int total = 0;//每次读取的字节数---读到文件末尾-1
            double temp = 0.0;//累计读了多少
            boolean flag = true;
            while ((total = fis.read(bs)) != -1) {
                temp += total;
                try {
                    //为了效果----模拟网络延迟
                    //本机不存在网络延迟----没有效果
                    TimeUnit.MILLISECONDS.sleep(1);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                MessageEntity messageEntity = new MessageEntity();
                messageEntity.setOprator(3);
                if (flag) {
                    messageEntity.setBookName(bookName);
                    flag = false;
                }
                messageEntity.setContent(new String(bs, 0, total));
                dataUtil.sendData(messageEntity);
                //如果接受成功 这一次读取的内容上传成功
                String s = dataUtil.receiveData();
                System.out.print("已经完成:" + String.format("%.1f", (temp / length) * 100) + "%\r");
            }

            System.out.println("上传进度=100%");
            System.out.println("上传完成");
            MessageEntity messageEntity = new MessageEntity();
            messageEntity.setOprator(3);
            messageEntity.setContent("end");
            dataUtil.sendData(messageEntity);

            String r = ct.menu();
            postBookResult(r);

        } else if (info.equals("3")) {
            //下载之前先要做查询
            List<String> list = bookClientService.queryPrintAllBook(dataUtil);

            System.out.println("请输入下面显示的小说名字进行下载");
            //遍历输出所有的小说名字
            list.stream().forEach(s -> System.out.println(s));
            String bookName = "";
            while (true) {
                bookName = sc.nextLine();
                String finalBookName = bookName;
                //遍历查找list中是否存在输入的书名
                long count = list.stream().filter(s -> s.equals(finalBookName)).count();
                if (count == 0) {  //输入的小说名字不存在
                    System.out.println("请输入合理的小说名字");
                } else {
                    break;
                }
            }
            //收集到用户输入的小说名字,告诉服务器操作为
            MessageEntity messageEntity = new MessageEntity();
            messageEntity.setOprator(4);
            messageEntity.setBookName(bookName);
            dataUtil.sendData(messageEntity);

            File file = new File(Contain.downloadPath + "\\" + bookName);
            if (!file.exists()) {
                //当小说不存在是,创建一个小说文件
                file.createNewFile();
            } else {
                //当小说存在时
                file.delete();  //先删除原有小说文件
                file.createNewFile();  //再创建新的小说文件
            }
            while (true) {
                //接收到的数据
                String downLoadContent = dataUtil.receiveData();
                if (downLoadContent.endsWith("end")) {
                    //在上一步的最后,小说末尾有end,表示这里为小说末尾
                    System.out.println("下载完成!!!!!!!!!!!!!!!");
                    FileOutputStream fos = new FileOutputStream(file, true);
                    //这里把所有的end替换成无内容,实际上是删除所有end
                    fos.write(downLoadContent.replaceAll("end", "").getBytes());
                    break;
                }
                //写出接收到的内容到小说文件中
                FileOutputStream fos = new FileOutputStream(file, true);
                fos.write(downLoadContent.getBytes());
            }
            //返回二级菜单
            String s = ct.menu();
            postBookResult(s);
        }
    }
}

CilentTest类:客户端的运动代码

public class ClientTest {
    static Socket socket=null;
    Scanner sc =new Scanner(System.in);
    static UserClientService userClientService;

    public static void main(String[] args) throws IOException, InterruptedException {
        ClientTest clientTest = new ClientTest();
        clientTest.clientInit();
        //封装了接收数据和发送数据的api 功能
        DataUtil dataUtil =  new DataUtil(socket);
        userClientService= new UserClientService(dataUtil,new ResultUtil(clientTest,dataUtil));
        clientTest.welcome();
    }

    //初始化---连接服务器
    public void clientInit() throws IOException {
        //连接服务器
        socket = new Socket();
        socket.connect(new InetSocketAddress(8080));
    }

    //欢迎界面
    public void welcome() throws IOException, InterruptedException {
        System.out.println("欢迎来到在线小说阅读系统");
        System.out.println("1、登录系统");
        System.out.println("2、注册用户");
        System.out.println("3、退出系统");
        System.out.println("输入序号进行操作");
        String no = sc.nextLine();
        if(no.equals("1")){
            userClientService.login();
        } else if (no.equals("2")) {//注册
            userClientService.register();
        }else {
            System.exit(0);
        }

    }


    //登录之后的二级菜单
    public String menu(){
        System.out.println("选择序号操作");
        System.out.println("1、阅读小说");
        System.out.println("2、上传小说");
        System.out.println("3、下载小说");
        System.out.println("4、退出");
        String info = sc.nextLine();
        return info;
    }
}

4.服务端特有类

UserService类:验证客户端输入的登录信息和注册信息

public class UserService {

    public String login(UserEntity entity) throws DocumentException {
        List<UserEntity> userEntities = XMLUtil.parseXml();
        //通过stream流来判断用户名和密码是否合格
        //解析xml得到的数据----2条
        //count=1 表示有一条数据
        //else 表示没有数据或者数据大于一条,登录失败
        long count = userEntities.stream()
                .filter(s -> s.getUsername().equals(entity.getUsername()))
                .filter(s -> s.getPassword().equals(entity.getPassword())).count();
        if (count == 1){
            //登录成功
            return ServerApp.LOGINSUCRESULT;
        }else {
            //登录失败
            return ServerApp.LOGINFAIRESULT;
        }
    }

    public String register(UserEntity userEntity) {
        try {
            XMLUtil.updateXml(userEntity);
            //注册成功
            return ServerApp.REGISTERSUCRESULT;
        } catch (Exception e) {
            e.printStackTrace();
            //注册失败
            return ServerApp.REGISTERFAiRESULT;
        }
    }
}

XMLUtil类:用来处理xml的相关(例如读取和修改xml文件)

public class XMLUtil {
    static List<UserEntity> list = new ArrayList<>();

    public static List<UserEntity> getList(){
        return list;
    }

    static String xmlFilePath = "D:\\feisi_Java\\stream\\Server\\src\\Users.xml";

    static Document document = null;
    /**
     * 获取所有的XML当中的元素
     */
    public static List<UserEntity> parseXml() throws DocumentException {
        Element rootElement = init();
        //遍历根节点下面所有的节点
        Iterator<Element> iterator = rootElement.elementIterator();
        while (iterator.hasNext()){
            //一个子元素---更元素下面的子元素
            Element element = iterator.next();
            //获取元素的属性
            Element username = element.element("username");
            String usernameValue = username.getStringValue();
            Element pwd = element.element("pwd");
            String pwdValue = pwd.getStringValue();

            UserEntity userEntity = new UserEntity();
            userEntity.setUsername(usernameValue);
            userEntity.setPassword(pwdValue);

            list.add(userEntity);
        }
        return list;
    }

    public static Element init() throws DocumentException {
        List<UserEntity> list = new ArrayList<>();
        File file = new File(xmlFilePath);
        //实例化SAXReader对象   读取xml
        SAXReader saxReader = new SAXReader();
        //整个xml的内容----Document
        document = saxReader.read(file);
        //根元素节点
        Element rootElement = document.getRootElement();
        return rootElement;
    }

    //更新
    public static void updateXml(UserEntity userEntity) throws DocumentException, IOException {
        Element rootElement = init();
        //往根元素下面添加一个属性 user
        Element element = rootElement.addElement("user");
        //给先添加的user元素添加一个属性 userId
        element.addAttribute("userId",userEntity.getId() + "");
        element.addElement("username").setText(userEntity.getUsername());
        element.addElement("pwd").setText(userEntity.getPassword());

        OutputFormat format = OutputFormat.createPrettyPrint();
        format.setEncoding("UTF-8");
        FileWriter fw = new FileWriter(xmlFilePath);
        XMLWriter xw = new XMLWriter(fw,format);
        xw.write(document);
        xw.close();
        fw.close();
    }
    public static boolean isEmpty(String s){
        if (s==null){
            return true;
        }else if (s.equals("")){
            return true;
        }
        return false;
    }
}

 Users.xml文件:存放用户的信息

任务一:客户端和服务器端通信连接

分析

  1. 创建服务器端线程类,并循环监听状态

  2. 创建客户端,请求服务器并发送消息

  3. 服务器端响应客户端

//服务端 
public void init() throws IOException, ClassNotFoundException, DocumentException {
        //监听是否有人来连接
        ServerSocket serverSocket = new ServerSocket();
        //绑定端口号
        serverSocket.bind(new InetSocketAddress(8080));
        System.out.println("服务器已启动,等待客户端连接...");
        //监听
        socket = serverSocket.accept();
        System.out.println("客户端已连接到服务器..."+socket.getInetAddress());
        postClientMessage();
}
//客户端 
public void clientInit() throws IOException {
        //连接服务器
        socket = new Socket();
        socket.connect(new InetSocketAddress(8080));
}

任务二:登录、注册、退出功能

分析

        1. 创建用于保存登录信息的文件

        2. 接收用户登录信息并查找登录信息文件,判断是否登录成功

        3. 接收用户注册信息并保存至登录信息文件

//服务端判定客户端输入内容
if (m.getOprator() == 1) { //登录
      //客户端输入的用户名,密码
      String result = userService.login(m.getUserEntity());
      //把登录结果write给客户端
      os.write(result.getBytes());
}else if (m.getOprator() == 2){
      //客户端输入的用户id,用户名,密码
      String register = userService.register(m.getUserEntity());
      //把注册结果write给客户端
      os.write(register.getBytes());
}

任务三:小说查询列表功能

else if (m.getOprator()==5){ //查询小说列表
            String bookList = "";
            File file = new File(Contain.bookPath);
            String[] list = file.list();
            for (String s : list) {
                bookList += s+"-";
            }
            os.write(bookList.getBytes());
        }

任务四:在线阅读小说功能

分析

  1. 添加用于存放各类小说文件地址的配制项

  2. 根据配制文件和小说列表xml文件将所有小说对象添加到List中

  3. 根据用户选择的小说名,从List中查找小说地址并显示内容

 

if (info.equals("1")) { //阅读小说
            List<String> list = bookClientService.queryPrintAllBook(dataUtil);
            list.stream().forEach(s -> System.out.println(s));
            System.out.println("请选择你要阅读的小说:");
            //输入小说名
            String bookName = sc.nextLine();
            //用来记录有页数
            int page = 1;
            while (true) {
                //每一次都向服务器发送要执行的操作和书的页码,让服务器根据页码来读取相应的内容
                MessageEntity messageEntity = new MessageEntity();
                messageEntity.setBookName(bookName);
                messageEntity.setOprator(6);
                messageEntity.setPage(page);
                //向服务器发送书名,和阅读小说的操作
                dataUtil.sendData(messageEntity);
                //接受读取到的内容
                String content = dataUtil.receiveData();
                //打印到控制台
                System.out.println(content);
                System.out.println("第"+page+"页");
                System.out.println("1.上一页  2.下一页");
                System.out.println("其他数字退出");
                String choose = sc.nextLine();
                if (choose.equals("2")){//如果客户端选择下一页,就把页码数加一
                    page++;
                }else if(choose.equals("1")){//如果客户端要阅读上一页,就把页码数减一
                    //先要判断当前页数是不是第一页
                    if(page == 1){
                        System.out.println("当前已经为第一页");
                    }else{
                        page--;
                    }
                }else if (page!=1 &&page!=2){
                    break;
                }
                if(content.equals("end")){
                    break;
                }
            }
            String s = ct.menu();
            postBookResult(s);
        }

任务五:上传小说功能

分析

  1. 根据用户输入的小说路径,读取源文件

  2. 根据配制文件的各类小说路径,将读取的源文件写入相应位置

  3. 根据用户输入的小说信息:小说名,保存至小说列表xml文件

 

else if (info.equals("2")) {
            System.out.println("请输入小说路径和名字");
            //D:\feisi_Java\stream\book\\天龙八部.txt
            String bookPathName = sc.nextLine();
            //为了获取文件的大小 ---百分比
            File file = new File(bookPathName);
            //整个文件的字节数
            long length = file.length();
            System.out.println("文件长度=" + length + "个字节");
            //上传----先读到内容---写出去网络
            FileInputStream fis = new FileInputStream(file);
            //服务器那边不知道你的文件名 ---告诉服务器文件名
            String bookName = bookPathName.substring(bookPathName.lastIndexOf("\\\\"));
            int total = 0;//每次读取的字节数---读到文件末尾-1
            double temp = 0.0;//累计读了多少
            boolean flag = true;
            while ((total = fis.read(bs)) != -1) {
                temp += total;
                try {
                    //为了效果----模拟网络延迟
                    //本机不存在网络延迟----没有效果
                    TimeUnit.MILLISECONDS.sleep(1);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                MessageEntity messageEntity = new MessageEntity();
                messageEntity.setOprator(3);
                if (flag) {
                    messageEntity.setBookName(bookName);
                    flag = false;
                }
                messageEntity.setContent(new String(bs, 0, total));
                dataUtil.sendData(messageEntity);
                //如果接受成功 这一次读取的内容上传成功
                String s = dataUtil.receiveData();
                System.out.print("已经完成:" + String.format("%.1f", (temp / length) * 100) + "%\r");
            }

            System.out.println("上传进度=100%");
            System.out.println("上传完成");
            MessageEntity messageEntity = new MessageEntity();
            messageEntity.setOprator(3);
            messageEntity.setContent("end");
            dataUtil.sendData(messageEntity);

            String r = ct.menu();
            postBookResult(r);

        } 

任务六:下载小说功能

分析

  1. 在配制文件添加下载路径的配制项

  2. 根据用户选择的小说读取小说源文件

  3. 把读取的文件写到对应下载路径中

else if (info.equals("3")) {
            //下载之前先要做查询
            List<String> list = bookClientService.queryPrintAllBook(dataUtil);

            System.out.println("请输入下面显示的小说名字进行下载");
            //遍历输出所有的小说名字
            list.stream().forEach(s -> System.out.println(s));
            String bookName = "";
            while (true) {
                bookName = sc.nextLine();
                String finalBookName = bookName;
                //遍历查找list中是否存在输入的书名
                long count = list.stream().filter(s -> s.equals(finalBookName)).count();
                if (count == 0) {  //输入的小说名字不存在
                    System.out.println("请输入合理的小说名字");
                } else {
                    break;
                }
            }
            //收集到用户输入的小说名字,告诉服务器操作为
            MessageEntity messageEntity = new MessageEntity();
            messageEntity.setOprator(4);
            messageEntity.setBookName(bookName);
            dataUtil.sendData(messageEntity);

            File file = new File(Contain.downloadPath + "\\" + bookName);
            if (!file.exists()) {
                //当小说不存在是,创建一个小说文件
                file.createNewFile();
            } else {
                //当小说存在时
                file.delete();  //先删除原有小说文件
                file.createNewFile();  //再创建新的小说文件
            }
            while (true) {
                //接收到的数据
                String downLoadContent = dataUtil.receiveData();
                if (downLoadContent.endsWith("end")) {
                    //在上一步的最后,小说末尾有end,表示这里为小说末尾
                    System.out.println("下载完成!!!!!!!!!!!!!!!");
                    FileOutputStream fos = new FileOutputStream(file, true);
                    //这里把所有的end替换成无内容,实际上是删除所有end
                    fos.write(downLoadContent.replaceAll("end", "").getBytes());
                    break;
                }
                //写出接收到的内容到小说文件中
                FileOutputStream fos = new FileOutputStream(file, true);
                fos.write(downLoadContent.getBytes());
            }
            //返回二级菜单
            String s = ct.menu();
            postBookResult(s);
        }

 5.错误提示

提示:所有的功能中,向服务端传送的数据的oprator数字,必须和对应功能一样,否则可能会出现Exception in thread “main” java.net.SocketException: Connection reset(线程“main”java.net.SocketException异常:连接重置)的错误。一般出现这个错误说明你客户端或者服务端有一端的读写出错了,或者有一端连接断开,可以使用debug一步步查看。

6.效果展示


总结

        经过这一次的在线小说阅读系统,我对很多知识有了更全面的了解,不再只停留在之前固定的几种方式中。例如I/O流,在项目之前,做的最复杂的也就是文件的复制,而且有具体的模版,所以我对I/O流没有很熟悉,但是这次项目,结合Socket编程一起,不再只是简单的拿名字或者复制,而是实现了客户端和服务端内容的交互,服务端的内容可以写出到客户端中,客户端的内容也可以写入到服务端中进行判断。

        对于Socket编程,更加体验到了它的难点,尤其是关于客户端和服务端两边的信息交互,它们之间是如何输入输出的,又用什么连接起来,这也是我需要继续去努力学习的地方,在编程中遇到的错误也大部分出自于有关Socket的地方,都努力去解决了。

        总的来说,这个项目让我对这一阶段的知识有了更全面、深刻的认识,更加意识到自己在哪些方面有不足,需要继续努力的。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值