会员可以在此提问,百战程序员老师有问必答
对大家有帮助的问答会被标记为“推荐”
看完课程过来浏览一下别人提的问题,会帮你学得更全面
截止目前,同学们一共提了 132437个问题

看完了这节课的视频以后,总结了下面的内容:

这节课的视频与上次课的视频不同的点在

上次课最后实现的多线程是 多个客户端访问一个服务器的情况,为了让服务器处理多个客户端,使用循环开启多个线程,为每一个客户端开启一个线程来处理服务器端接收信息及相应信息的操作。

while(true){

      Socket socket=server.accept();//接受多个客户端的连接

      ServerThread st=new ServerThread(socket);

      new Thread(st).start();

}


这次课的多线程是客户端的多线程,是单个客户端和单个服务器端之间,单个客户端想跟单个服务器端多次聊天,如果是单次聊天,按视频里最开始的写法(没有多线程的),客户端就只能先,通过BufferedReader包装键盘录入发送信息,后获取响应,并且只有一次聊天的机会,socket就结束了。

为了解决这两个问题:

1)客户端想多次聊天

2)客户端能不能不要总是先发送,后接受信息,能主动接受信息吗?

解决:

1) 循环,循环发送信息,循环读取信息,就可以多次聊天了

2)怎么能决定先发送还是先接受,如果写成以前死的代码,就是先发送后接受,想先接受怎么办,多线程,建立一个发送线程,一个接受线程,让2个线程开启,cpu不断的切换2个线程,有内容发送到客户端来,就主动去接受,就可以先接受了。这边键盘录入,用户想发送的时候按下回车,就可以向输入流中写数据,创造输入的字符串,有内容想发送到服务端,就会触发发送线程。


我分析的视频中的代码:

image.png


一个客户端 一个服务端

服务端只接受一次的socket对象,后面的多次聊天都是因为 

客户端一直开启线程,等待用户键盘录入的回车,从而发送数据,

服务器端接收到数据就一直执行while(true),不停的readUTF() 和writeUTF("收到了");


至于我看到有同学问为什么服务器端能一直读取,我想是因为while(true)里面的readUTF()在不停执行,只要在流里读到东西就会读取出来,在流里东西可用,检测到流末尾或者抛出异常前,此方法一直阻塞,等待读取的字符串。这里需要老师验证一下我说的,是不是我分析的这个原因******。


还有一个问题******,就是在客户端线程类:Send类的send方法中写出字符串的时候,为什么要flush一下。

我猜是因为:这里也需要老师解答一下:

1)每次写出之后flush是为了提高效率,如果一直不flush,缓冲区如果满了就会造成缓冲区堵塞

2)视频里的案例没有关闭流,关闭流的操作里会刷新,但是没有关闭流,一直开着,所以在这里刷新一下。

ps:

什么时候字节流需要刷新:

如果你的流入数据不是特别多,可以都操作结束了关流时写入,那么如果你的数据特别多,你把他们全都放到流中就会占用内存吧,如果占用够多就会死机吧?然后结果你明白了!你读取数据失败了!或者説你担心万一死机了数据没有保存不是很坑!所以你可以选择什么时候刷新下

所以当传入的数据特别大,又担心什么时候会突然停止的时候,字节流可以在某些地方刷新一下。

image.png


以上提到的两个地方都需要老师解答一下(带******号的),还有提到的其他地方如果有不太对的地方,也希望老师指导一下,谢谢!

JAVA 全系列/第二阶段:JAVA 基础深化和提高/网络编程(旧) 2701楼
JAVA 全系列/第二阶段:JAVA 基础深化和提高/IO 流技术(旧) 2702楼

容器中有两个同名hello对象,如果用list.remove("hello"),为何默认删除索引是0的这个,如果要删除后面的hello只能根据索引删除吗?


package string;


import java.util.List;
import java.util.ArrayList;
import java.util.Scanner;

public class TestArrayList {
    public static void main(String[] args) {
        //创建集合对象,接口new实现类
        List list = new ArrayList();
        //1.添加add(Object obj)
        list.add("hello");
        list.add(123);//自动装箱

        //2.集合中元素的个数size()
        System.out.println(list.size());
        System.out.println("集合是否为空"+list.isEmpty());
        //3.addAll(collection c)集合中元素添加到其他集合中
        List list2=new ArrayList();
        list2.add("hello");
        list2.add(123);
        list.addAll(list2);
        System.out.println(list);
        System.out.println("集合中元素个数"+list.size());
        //4.删除
        System.out.println("根据对象去删除");
        list.remove("hello");
        System.out.println(list);
        list.remove(new Integer(123));//索引
        System.out.println(list);
        list.remove(0);//根据索引去删除
        System.out.println(list);
        list.add("world");
        System.out.println(list);
    }
}


