Java高级基础

it2024-12-05  19

IO流

IO流​是一种实现数据交换技术的核心,比较常见的流的使用在于:文件操作,网络数据传输等;流由两大核心部分构成:1.Input(输入),2.Output(输出)。

流的分类

​按流向分为:输入流和输出流, 按类型分为:字节流和字符流,按功能分为:节点流和处理流。​字节流一般用于对于一些二进制文件(图片,音频,视频等)进行读写操作,java中的字节流都是来自以下两个抽象类:InputStream(字节输入流)OutputStream(字节输出流)。字符流主要用于文本输入输出。​java中所有的字符流都从以下两个抽象类继承:Reader 字符输入流 ,Writer 字符输出流。 ​在实际开发中有些需求可能会涉及到需要将字节流转换为字符流,或者将字符流转换为字节流等一些转换操作;另外也有可能需要将这些低级的节点流提高读取和写入效率,因此还需要一些高级流来进行处理,因此这些高级流也被称之为处理流,比如:转换流,缓冲流,打印流等。IO流基本是成对出现,因此在应用是注意相对应。

IO流经典实例:文件目录拷贝

public class FileCopyUtils { /** * 将一个源file对象拷贝到另一个目标file * @param source 源文件(可能是目录) * @param target 目标目录 * @throws IOException */ public static void copy(File source,File targetDir) throws IOException{ //判断当前需要被拷贝对象是目录还是标准文件 if(source.isDirectory()){ //在目录中创建子目录(不存在) targetDir = new File(targetDir,source.getName()); if(!targetDir.exists()){ //如果目录不存在则试图创建 if(!targetDir.mkdirs()){ throw new FileNotFoundException("目录创建失败,请检查权限"); } } //读取目录 File[] files = source.listFiles(); if(Objects.nonNull(files)){ for (int i = 0; i < files.length; i++) { copy(files[i],targetDir); } } }else{ //文件拷贝 copyFile(source,targetDir); } } private static void copyFile(File source, File targetDir) throws IOException { BufferedInputStream bis = null; BufferedOutputStream bow = null; try{ //获取源文件的输入流并包装为缓冲流 bis = new BufferedInputStream(new FileInputStream(source)); //根据源文件文件名组合目标目录成为新文件对象 File target = new File(targetDir,source.getName()); //获取目标文件的输出流 bow = new BufferedOutputStream(new FileOutputStream(target)); //声明字节缓冲区,缓存读取的字节数据 byte[] b = new byte[1024]; int len = 0; //循环读写 while((len = bis.read(b)) != -1){ bow.write(b, 0, len); } }finally{ //关闭资源 if(bow != null)bow.close(); if(bis != null)bis.close(); } } } public class TestCopy { public static void main(String[] args) throws IOException { //源file File f1 = new File("D:/javacode"); //目标file File f2 = new File("C:/Users/mrchai/Desktop"); //拷贝 FileCopyUtils.copy(f1, f2); } }

线程

进程就像是正在执行的任务,线程就像其中的一条路径。每一条线程都有各自的生命周期,并且线程对象都存在以下几种状态:初始,就绪,运行,阻塞,销毁。

线程创建

java中创建线程包含四种方式,但 实现Runnable接口和 继承Thread类是最基本也是最常用的创建方式。实现Runnable接口更灵活,类还能在实现其他接口或继承其他类,但是线程的创建和启动依然需要Thread类完成。继承Thread类,相对第一种更简单,可以直接创建子类对象并启动线程,但是耦合度较高,子类不能再对其他类继承。线程的启动:必须通过调用Thread类的start方法完成,不能直接通过线程对象调用run方法(实际还是单线程的执行方法:普通方法调用)。

线程中断

java多线程编程中,线程的中断包含以下几种方式:

标记中断法异常中断法 线程同步时使用synchronizad关键字将对象锁定,此时,如果对象被一个线程锁定,则其他线程无法在操作当前对象,只有等待拥有该对象锁的线程释放锁之后,其他线程才能使用该对象。 wait和notify(notifyAll)是Object类中的方法,wait和notify在调用时,当前线程对象必须拥有该对象的对象锁。 sleep是Thread类中提供一个用于让当前线程休眠的方法,里面需要一个毫秒数作为参数,当sleep执行后,当前线程会进入休眠状态(让出cup的时间片),当休眠时间到达后,线程会自动唤醒继续执行,sleep不需要当前线程拥有任何对象的对象监视器(对象锁)。 wait是来之Object类中的一个方法,可以让一个线程进入等待状态,并且这种等待状态不能自动唤醒,需要其他线程通过调用该对象的notify或notifyAll来手动唤醒,wait必须要求当前线程拥有该对象的对想想监视器(对象锁),并且wait一旦执行,该线程就会释放在对象上的监视器。

例:多线程实现文件修改监听

public class FileLinstener2 implements Runnable{ private File file; public FileLinstener2(File file) { this.file = file; } @Override public void run() { //获取当前文件最后修改时间 long time = file.lastModified(); while(true){ try { long now = file.lastModified(); if(now != time){ //文件被修改 System.out.println(file.getName()+" file changed,"+getTime(now)); //将原来的时间设置为最新时间 time = now; } Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } /**格式化日期*/ public String getTime(long time){ DateFormat fmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Date d = new Date(time); return fmt.format(d); } public static void main(String[] args) { //目标目录 File file = new File("C:\\Users\\mrchai\\Desktop\\tempfile"); //获取目录中所有子文件 File[] files = file.listFiles(); for (File f : files) { //为每一个File对象启动一条监听线程 FileLinstener2 lis = new FileLinstener2(f); Thread t = new Thread(lis); t.start(); } } }

网络编程

基于TCP/IP的Socket通信:

TCP/IP是一个安全可靠的传输协议,需要保证两个通信端点之间的稳定连接,并且也能保证数据传输的完整性还有顺序,Java中基于TCP/IP编程主要通过以下两个类完成:- java.net.ServerSocket 用于表示服务端套接字; java.net.Socket 用户表示客户端套接字。

Socket通信实例-文件传输

服务器端: public class FileServer2 extends Thread{ private Socket s; private File source; public FileServer2(Socket s, File source) { super(); this.s = s; this.source = source; } @Override public void run() { BufferedInputStream bis = null; BufferedOutputStream bos = null; try { //获取源文件的输入流 bis = new BufferedInputStream(new FileInputStream(source)); //获取socket的输出流并包装 bos = new BufferedOutputStream(s.getOutputStream()); byte[] b = new byte[1024]; int len = 0; System.out.println("向 "+s.getInetAddress().getHostAddress()+"开始传输...."); while((len = bis.read(b)) != -1){ bos.write(b, 0, len); } System.out.println("向 "+s.getInetAddress().getHostAddress()+"传输完成!"); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally{ try { if(bos != null)bos.close(); if(bis != null)bis.close(); } catch (IOException e) { e.printStackTrace(); } } } public static void main(String[] args) throws IOException { ServerSocket server = new ServerSocket(6666); System.out.println("SOFEEM文件服务器已启动,等待连接..."); //准备需要传输的文件对象 File source = new File("D:\\素材\\视频\\larva搞笑虫子\\1.mp4"); //循环监听 while(true){ //等待客户端连接 Socket s = server.accept(); System.out.println(s.getInetAddress().getHostAddress()+"进入服务器,准备传输..."); //根据每一个连接的客户端启动一条子线程 new FileServer2(s, source).start(); } } } 客户端: public class Client { public static void main(String[] args) throws UnknownHostException, IOException { //建立连接 Socket s = new Socket("192.168.4.198",6789); //获取socket的输入流 InputStream is = s.getInputStream(); DataInputStream dis = new DataInputStream(is); //准备file对象接受socket中的数据 File f = new File("C:\\Users\\mrchai\\Desktop\\1.mp4"); FileOutputStream fos = new FileOutputStream(f); byte[] b = new byte[1024]; int len = 0; while((len = dis.read(b)) != -1){ fos.write(b, 0, len); } fos.close(); dis.close(); s.close(); } }

基于UDP协议的Socket通信:

UDP(User Datagram Protocol),用户数据报协议,不是一个基于稳定连接的协议,使用UDP协议通信不需要通信的两个端点间建立连接,通信的端点既可以作为发送端也可以作为接收端;与TCP 协议之间的不同在于, UDP 不是一种基于稳定连接的通讯协议。Java中也提供了两个用于实现UDP通信的核心类:1. java.net.DatagramPacket 2. java.net.DatagramSocket。UDP数据广播的实现是通过java.net包中的MulticastSocket类实现,该类是DatagramSocket的子类,通过该类可以实现组播(广播)数据报的发送与接收。组播地址的使用一般为D类ip地址,D类地址一般为:224.0.0.0至239.255.255.255(包含)之间。

例:

发送端 public class BroadcastSender { public static void main(String[] args) throws IOException { //准备需要发送的消息 String msg = "路漫漫其修远兮"; //准备组播地址(D类IP地址) InetAddress ip = InetAddress.getByName("228.5.6.7"); //创建组播socket通道 MulticastSocket ms = new MulticastSocket(); //加入多播组 ms.joinGroup(ip); //将数据打包成数据报包 DatagramPacket dp = new DatagramPacket( msg.getBytes(), msg.getBytes().length, ip, 4567); ms.send(dp); ms.close(); } } 接收端 public class BroadcastReceiver { public static void main(String[] args) throws IOException { //准备组播地址(D类IP地址) InetAddress ip = InetAddress.getByName("228.5.6.7"); //创建组播socket通道 MulticastSocket ms = new MulticastSocket(4567); ms.joinGroup(ip); byte[] b = new byte[1024]; DatagramPacket dp = new DatagramPacket(b, b.length); //接收消息 ms.receive(dp); String s = new String(b,0,dp.getLength()); System.out.println(s); } }
最新回复(0)