JAVA 全系列/第二阶段:JAVA 基础深化和提高/容器(旧) 2703楼
JAVA 全系列/第二阶段:JAVA 基础深化和提高/IO 流技术(旧) 2705楼



老师您好,您看一下我的代码和运行结果,帮我指出哪里出现了问题

package com.bjsxt.server;

import java.util.List;
import java.util.Map;

import com.bjsxt.servlet.Servlet;



/**
 * 
 * @author zhang - dell
 *用于初始化程序运行的数据
 *和根据不同的url创建所请求的Servlet对象
 */
public class WebApp {//App应用程序
	private static ServletContext contxt;
	
	static {
		contxt=new ServletContext();
		//分别获取对应关系的Map集合
		Map<String,String> servlet=contxt.getServlet();
		Map<String,String> mapping=contxt.getMapping(); 
		
		//创建解析XML文件
		WebDom4j web = new WebDom4j();
		web.parse(web.getDocument());//解析XML
		
		//获取解析XML之后的List集合
		List<Entity> entityList = web.getEntityList();
		List<Mapping> mappingList = web.getMappingList();
		
		//将List集合中的数据存储到Map集合
		for(Entity entity : entityList) {
			
			servlet.put(entity.getName(),entity.getClazz());
		}
//		System.out.println(servlet);
		for(Mapping map : mappingList) {
			//遍历url-pattern的集合
			List<String> urlPattern=map.getUrlPattern();
			for(String s:urlPattern) {
				mapping.put(s, map.getName());
			}
//			System.out.println(mapping);
			
		}
		/**根据url创建不同的Servlet对象
		 */
		public static Servlet getServlet(String url) {
			if(url==null||url.trim().equals("")) {
				return null;
			}
			//如果url正确
			//根据url的key获取servlet-name的值 /log,/reg=register
			String servletName=contxt.getMapping().get(url);
			//servletName得到对应的servlet-class
			String servletClass=contxt.getServlet().get(servletName);
			//使用反射创建Servlet对象
			Class<?>clazz=Class.forName(servletClass);
			//调用无参构造方法创建Servlet对象
			Servlet servlet=(Servlet) clazz.newInstance();
			return servlet;
		
		}
		
	}
	public static void main(String[] args) {
		
	}
	
}

代码截图:


    blob.png

运行截图:

blob.png

JAVA 全系列/第二阶段:JAVA 基础深化和提高/手写服务器项目(旧) 2708楼

public class Student implements Serializable {
    private String name;
    private int age;
    public static String schoolName;
    private transient String pwd;

    public Student() {
    }

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

    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;
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", pwd='" + pwd + '\'' +
                '}'+"schoolName="+schoolName;
    }
}
public class Test {
    public static void main(String[] args) {
        write();
        read();
    }

    //写对象方法
    public static void write(){
        ObjectOutputStream oos = null;
        try {
            oos = new ObjectOutputStream(new FileOutputStream("d:/a.txt"));
            Student stu = new Student("marry",20,"888888");
            Student.schoolName = "北校区";
            oos.writeObject(stu);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(oos != null){
                try {
                    oos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    //读对象方法
    public static void read(){
        ObjectInputStream ois = null;
        try {
            ois = new ObjectInputStream(new FileInputStream("d:/a.txt"));
            Student stu = (Student) ois.readObject();
            System.out.println(stu);
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            if(ois != null){
                try {
                    ois.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

运行结果:

image.png

老师,为什么我这个静态成员schoolName可以被序列化?

JAVA 全系列/第二阶段:JAVA 基础深化和提高/IO 流技术(旧) 2710楼

package com.bjsxt.array;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Date;

public class Test {
	public static void main(String[] args) {
		byte [] buf=write();//调用写对象的方法
		//调用读对象的方法
		read(buf);
	}
	public static byte[] write(){
		//创建字节数组流对象
		ByteArrayOutputStream baos=null;
		ObjectOutputStream oos=null;
		
		try {
			baos=new ByteArrayOutputStream();//创建字节数组流对象,目的地是字节数组,底层创建一个长度数为32的字节数组
			oos=new ObjectOutputStream(baos);
			oos.writeInt(98);
			oos.writeDouble(98.5);
			oos.writeChar('a');
			oos.writeBoolean(false);
			oos.writeObject(new Date(1000));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			//关闭流
			if (oos!=null) {
				try {
					oos.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
		
		return baos.toByteArray();
	}
	public static void read(byte [] buf){
		ByteArrayInputStream bais=null;
		ObjectInputStream ois=null;
		//创建对象
		try {
			bais=new ByteArrayInputStream(buf); //数据源是byte类型的数组
			ois=new ObjectInputStream(bais);
			
			//读数据
			System.out.println(ois.readInt());
			System.out.println(ois.readDouble());
			System.out.println(ois.readChar());
			System.out.println(ois.readBoolean());
			System.out.println(ois.readObject());
		} catch (ClassNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
		
			//关闭流
			if(ois!=null){
				try {
					ois.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
}

这里主函数去调用写出方法时是这样调用的

byte [] buf=write();//调用写对象的方法

有什么说法吗   第一次见这种写法

JAVA 全系列/第二阶段:JAVA 基础深化和提高/IO 流技术(旧) 2711楼

package com.bjsxt.copy;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

public class TestCopy {
	public static void main(String[] args) {
		/*File srcFile=new File("D:\\180416\\五一作业.docx");
		File targetFile=new File("E:\\五一作业.docx");
		//调用复制文件的方法
		copyFile(srcFile, targetFile);*/
		File srcDir=new File("D:\\180416");
		File targetDir=new File("E:\\180416");
		//调用复制指定目录下所有文件的方法
		copyDir(srcDir, targetDir);
	}
	public static void copyDir(File srcDir,File targetDir){
		if(!targetDir.exists()){
			targetDir.mkdir();//如果目的地的目录不存在,则需要使用File类的方法进行创建目录
		}
		File []files=srcDir.listFiles(); //获取指定目录下的所有File对象
		for (File file : files) {
			if (file.isFile()) {
				 //复制  srcDir -->D:\\180416  拼接  D:\\180416\\XXXX.doc文件
				//    targetDir-->E:\\180416 拼接 E:\\180416\\XXXX.doc文件
				copyFile(new File(srcDir+"\\"+file.getName()), new File(targetDir+"\\"+file.getName()));
			}else{
				//继续调用该方法,使用递归实现
				copyDir(new File(srcDir+"\\"+file.getName()), new File(targetDir+"\\"+file.getName()));
			}
		}
	}
	public static void copyFile(File srcFile,File targetFile){
		//(1)提高读取效率,从数据源
		BufferedInputStream bis=null;
		//(2)提高写入效率,写到目的地
		BufferedOutputStream bos=null;
		try {
			bis = new BufferedInputStream(new FileInputStream(srcFile));
			
			bos = new BufferedOutputStream(new FileOutputStream(targetFile));
			//(3)边读边写
			byte [] buf=new byte[1024];//中转站
			int len=0;//用于存储读到的字节的个数
			while((len=bis.read(buf))!=-1){
				bos.write(buf,0,len);
			}
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
		//(4)关闭
			if(bos!=null){
				try {
					bos.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			if(bis!=null){
				try {
					bis.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		
		}
	}
}

这个方法中拼接文件名字部分代码不太理解

public static void copyDir(File srcDir,File targetDir){
		if(!targetDir.exists()){
			targetDir.mkdir();//如果目的地的目录不存在,则需要使用File类的方法进行创建目录
		}
		File []files=srcDir.listFiles(); //获取指定目录下的所有File对象
		for (File file : files) {
			if (file.isFile()) {
				 //复制  srcDir -->D:\\180416  拼接  D:\\180416\\XXXX.doc文件
				//    targetDir-->E:\\180416 拼接 E:\\180416\\XXXX.doc文件
				copyFile(new File(srcDir+"\\"+file.getName()), new File(targetDir+"\\"+file.getName()));
			}else{
				//继续调用该方法,使用递归实现
				copyDir(new File(srcDir+"\\"+file.getName()), new File(targetDir+"\\"+file.getName()));
			}
		}
	}

要传入copyFile方法的参数是文件 不是只能传文件吗 又传入"\\"是干什么的  还有file.getName 完全不懂

JAVA 全系列/第二阶段:JAVA 基础深化和提高/IO 流技术(旧) 2712楼

object.rar

我这个还是出错为啥呢

JAVA 全系列/第二阶段:JAVA 基础深化和提高/IO 流技术(旧) 2713楼

seven.zip

人傻了,检查了好几遍都不行,老师帮忙看看哈



image.pngimage.png


JAVA 全系列/第二阶段:JAVA 基础深化和提高/XML 技术(旧) 2714楼
JAVA 全系列/第二阶段:JAVA 基础深化和提高/容器(旧) 2715楼

课程分类

百战程序员微信公众号

百战程序员微信小程序

©2014-2025百战汇智(北京)科技有限公司 All Rights Reserved 北京亦庄经济开发区科创十四街 赛蒂国际工业园
网站维护:百战汇智(北京)科技有限公司
京公网安备 11011402011233号    京ICP备18060230号-3    营业执照    经营许可证:京B2-20212637