Java的网络编程 Li.048

网络通信 ip 电脑地址 UDP TCP 端口号 socket 插座, 数据流间的插座, 用来联通 类似电脑是港口ip, socket是航线用来发货, 端口号是港口停放船的泊位, UDP TCP是小船还是大船来运送数据箱子 DatagramSocket 与 DatagramPacket DatagramSocket 创建一条航线 DatagramPacket 指定电脑ip(港口), 端口号(泊位), 运送的数据(集装箱) import java.io.IOException; import java.net.*; import java.nio.charset.StandardCharsets; public class Demo1_Send { public static void main(String[] args) throws IOException { String msg = "中午一起吃饭"; DatagramSocket datagramSocket = new DatagramSocket(); DatagramPacket datagramPacket = new DatagramPacket (msg.getBytes(StandardCharsets.UTF_8),msg.getBytes().length, InetAddress.getByName("127.0.0.1"),2000); datagramSocket.send(datagramPacket); datagramSocket.close(); } } import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; public class Demo2_Receive { public static void main(String[] args) throws IOException { DatagramSocket socket = new DatagramSocket(2000); DatagramPacket packet = new DatagramPacket(new byte[1024], 1024); socket.receive(packet); byte[] arr = packet.getData(); int len = packet.getLength(); System.out.println(new String(arr,0,len)); socket.close(); } } 能够不断录入的版本 import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.nio.charset.StandardCharsets; import java.util.Scanner; public class Demo3_Send { public static void main(String[] args) throws IOException { Scanner sc = new Scanner(System.in); DatagramSocket datagramSocket = new DatagramSocket(); while (true){ String msgLine = sc.nextLine(); if( "quit".equals(msgLine)){ break; } System.out.println(msgLine); DatagramPacket packet = new DatagramPacket (msgLine.getBytes(StandardCharsets.UTF_8), msgLine.getBytes().length, InetAddress.getByName("127.0.0.1"), 2000); datagramSocket.send(packet); } datagramSocket.close(); } } import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; public class Demo3_Receive { public static void main(String[] args) throws IOException { DatagramSocket socket = new DatagramSocket(2000); DatagramPacket packet = new DatagramPacket(new byte[1024], 1024); while (true){ socket.receive(packet); byte[] arr = packet.getData(); int len = packet.getLength(); System.out.println("信息" + new String(arr,0,len)); } } } 多线程发送和接收信息 import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.nio.charset.StandardCharsets; import java.util.Scanner; public class Demo4_MoreThread { public static void main(String[] args) { MyReceive myReceive = new MyReceive(); MySend mySend = new MySend(); myReceive.start(); mySend.start(); } } class MyReceive extends Thread{ @Override public void run() { try { DatagramSocket socket = null; socket = new DatagramSocket(2000); DatagramPacket packet = new DatagramPacket(new byte[1024], 1024); while (true){ socket.receive(packet); byte[] arr = packet.getData(); int len = packet.getLength(); System.out.println("信息" + new String(arr,0,len)); } } catch (IOException e) { e.printStackTrace(); } } } class MySend extends Thread{ @Override public void run() { Scanner sc = new Scanner(System.in); DatagramSocket datagramSocket = null; try { datagramSocket = new DatagramSocket(); while (true){ String msgLine = sc.nextLine(); if( "quit".equals(msgLine)){ break; } DatagramPacket packet = new DatagramPacket (msgLine.getBytes(StandardCharsets.UTF_8), msgLine.getBytes().length, InetAddress.getByName("127.0.0.1"), 2000); datagramSocket.send(packet); } } catch (IOException e) { e.printStackTrace(); } datagramSocket.close(); } } GUI 聊天 import java.awt.*; import java.awt.event.*; import java.io.*; import java.net.*; import java.nio.charset.StandardCharsets; import java.text.SimpleDateFormat; import java.util.Date; public class Demo5_GUIChat extends Frame{ private TextField textField; private TextArea viewText; private TextArea sendText; private Button send; private Button log; private Button clear; private Button shake; private DatagramSocket socket; // private BufferedReader br; private FileInputStream fis; private BufferedWriter bw; public Demo5_GUIChat() throws SocketException,IOException{ init(); southPanel(); centerPanel(); event(); Receive r = new Receive(); r.start(); this.setVisible(true); } public void event() { this.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { try { bw.close(); } catch (IOException ex) { ex.printStackTrace(); } socket.close(); System.exit(0); } }); send.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { try { send(); } catch (SocketException ex) { ex.printStackTrace(); } catch (IOException ex) { ex.printStackTrace(); } } }); log.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { try { logFile(); } catch (IOException ex) { ex.printStackTrace(); } } }); clear.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { viewText.setText(""); } }); shake.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) { // shake(); try { send(new byte[]{-1},textField.getText()); } catch (IOException ex) { ex.printStackTrace(); } } }); sendText.addKeyListener(new KeyAdapter() { @Override public void keyReleased(KeyEvent e) { if(e.getKeyCode() == KeyEvent.VK_ENTER ){ try { send(); } catch (IOException ex) { ex.printStackTrace(); } } } }); } public void shake(){ int x = this.getX(); int y = this.getY(); for(int i=0;i<20;i++){ try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } if(i % 2 == 0){ this.setLocation(x+3,y+3); } else { this.setLocation(x,y); } } } public void logFile() throws IOException { // br = new BufferedReader(new InputStreamReader(new FileInputStream("chat.log"))); // br = new BufferedReader(new FileReader("chat.log")); // viewText.setText(""); // int len ; // char [] arr = new char[1024]; // while ( ( len =br.read(arr)) != -1){ // viewText.append(new String(arr,0,len)); // } // br.close(); fis = new FileInputStream("chat.log"); ByteArrayOutputStream bos = new ByteArrayOutputStream(); int len; byte[] arr = new byte[8192]; while ( (len = fis.read(arr)) != -1){ bos.write(arr,0,len); } viewText.setText(bos.toString()); bos.close(); } public void send(byte[] arr,String ip) throws IOException { DatagramPacket packet = new DatagramPacket(arr, arr.length, InetAddress.getByName(ip), 9999); socket.send(packet); } public void send() throws IOException { String msg = sendText.getText(); if( "".equals(msg.trim()) || null ==msg){ return; } else { String ip = textField.getText(); if( ip.equals(null) || ip.trim().equals("")){ ip = "255.255.255.255"; } String time = getTime(); send(msg.getBytes(StandardCharsets.UTF_8),ip); String chatlog = time+" "+"我对:"+(ip.equals("255.255.255.255")? "所有人":ip)+"说:"+"\n"+ msg +"\n"+"\n"; viewText.append(chatlog); bw.write(chatlog); bw.flush(); sendText.setText(""); } } public String getTime(){ Date date = new Date(); SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss"); return sdf.format(date); } public void centerPanel() { Panel center = new Panel(); viewText = new TextArea(); sendText = new TextArea(5,2); viewText.setEditable(false); viewText.setBackground(Color.WHITE); center.setLayout( new BorderLayout()); center.add(sendText, BorderLayout.SOUTH); center.add(viewText, BorderLayout.CENTER); sendText.setFont(new Font("xxx", Font.PLAIN,20)); viewText.setFont(new Font("xxx", Font.PLAIN,16)); this.add(center, BorderLayout.CENTER); } public void southPanel() { Panel south = new Panel(); textField = new TextField(15); textField.setText("127.0.0.1"); send = new Button("发送"); log = new Button("记录"); clear = new Button("清除"); shake = new Button("振动"); south.add(textField); south.add(send); south.add(log); south.add(clear); south.add(shake); this.add(south, BorderLayout.SOUTH); } private void init() throws IOException { this.setLocation(500,10); this.setSize(500,800); socket = new DatagramSocket(); // bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("chat.log",true))); bw = new BufferedWriter(new FileWriter("chat.log",true)); } public static void main(String[] args) throws SocketException,IOException { Demo5_GUIChat guiChat = new Demo5_GUIChat(); } private class Receive extends Thread{ //发送 接收同时进行 @Override public void run() { try { DatagramSocket socket = new DatagramSocket(9999); DatagramPacket packet = new DatagramPacket(new byte[8192], 8192); while (true){ socket.receive(packet); byte[] arr = packet.getData(); int length = packet.getLength(); if( length == 1 && arr[0] == -1){ shake(); continue; } String msg = new String(packet.getData(), 0, packet.getLength()); String chatlog = getTime()+" "+textField.getText()+" "+"对我说:"+"\n"+msg+"\n\n" ; viewText.append(chatlog); bw.write(chatlog); bw.flush(); } } catch (SocketException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } } TCP协议 (重要) TCP 三次握手 import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; import java.nio.charset.StandardCharsets; public class Demo2_Server { public static void main(String[] args) throws IOException { ServerSocket server = new ServerSocket(2000); Socket socket = server.accept(); InputStream is = socket.getInputStream(); OutputStream os = socket.getOutputStream(); os.write("明天还上班不".getBytes(StandardCharsets.UTF_8)); byte[] arr = new byte[8192]; int len; len = is.read(arr); System.out.println(new String(arr,0,len)); } } import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.Socket; import java.nio.charset.StandardCharsets; public class Demo1_Client { public static void main(String[] args) throws IOException { Socket socket = new Socket("127.0.01",2000); InputStream is = socket.getInputStream(); OutputStream os = socket.getOutputStream(); byte[] arr = new byte[8192]; int len = is.read(arr); os.write("吃了".getBytes(StandardCharsets.UTF_8)); System.out.println(new String(arr,0,len)); } } 服务端 客户端TCP 优化 import java.io.*; import java.net.ServerSocket; import java.net.Socket; import java.nio.charset.StandardCharsets; public class Demo2_Server { public static void main(String[] args) throws IOException { ServerSocket server = new ServerSocket(2000); Socket socket = server.accept(); BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); OutputStream out; PrintStream ps = new PrintStream(socket.getOutputStream()) ; ps.println("快乐, 放假了"); System.out.println(br.readLine()); ps.println("出来玩吧"); System.out.println(br.readLine()); } } import java.io.*; import java.net.Socket; public class Demo2_Client { public static void main(String[] args) throws IOException { Socket socket = new Socket("127.0.01",2000); BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); PrintStream ps = new PrintStream(socket.getOutputStream()) ; System.out.println( br.readLine()); ps.println("是的, 放假了"); System.out.println( br.readLine()); ps.println("起飞"); } } 服务增加多线程 import java.io.*; import java.net.ServerSocket; import java.net.Socket; public class Demo2_Server { public static void main(String[] args) throws IOException { ServerSocket server = new ServerSocket(2000); while (true){ final Socket socket = server.accept(); new Thread(){ @Override public void run() { try { BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); OutputStream out; PrintStream ps = new PrintStream(socket.getOutputStream()) ; ps.println("快乐, 放假了"); System.out.println(br.readLine()); ps.println("出来玩吧"); System.out.println(br.readLine()); } catch (IOException e) { e.printStackTrace(); } } }.start(); } } } 服务端反转字符并写给客户端 import java.io.*; import java.net.ServerSocket; import java.net.Socket; public class Demo3_Server { public static void main(String[] args) throws IOException { ServerSocket server = new ServerSocket(2000); while (true){ final Socket socket = server.accept(); new Thread(){ @Override public void run() { while (true){ try { BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); PrintStream ps = new PrintStream(socket.getOutputStream()) ; StringBuilder sb = new StringBuilder( br.readLine()); ps.println(sb.reverse()); } catch (IOException e) { e.printStackTrace(); } } } }.start(); } } } import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintStream; import java.net.Socket; import java.util.Scanner; public class Demo3_Client { public static void main(String[] args) throws IOException { Socket socket = new Socket("127.0.01",2000); BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); PrintStream ps = new PrintStream(socket.getOutputStream()) ; Scanner sc = new Scanner(System.in); String s = null; while (true){ s = sc.nextLine(); ps.println(s); System.out.println( br.readLine()); } } } 上传文件到服务端 import java.io.*; import java.net.ServerSocket; import java.net.Socket; public class Demo4_Server_SaveFiles { public static void main(String[] args) throws IOException{ ServerSocket server = new ServerSocket(2000); while (true){ final Socket socket = server.accept(); new Thread(){ @Override public void run() { while (true){ try { InputStream is = socket.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(is)); PrintStream ps = new PrintStream(socket.getOutputStream()) ; File dir = new File("update"); if(!dir.exists()){ dir.mkdir(); } String fileName = br.readLine(); System.out.println(fileName); File file = new File(dir, fileName); if( file.exists()){ ps.println("已存在"); return; }else { ps.println("不存在"); } byte[] arr = new byte[8192]; int len; FileOutputStream fos = new FileOutputStream(file); while ( ( len = is.read(arr)) != -1){ fos.write(arr,0,len); } fos.close(); socket.close(); } catch (IOException e) { e.printStackTrace(); } } } }.start(); } } } import java.io.*; import java.net.Socket; import java.util.Scanner; public class Demo4_Client { public static void main(String[] args) throws IOException { Socket socket = new Socket("127.0.01",2000); InputStream is = socket.getInputStream(); BufferedReader br = new BufferedReader(new InputStreamReader(is)); PrintStream ps = new PrintStream(socket.getOutputStream()) ; Scanner sc = new Scanner(System.in); String s = null; int len; byte[] arr = new byte[8192]; while (true){ s = sc.nextLine(); File file = new File(s); if( !file.exists()){ System.out.println("文件不存在"); } else if( file.isDirectory()){ System.out.println("文件夹, 请重新输入文件"); } else if (file.isFile()){ ps.println(s); String flag = br.readLine(); if( "已存在".equals(flag)){ System.out.println(flag); return; } else { InputStream inputStream = new FileInputStream(file); while ( (len = inputStream.read(arr)) != -1){ ps.write(arr,0,len); } ps.flush(); } } } } }

September 17, 2021&nbsp;·&nbsp;8 分钟&nbsp;·&nbsp;Lizicai

Java的多线程二 Li.047

单例设计模式(重要) 保证类在内存中只有一个对象 饿汉式, 空间换时间, 类创建的时候就创建对象, 线程安全的 懒汉式, 双叫单例加载模式, 使用的时候才创建对象, 存在线程安全问题 区别, 饿汉式空间换时间, 懒汉式时间换空间, 多线程访问时, 饿汉式不会创建多个对象, 懒汉式可能创建多个对象 public class Demo1_Singleton { public static void main(String[] args) { Singleton s1 = Singleton.getInstance(); Singleton s2 = Singleton.getInstance(); System.out.println(s1); System.out.println(s2 == s1); } } class Singleton{ // 1. 私有化构造函数, 就不能随意实例类了 private Singleton (){} // 2. 创建实例 private static Singleton s = new Singleton(); // 3. 饿汉式 public static Singleton getInstance() { return s; } } class SingletonLazy{ private SingletonLazy (){} private static SingletonLazy s ; public static SingletonLazy getInstance() { if(s == null){ s = new SingletonLazy(); } return s; } } class SingletonFinal{ private SingletonFinal(){} public static final SingletonFinal s = new SingletonFinal(); } Runtime 类 Process exec(String command) throws IOException 执行命令 import java.io.IOException; public class Demo2_Runtime { public static void main(String[] args) throws IOException { Runtime runtime = Runtime.getRuntime(); runtime.exec("ls"); } } Timer ( 可以被ScheduledExecutorService取代 ) 一种工具, 线程用其安排以后在后台线程中执行的任务, 可安排任务执行一次, 或者定期重复执行 private static void demo1() { Timer t = new Timer(); // t.schedule(new MyTimerTask(), new Date(121,8,13,11,8,01); // 定时 执行 // 循环执行, 每3秒执行一次 t.schedule(new MyTimerTask(), new Date(121,8,13,11,8,01),3000); while (true){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(new Date()); } } ScheduledExecutorService Time的缺陷, 单线程多个任务排队, 一个任务执行时间长了, 后面任务受影响, 一个任务挂了, 后面的任务无法执行, 强依赖系统时间, 系统时间更改则会更改 ScheduledExecutorService 多线程, 则没有上述问题 ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) 延时initialDelay, 开始周期delay执行 import java.util.Date; import java.util.Timer; import java.util.TimerTask; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; public class Demo3_Timer { public static void main(String[] args) throws InterruptedException { // 一个任务出现 异常, 不影响其他任务 ScheduledExecutorService ses = Executors.newScheduledThreadPool(2); ses.scheduleAtFixedRate( new Runnable() { @Override public void run() { System.out.println("===" + Thread.currentThread().getName() + "==="); } } , 0, 3, TimeUnit.SECONDS); ses.scheduleAtFixedRate( new Runnable() { @Override public void run() { int i = 1/0; System.out.println("***" + Thread.currentThread().getName() + "***"); } } , 0, 3, TimeUnit.SECONDS); } private static void demo2(){ // 一个任务执行时间长了, 也不会任务其他任务 ScheduledExecutorService ses = Executors.newScheduledThreadPool(2); ses.scheduleAtFixedRate( new Runnable() { @Override public void run() { System.out.println("===" + Thread.currentThread().getName() + "==="); try { TimeUnit.SECONDS.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } } } , 0, 3, TimeUnit.SECONDS); ses.scheduleAtFixedRate( new Runnable() { @Override public void run() { System.out.println("***" + Thread.currentThread().getName() + "***"); } } , 0, 3, TimeUnit.SECONDS); } private static void demo1() { Timer t = new Timer(); // t.schedule(new MyTimerTask(), new Date(121,8,13,11,8,01); // 定时 执行 // 循环执行, 每3秒执行一次 t.schedule(new MyTimerTask(), new Date(121,8,13,11,8,01),3000); while (true){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(new Date()); } } } class MyTimerTask extends TimerTask{ @Override public void run() { System.out.println("起来上班"); } } 多个线程的通信(重要) this.notify() 随机唤醒单个等待线程 public class Demo1_Notify { public static void main(String[] args) { Printer p = new Printer(); new Thread(){ @Override public void run() { while (true){ try { p.method1(); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); new Thread(){ @Override public void run() { while (true){ try { p.method2(); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); } } class Printer{ private int flag = 1; public void method1() throws InterruptedException { synchronized (this){ if(flag != 1){ this.wait(); } System.out.println("aaaa"); flag = 2; this.notify(); } } public void method2() throws InterruptedException { synchronized (this){ if(flag != 2){ this.wait(); } System.out.println("bbbbbbbb"); flag = 1; this.notify(); } } } 三个或三个以上间的线程通信 public class Demo2_Notify3 { public static void main(String[] args) { Printer2 p = new Printer2(); new Thread(){ @Override public void run() { while (true){ try { p.method1(); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); new Thread(){ @Override public void run() { while (true){ try { p.method2(); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); new Thread(){ @Override public void run() { while (true){ try { p.method3(); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); } } class Printer2{ private int flag = 1; public void method1() throws InterruptedException { synchronized (this){ while (flag != 1){ this.wait(); } System.out.println("aaaa"); flag = 2; this.notifyAll(); } } public void method2() throws InterruptedException { synchronized (this){ while (flag != 2){ this.wait(); } System.out.println("bbbbbbbb"); flag = 3; this.notifyAll(); } } public void method3() throws InterruptedException { synchronized (this){ while (flag != 3){ this.wait(); } System.out.println("cccccccccccccc"); flag = 1; this.notifyAll(); } } } 线程间通信注意的问题 1.在同步代码块中,用哪个对象锁,就用哪个对象调用wait方法 2.为什么wait方法和notify方法定义在Object这类中? 因为锁对象可以是任意对象,Object是所有的类的基类,所以wait方法和notify方法需要定义在Object这个类中 3.sleep方法和wait方法的区别? a,sleep方法必须传入参数,参数就是时间,时间到了自动醒来 wait方法可以传入参数也可以不传入参数,传入参数就是在参数的时间结束后等待,不传入参数就是直接等待 b,sleep方法在同步函数或同步代码块中,不释放锁,睡着了也抱着锁睡 wait方法在同步函数或者同步代码块中,释放锁 互斥锁(重要) ReentrantLock Condition import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; public class Demo3_ReentrantLock { public static void main(String[] args) { Printer3 p = new Printer3(); new Thread(){ @Override public void run() { while (true) { try { p.method1(); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); new Thread(){ @Override public void run() { while (true) { try { p.method2(); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); new Thread(){ @Override public void run() { while (true) { try { p.method3(); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); } } class Printer3{ private int flag = 1; private ReentrantLock r = new ReentrantLock(); Condition c1 = r.newCondition(); Condition c2 = r.newCondition(); Condition c3 = r.newCondition(); public void method1() throws InterruptedException { r.lock(); if (flag != 1){ c1.await(); } System.out.println("aaaa"); flag = 2; c2.signal(); r.unlock(); } public void method2() throws InterruptedException { r.lock(); if (flag != 2){ c2.await(); } System.out.println("bbbbbbbb"); flag = 3; c3.signal(); r.unlock(); } public void method3() throws InterruptedException { r.lock(); if(flag != 3){ c3.await(); } System.out.println("cccccccccccccc"); flag = 1; c1.signal(); r.unlock(); } } 线程组 public class Demo4_ThreadGroup { public static void main(String[] args) { // demo1(); ThreadGroup threadGroup = new ThreadGroup("自造线程组"); Mythread mythread = new Mythread(); Runnable target; Thread t1 = new Thread(threadGroup, mythread); Thread t2 = new Thread(threadGroup,mythread,"线程1"); Thread t3 = new Thread(threadGroup,mythread,"线程2"); System.out.println(t1.getName()); System.out.println(t2.getName()); System.out.println(t3.getName()); System.out.println(t1.getThreadGroup().getName()); System.out.println(t2.getThreadGroup().getName()); System.out.println(t3.getThreadGroup().getName()); System.out.println(t1.getThreadGroup().getParent().getName()); } private static void demo1() { Mythread mythread = new Mythread(); Thread t1 = new Thread(mythread); Thread t2 = new Thread(mythread); ThreadGroup tg1 = t1.getThreadGroup(); ThreadGroup tg2 = t2.getThreadGroup(); System.out.println(tg1.getName()); System.out.println(tg2.getName()); } } class Mythread implements Runnable{ @Override public void run() { } } 线程的5种状态 新建线程.start() -> 线程就绪状态, 有执行权->抢到CPU执行权限执行->死亡状态, run执行完了 抢到CPU执行权限执行->wait或sleep线程阻塞->叫醒线,程线程就绪状态, 有执行权 线程池 程序创建一个线程成本比较高, 为了方便使用线程池, 使用后再返给JVM import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Demo5_Executors { public static void main(String[] args) { ExecutorService pool = Executors.newFixedThreadPool(2); pool.submit(new Mythread()); pool.submit(new Mythread()); pool.shutdown(); } } 实现Callable的线程 import java.util.concurrent.*; public class Demo6_Callable { public static void main(String[] args) throws ExecutionException, InterruptedException { ExecutorService pool = Executors.newFixedThreadPool(2); Future<Integer> f1 = pool.submit(new MyCallable(10)); Future<Integer> f2 = pool.submit(new MyCallable(20)); System.out.println(f1.get()); System.out.println(f2.get()); pool.shutdown(); } } class MyCallable implements Callable<Integer>{ private int num; public MyCallable(int num){ this.num = num; } @Override public Integer call() throws Exception { int sum = 0; for(int i=1;i<num;i++){ sum = sum + i; } return sum; } } 简单工厂模式 概述 静态工厂方法模式, 它定义一个具体的工厂类负责创建一些类的实例 优点 客户端不负责对象的创建, 从而明确各类的职责 缺点 静态工厂负责所有类的创建, 如果有新的对象或者新对象创建方式不同, 就需要不断修改工厂类, 不利于后期维护. public abstract class Animal { public void eat(){}; } public class AnimalFactory { public static Dog createDog(){ return new Dog(); } public static Cat createCat(){ return new Cat(); } public static Animal createAnimal(String animal){ if( "dog".equals(animal)){ return new Dog(); } else if( "cat".equals(animal)){ return new Cat(); } return null; } } public class Cat extends Animal{ @Override public void eat() { System.out.println("猫吃鱼"); } } public class Dog extends Animal{ @Override public void eat() { System.out.println("单身狗儿吃狗粮"); } } `` ...

September 12, 2021&nbsp;·&nbsp;9 分钟&nbsp;·&nbsp;Lizicai

Java的多线程一 Li.046

多线程增加效率 并行, 就是多个任务同时进行, 多核cpu同时执行 并发, 多个任务轮流进行, cpu一个一个的执行 证明 JVM 是多线程的 垃圾回收和main线程间隔执行 public class Demo1_Thread { public static void main(String[] args) { for(int i=0; i < 10000000 ;i++){ new Demo(); } for(int i=0; i < 10000 ; i++){ System.out.println("主线程"); } } } class Demo{ @Override protected void finalize() throws Throwable { System.out.println("垃圾被回收了"); } } 继承Thread 开启一个线程 实际run() 方法 start() 开启线程 public class Demo2_ExtendsThread { public static void main(String[] args) { MyThread mt = new MyThread(); // mt.run(); mt.start(); for (int i=0; i <10000 ; i++){ System.out.println(i+"bbbbbbbbbbbbb"); } } } class MyThread extends Thread{ @Override public void run() { for(int i=0; i < 10000 ;i++){ System.out.println(i+"aaaaaaaaaaaaaaa"); } } } 实际 Runnable 接口的类 实际Runnable类, 类作为参数传递给线程, start() 开启线程 public class Demo3_Runnable { public static void main(String[] args) { MyRunnable d = new MyRunnable(); Thread t = new Thread(d); t.start(); for(int i=0; i < 10000 ;i++){ System.out.println(i+"bbbbbbbbbbbbbbb"); } } } class MyRunnable implements Runnable{ @Override public void run() { for(int i=0; i < 10000 ;i++){ System.out.println(i+"aaa"); } } } 多线程的2种区别 继承 Thread: 由于子类重写了Thread类的run()方法, 当调用start()时, 直接找子类的run()方法 实际 Runnable: 构造函数中传入了Runnable的引用, 成员变量记住了它, start()调用run() 方法时内部判断成员变量Runnable的引用是否为空, 不为空看的Runnable的run(), 运行时是子类的run()方法. 继承Thread实现简单, 方便使用, 有父类则不能使用这种方法 有父类时可以实际Runnable 接口实现多线程, 对继承Thread的补充, 使用时必须获取线程对象, 使用复杂 匿名内类实现多线程的方法 public class Demo4_NoNameThread { public static void main(String[] args) { new Thread(){ @Override public void run() { for(int i=0; i<100000 ;i++){ System.out.println("aaaaaa"); } } }.start(); Thread t = new Thread(new Runnable() { @Override public void run() { for(int i=0;i<10000;i++){ System.out.println("bbbbbbbbbbbbbbbbbbb"); } } }); t.start(); } } 匿名内部类设置线程名字 public class Demo5_ThreadName { public static void main(String[] args) { // demo1(); Thread t = new Thread(){ @Override public void run() { // this.setName("小明"); System.out.println(this.getName()+"aaaaa"); } }; t.setName("李明"); t.start(); new Thread(){ @Override public void run() { this.setName("小明"); System.out.println(this.getName()+"aaaaa"); } }.start(); } private static void demo1() { new Thread("小明"){ @Override public void run() { System.out.println(this.getName()+ "aaaaa"); } }.start(); new Thread("小红"){ @Override public void run() { System.out.println(this.getName()+ "bbbbbb"); } }.start(); } } 也可调用setName更改名称 获取本类的引用Thread.currentThread() ...

September 10, 2021&nbsp;·&nbsp;6 分钟&nbsp;·&nbsp;Lizicai

Java的递归 Li.045

递归练习, 计算文件夹大小 import java.io.File; import java.util.Scanner; public class Demo1_FolderSize { public static void main(String[] args) { Scanner sc = new Scanner(System.in); String strFolder = null; long size = 0; while (true){ if( sc.hasNext()){ strFolder = sc.nextLine(); break; } } if( strFolder.equals(null)){ System.out.println("不能为空"); } else { File folder = new File(strFolder); if(folder.isFile()){ size = folder.length(); } else if(folder.isDirectory()){ size = getSize(folder); } else if(! folder.exists()){ System.out.println("文件夹不存在"); } } System.out.println(size); } public static long getSize(File folder){ long len = 0; File [] files = folder.listFiles(); for(File subFile:files){ if(subFile.isFile()){ len = len + subFile.length(); } else{ len = len + getSize(subFile); } } return len; } } 递归删除文件夹 删除文件内的文件 删除文件夹本身 import java.io.File; import java.util.Scanner; public class Demo2_DeleteFolder { public static void main(String[] args) { Scanner sc = new Scanner(System.in); String strFolder = null; strFolder = getDir(sc); if( strFolder.equals(null)){ System.out.println("不能为空"); } else { File folder = new File(strFolder); if(folder.isFile()){ folder.delete(); } else if(folder.isDirectory()){ deleteFolder(folder); } else if(! folder.exists()){ System.out.println("文件夹不存在"); } } } private static void deleteFolder(File folder) { File[] files = folder.listFiles(); for (File f : files){ if(f.isFile()){ f.delete(); } else if(f.isDirectory()){ deleteFolder(f); f.delete(); } } folder.delete(); } public static String getDir(Scanner sc) { String strFolder; while (true){ if( sc.hasNext()){ strFolder = sc.nextLine(); break; } } return strFolder; } } 复制文件到指定文件夹下 源文件夹, 目标文件夹 在目标文件夹中创建源文件夹 遍历源文件夹, 文件则调用stream 复制到目标文件夹/源文件夹, 文件夹则递归调用 import java.io.*; public class Demo3_MvFolder { public static void main(String[] args) throws IOException { File folderSrc = new File("test"); File folderDes = new File("des"); copyFile3(folderSrc, folderDes); } public static void copyFile3(File folderSrc, File folderDes) throws IOException { if(! folderDes.isDirectory()){ System.out.println("请复制到文件夹中"); return; } File newFolder = new File(folderDes, folderSrc.getName()); newFolder.mkdir(); for(File f : folderSrc.listFiles()){ if( f.isFile()){ fileStream(f.getAbsolutePath(), newFolder.getAbsolutePath()+"/"+f.getName()); } else{ copyFile3(f, newFolder); } } } public static void copyFile2(File folderSrc, File folderDes) throws IOException{ if(! folderDes.isDirectory()){ System.out.println("请复制到文件夹中"); return; } File tempFolder = new File(folderDes.getAbsolutePath()+"/"+folderSrc.getName()); if( folderSrc.isDirectory()){ tempFolder.mkdir(); } for( File f : folderSrc.listFiles()){ if( f.isFile()){ fileStream(f.getAbsolutePath(), tempFolder.getAbsolutePath()+"/"+f.getName()); } else { copyFile2(f, tempFolder); } } } public static void copyFile(File folderSrc, File folderDes) throws IOException { if(! folderDes.isDirectory()){ System.out.println("请复制到文件夹中"); return; } if( folderSrc.isDirectory()){ new File(folderDes.getAbsolutePath()+"/"+folderSrc).mkdir(); } for(File f: folderSrc.listFiles()){ if ( f.isFile()){ fileStream(f.getAbsolutePath(), (folderDes.getAbsolutePath()+"/"+f.getPath())); } else if( f.isDirectory()){ copyFile(f, folderDes); } } } public static void fileStream(String src, String desc) throws IOException{ FileInputStream fis = new FileInputStream(src); int len; byte[] arr = new byte[1024*100]; FileOutputStream fos = new FileOutputStream(desc); while ( (len = fis.read(arr)) != -1){ fos.write(arr,0,len); } fis.close(); fos.close(); } } 打印文件夹的内文件, 保持层级 import java.io.File; public class Demo4_PrintFolder { public static void main(String[] args) { File folder = new File("test"); int lev = 0; printFolder(folder, lev); } public static void printFolder(File folder , int lev){ System.out.println(folder.getPath()); for ( File f : folder.listFiles()){ for (int i=0;i<=lev;i++){ System.out.print("\t"); } if(f.isFile()){ System.out.println(f.getPath()); } else { // lev不能用lev++或++lev, 改变了lev值 printFolder(f, lev+1); } } } } 斐波那契数列 public class Demo5_TwoZi { public static void main(String[] args) { System.out.println(twoZi(6)); } public static int twoZi(int month){ int sum = 0; if(month > 2){ sum = twoZi(month-1) + twoZi(month-2); } else if(month == 2){ sum = 1; } else if(1 == month){ sum = 1; } return sum; } } 1000的阶乘, 其中所有0和尾部0的个数 import java.math.BigInteger; public class Demo6_1000JieChen { public static void main(String[] args) { BigInteger bi = new BigInteger("1"); for(int i=1;i<=1000;i++) { BigInteger tmepBi = new BigInteger(i + ""); bi = bi.multiply(tmepBi); } int sum = 0; String str = String.valueOf(bi); for(int i=0;i<str.length();i++){ if('0'== (str.charAt(i))){ sum++; } } int num = 0; for(int j=str.length()-1;j>=0;j--){ if( '0' == str.charAt(j)){ num++; } else { break; } } System.out.println(sum); System.out.println(num); } } 约瑟夫环 import java.util.ArrayList; import java.util.Iterator; public class Demo7_LuckYue { public static void main(String[] args) { int num = 8; System.out.println(getLuck(num)); System.out.println(getLuck2(num)); } public static int getLuck2(int num) { ArrayList<Integer> arrayList = new ArrayList<>(); for(int i=1;i<= num;i++){ arrayList.add(i); } int sum = 1; for(int i=0; arrayList.size()!=1;i++){ if( i == arrayList.size() ){ i = 0; } if(0 == sum % 3){ arrayList.remove(i--); } sum ++; } return arrayList.get(0); } public static int getLuck(int num){ ArrayList<Integer> arrayList = new ArrayList<>(); for(int i=1;i<= num;i++){ arrayList.add(i); } int sum = 0; while (arrayList.size() > 1){ Iterator<Integer> iterator = arrayList.iterator() ; while (iterator.hasNext()){ Integer i = iterator.next(); // next()和remove方法依赖关系 sum++; if(0 == sum % 3){ iterator.remove(); } } } return arrayList.get(0); } }

September 8, 2021&nbsp;·&nbsp;4 分钟&nbsp;·&nbsp;Lizicai

Java的IO其他流(及Properties) Li.044

序列流 SequenceInputStream 关闭时会关闭所有流 public class Demo1_Stream { public static void main(String[] args) throws IOException { FileInputStream fr1 = new FileInputStream("read1.md"); FileInputStream fr2 = new FileInputStream("read2.md"); SequenceInputStream sis = new SequenceInputStream(fr1,fr2); FileOutputStream fos = new FileOutputStream("read3.md"); int b ; while ( ( b = sis.read()) != -1){ fos.write(b); } sis.close(); fos.close(); } public static void demo1() throws IOException { FileInputStream fr1 = new FileInputStream("read1.md"); FileOutputStream fos = new FileOutputStream("read3.md"); int b; while ((b = fr1.read()) != -1) { fos.write(b); } fr1.close(); FileInputStream fr2 = new FileInputStream("read2.md"); while ((b = fr2.read()) != -1) { fos.write(b); } fr2.close(); fos.close(); } } IO 流整合多个 public class Demo1_Stream { public static void main(String[] args) throws IOException { Vector<FileInputStream> v = new Vector<>(); FileInputStream fr1 = new FileInputStream("read1.md"); FileInputStream fr2 = new FileInputStream("read2.md"); v.add(fr1); v.add(fr2); Enumeration<FileInputStream> en = v.elements(); SequenceInputStream sis = new SequenceInputStream(en); FileOutputStream fos = new FileOutputStream("read3.md"); int b ; while ( (b = sis.read()) != -1){ fos.write(b); } sis.close(); fos.close(); } } ByteArrayOutputStream 获取数据 ByteArrayOutputStream 的 toString 可直接转为默认或指定的字符 import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.IOException; public class Deom2_ByteArrayOutputStream { public static void main(String[] args) throws IOException { FileInputStream fi = new FileInputStream("read1.md"); ByteArrayOutputStream baos = new ByteArrayOutputStream(); int b ; while ( (b = fi.read()) != -1){ baos.write(b); } fi.close(); System.out.println(baos.toString()); System.out.println(baos.toString("utf-8")); } private static void Demo1() throws IOException { FileInputStream fi = new FileInputStream("read1.md"); byte[] arr = new byte[3]; int len; while ( ( len = fi.read(arr)) != -1){ System.out.println(new String(arr,0,len)); } fi.close(); } } 内存输出 import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.IOException; public class Demo3_Test { public static void main(String[] args) throws IOException { FileInputStream fis = new FileInputStream("read1.md"); byte[] arr = new byte[5]; int len; ByteArrayOutputStream bos = new ByteArrayOutputStream(); while ( (len = fis.read(arr)) != -1){ bos.write(arr,0,len); } fis.close(); System.out.println(bos.toString()); bos.close(); } } 随机读和存 RandomAccessFile import java.io.IOException; import java.io.RandomAccessFile; public class Demo4_RandomAccessFile { public static void main(String[] args) throws IOException { // Demo1(); Demo2(); } public static void Demo2() throws IOException{ RandomAccessFile raf = new RandomAccessFile("random.txt","rw"); int b; while ( (b = raf.read()) != -1){ System.out.println(b); } raf.close(); } private static void Demo1() throws IOException { RandomAccessFile raf = new RandomAccessFile("random.txt","rw"); raf.write(97); raf.seek(10); raf.write(98); raf.close(); } } 对象操作流 ObjecOutputStream 输出对象流, 序列化 import com.lizicai.bean.Person; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectOutputStream; public class Demo5_ObjectOutputStream { public static void main(String[] args) throws IOException { Person p1 = new Person("小明", 23); Person p2 = new Person("小红", 23); ObjectOutputStream oos = new ObjectOutputStream( new FileOutputStream("person.txt")); oos.writeObject(p1); oos.writeObject(p2); oos.close(); } } 读取对象流 import com.lizicai.bean.Person; import java.io.*; public class Deom6_ObjectInputStream { public static void main(String[] args) throws IOException, ClassNotFoundException { ObjectInputStream oos = new ObjectInputStream(new FileInputStream("person.txt")); Person p1 = (Person) oos.readObject(); System.out.println(p1.getName()+p1.getAge()); Person p2 = (Person) oos.readObject(); System.out.println(p2.getName()+p2.getAge()); } } 对象操作优化 对象放入集合中, 集合输出到流 import com.lizicai.bean.Person; import java.io.*; import java.util.ArrayList; public class Demo7_OptimeObjectStream { public static void main(String[] args) throws IOException, ClassNotFoundException { ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("hashSetPerson.txt")); ArrayList<Person> arrayList = new ArrayList<>(); arrayList.add(new Person("小明",25)); arrayList.add(new Person("小红",23)); arrayList.add(new Person("小王",26)); oos.writeObject(arrayList); oos.close(); ObjectInputStream ois = new ObjectInputStream(new FileInputStream("hashSetPerson.txt")); ArrayList<Person> personArrayList = ( ArrayList<Person> ) ois.readObject(); for(Person p : personArrayList){ System.out.println(p.getName() + p.getAge()); } } } IO 流增加 id 号 更改Person属性时更改serialVersionUID 可以准备知道原来Persion和现在Persion属性区别 import java.io.Serializable; public class Person implements Serializable { private static final long serialVersionUID= 1L; private String name; private int age; public Person(){} public Person(String name, int age) { this.name = name; this.age = age; } public void setName(String name) { this.name = name; } public String getName() { return name; } public void setAge(int age) { this.age = age; } public int getAge() { return age; } } IO 基本数据流, DataInputStream DataOutputStream import java.io.*; public class Demo8_DataInputStream { public static void main(String[] args) throws IOException { Demo1(); DataOutputStream dos = new DataOutputStream(new FileOutputStream("outData.txt")); dos.writeInt(997); dos.writeInt(998); dos.writeInt(999); dos.close(); DataInputStream dis = new DataInputStream(new FileInputStream("outData.txt")); int x = dis.readInt(); int y = dis.readInt(); int z = dis.readInt(); System.out.println(x); System.out.println(y); System.out.println(z); dis.close(); } private static void Demo1() throws IOException { FileOutputStream fos = new FileOutputStream("output.txt"); fos.write(997); fos.close(); } private static void Demo2() throws IOException { FileInputStream fis = new FileInputStream("output.txt"); int b = fis.read(); fis.close(); } } 打印流的概述和特点 PrintStream 和 PrintWriter 分别是打印的字节流和字符流 只操作数据目的 自动刷出作用不大 import java.io.*; public class Demo9_PrintStream { public static void main(String[] args) throws IOException { // Demo2(); PrintWriter pw = new PrintWriter(new FileOutputStream("printWriter.txt"), true); pw.println(97); } private static void Demo2() throws FileNotFoundException { PrintWriter pw = new PrintWriter("printWriter.txt"); pw.println(97); pw.write(97); pw.flush(); pw.close(); } private static void demo1() { PrintStream p = System.out; p.println("Hello World!"); p.write(97); p.close(); } } 标准输入输出流概述和输出语句 标准输入只有1个, 未关联到文件, 不用关闭, 关闭后无法打开了 标准输出流未关联文件, 也不用关闭 import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.PrintStream; public class Demo10_SystemInOut { public static void main(String[] args) throws IOException { // demo1(); System.setIn(new FileInputStream("systemin.txt")); System.setOut(new PrintStream("systemout.txt")); InputStream is = System.in; PrintStream ps = System.out; int b; while ( ( b = is.read()) != -1){ ps.write(b); } is.close(); ps.close(); } private static void demo1() throws IOException { InputStream is = System.in; int x = is.read(); System.out.println(x); is.close(); InputStream is2 = System.in; int y = is2.read(); System.out.println(y); } } 练习, 复制文件, 增加使用数组, 增加复制速度 import java.io.*; public class Demo11_SystemInOutTest { public static void main(String[] args) throws IOException { System.setIn(new FileInputStream("systemin.txt")); System.setOut(new PrintStream("systemout.txt")); InputStream is = System.in; PrintStream ps = System.out; byte [] arr = new byte[1024]; int len; while ( ( len = is.read(arr)) != -1){ ps.write(arr,0,len); } is.close(); ps.close(); } } 2种键盘录入方式 import java.util.Scanner; public class Demo12_SystemIn { public static void main(String[] args) throws IOException { // demo1(); Scanner sc = new Scanner(System.in); String s = null; if(sc.hasNext()){ s = sc.nextLine(); } System.out.println(s); } private static void demo1() throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String line = br.readLine(); System.out.println(line); } } Properties的概述和作为Map集合的使用 Object setProperty(String key, String value) 添加键值对 Enumeration<?> propertyNames() 获取 key值枚举 String getProperty(String key) 根据key 值获取 value import java.util.Enumeration; import java.util.Properties; public class Demo13_Properties { public static void main(String[] args) { // demo1(); Properties pp = new Properties(); pp.setProperty("name", "小明"); pp.setProperty("tel", "12310001000"); System.out.println(pp); Enumeration <String> en = (Enumeration<String>) pp.propertyNames(); while ( en.hasMoreElements()){ String key = en.nextElement(); System.out.println(key+pp.getProperty(key)); } } private static void demo1() { Properties p = new Properties(); p.put("intA", 12); System.out.println(p); } } Properties 读和存 void load(InputStream inStream) throws IOException 读取文件 void store(OutputStream out, String comments) throws IOException 写到文件, comments 加入注释 import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.Enumeration; import java.util.Properties; public class Demo13_Properties { public static void main(String[] args) throws IOException { Properties pp = new Properties(); System.out.println(pp); pp.load(new FileInputStream("config.properties")); System.out.println(pp); pp.setProperty("qq","123"); System.out.println(pp); pp.store(new FileOutputStream("config.properties"), "utf-8"); } }

September 6, 2021&nbsp;·&nbsp;5 分钟&nbsp;·&nbsp;Lizicai

Java的Reader和Writer类 Li.043

FileReader 读取文件 import java.io.FileReader; import java.io.IOException; public class Demo1_FileReader { public static void main(String[] args) throws IOException { // Demo1(); FileReader fr = new FileReader("m.txt"); int b ; while ( (b = fr.read()) != -1){ System.out.println((char)b); } fr.close(); } private static void Demo1() throws IOException { FileReader fr = new FileReader("m.txt"); int x = fr.read(); System.out.println(x); System.out.println((char)x); } } FileWriter 字符写入文件 import java.io.FileWriter; import java.io.IOException; public class Demo2_FileWriter { public static void main(String[] args) throws IOException { FileWriter fw = new FileWriter("output.txt"); String s = "这只羊叫Leon"; fw.write(s); fw.flush(); fw.close(); } } 字符复制 import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; public class Demo3_ReaderWriter { public static void main(String[] args) throws IOException { FileReader fr = new FileReader("input.txt"); FileWriter fw = new FileWriter("output.txt"); int b ; while ( (b = fr.read()) != -1){ fw.write(b); } fr.close(); fw.close(); } } 什么情况使用使用字符流 字符流也能复制文件, 但不推荐, 字节->字符, 字符->字节 多一步转换 程序需要读取一段文本, 或都需要写入一段文本的时候可以使用字符流 读取的时候按字符读出, 不会出现半个中文 写出时可直接字符串写出, 不用转换为字节数组 图片类文件不能使用字符流复制, 丢失数据 自定义数组复制 import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; public class Demo4_ReaderWriter { public static void main(String[] args) throws IOException { FileReader fr = new FileReader("input.txt"); FileWriter fw = new FileWriter("output.txt"); char[] arr = new char[1024]; int len; while ( (len = fr.read(arr)) != -1){ fw.write(arr, 0 , len); } fr.close(); fw.close(); } } BufferedReader 和 BufferedWriter 读取写入字符 import java.io.*; public class Demo5_BufferedReader { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new FileReader("input.txt")); BufferedWriter bw = new BufferedWriter(new FileWriter("output.txt")); int b ; while ( (b=br.read()) != -1){ bw.write(b); } br.close(); bw.close(); } } BufferedReader readLine()方法, BufferedWriter 的newLine方法 newLine 没有放在write(line)后, 并写在循环内, 这样写多写一个空行 import java.io.*; public class Demo6_ReadLine { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new FileReader("input.txt")); BufferedWriter bw = new BufferedWriter(new FileWriter("output.txt")); String line ; if( (line = br.readLine() ) != null ){ bw.write(line); } while ( (line = br.readLine()) != null){ bw.newLine(); bw.write(line); } br.close(); bw.close(); } } 练习, 读取行, 并行数反向输出 流, 最好晚开早关 import java.io.*; import java.util.ArrayList; public class Demo7_ReverseLine { public static void main(String[] args) throws IOException { ArrayList<String> arrayList = new ArrayList<>(); String str ; BufferedReader br = new BufferedReader(new FileReader("input.txt")); while( ( str=br.readLine()) != null){ arrayList.add(str); } br.close(); BufferedWriter bw = new BufferedWriter(new FileWriter("output.txt")); for(int i= arrayList.size()-1;i>=0 ;i--){ bw.write(arrayList.get(i)); if( i == 0 ){ break; } bw.newLine(); } bw.close(); } } LineNumberReader import java.io.FileReader; import java.io.IOException; import java.io.LineNumberReader; public class Demo8_LineNumberReader { public static void main(String[] args) throws IOException { LineNumberReader lnr = new LineNumberReader(new FileReader("input.txt")); String line; lnr.setLineNumber(3); while ( (line = lnr.readLine()) != null){ System.out.println(lnr.getLineNumber() + " "+line); } lnr.close(); } } 装饰设计模式 使用被装饰的类, 对类中方法升级增加内容 好处 耦合性不强, 被装饰类的变化与装饰类的变化无关 public class Demo9_Wrap { public static void main(String[] args) { JiuCai j = new JiuCai(new Student()); j.code(); } } class Student { private String name; private int age; public void code(){ System.out.println("C"); System.out.println("Java"); } } interface Coder{ public void code(); } class JiuCai implements Coder{ JiuCai (Student stu){ this.stu = stu; } private Student stu; @Override public void code() { stu.code(); System.out.println("JavaEE"); System.out.println("SprintBoot"); } } 使用指定被码表读写字符 utf8格式写到gbk中, 乱码 ...

September 2, 2021&nbsp;·&nbsp;4 分钟&nbsp;·&nbsp;Lizicai

Java的IO流 Li.042

Java 的 IO 流 字节流, 字节流可以操作任何数据, 计算机中存储是字节流 InputStream OutputStream 字符流, 只能操作纯字符数据, 比较方便 Reader Writer 使用IO流要导入包, 使用时要进行异常处理, 使用后要释放资源 FileInputStream 读取一个文件 import java.io.FileInputStream; import java.io.IOException; public class Demo1_FileInputStream { public static void main(String[] args) throws IOException { FileInputStream fps = new FileInputStream("test.txt"); int x; while ((x = fps.read() ) != -1){ System.out.println(x); } fps.close(); } } read() 为什么接收的int类型 因为字节输入流可以操作任意类型的文件,比如图片音频等, 这些文件底层都是以二进制形式的存储的,如果每次读取都返回byte, 有可能在读到中间的时候遇到111111111,那么这11111111是byte类型的-1, 我们的程序是遇到-1就会停止不读了,后面的数据就读不到了,所以在读取的时候用int类型接收, 如果11111111会在其前面补上24个0凑足4个字节,那么byte类型的-1就变成int类型的255了这样可以保证整个数据读完, 而结束标记的-1就是int类型 字节输出流 write() void write(int b) throws IOException 在输出时int 去掉前3个byte字节, 写入第4个byte到文件中, 这个写是覆盖 import java.io.FileOutputStream; import java.io.IOException; public class Deom2_FileOutputStream { public static void main(String[] args) throws IOException { FileOutputStream fps = new FileOutputStream("test.txt"); fps.write(100); fps.write(101); fps.write(102); fps.close(); } } 字节输出流 追加 FileOutputStream(File file, boolean append) throws FileNotFoundException 输出字节流是否选择追加 import java.io.FileOutputStream; import java.io.IOException; public class Demo3_FileOutputStream { public static void main(String[] args) throws IOException { FileOutputStream fps = new FileOutputStream("test.txt", true); fps.write(100); fps.write(101); fps.close(); } } 复制文件 byte字节读取, byte复制 import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class Demo4_FileInOutStream { public static void main(String[] args) throws IOException { FileInputStream fis = new FileInputStream("test.txt"); FileOutputStream fos = new FileOutputStream("copy.txt"); int b = 0; while ( (b = fis.read() )!= -1){ fos.write(b); } fis.close(); fos.close(); } } FileInputStream 的 available方法 int available() throws IOException 返回输入流的长度 import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class Demo5_FileInOutStream { public static void main(String[] args) throws IOException { FileInputStream fis = new FileInputStream("test.txt"); FileOutputStream fos = new FileOutputStream("copy.txt"); int len = fis.available(); byte[] arr = new byte[fis.available()]; fis.read(arr); fos.write(arr); fis.close(); fos.close(); } } 通过数组 byte[] 读取写入 import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class Demo6_FileInOutStream { public static void main(String[] args) throws IOException { FileInputStream fis = new FileInputStream("test.txt"); FileOutputStream fos = new FileOutputStream("copy.txt"); byte[] arr = new byte[1024 * 1024]; int b = 0; while ( (b =fis.read(arr)) != -1 ){ fos.write(arr,0,b); } fis.close(); fos.close(); } private static void errSimple() throws IOException { FileInputStream fis = new FileInputStream("test.txt"); FileOutputStream fos = new FileOutputStream("copy.txt"); byte[] arr = new byte[3]; int b = 0; while ( (b =fis.read(arr)) != -1 ){ fos.write(arr); } fis.close(); fos.close(); } } BufferedInputStream BufferedOutputStream 原码先读取1024*8个字节到内存, 复制给 BufferedOutputStream 1024*8 然后才写入文件 只需要关闭BufferedInputStream BufferedOutputStream 就能关闭所有流 import java.io.*; public class Demo7_BufferInputStream { public static void main(String[] args) throws IOException { FileInputStream fis = new FileInputStream("test.txt"); FileOutputStream fos = new FileOutputStream("copy.txt"); BufferedInputStream bis = new BufferedInputStream(fis); BufferedOutputStream bos = new BufferedOutputStream(fos); int b ; while( ( b = bis.read() ) != -1){ bos.write(b); } // 只需关闭 BufferedInputStream BufferedOutputStream bis.close(); bos.close(); } } flush和close方法的区别 flush 刷新缓冲区, 缓冲区写到文件中, 刷完可以继续写. close 关闭前 就会刷新缓冲区 将缓冲区内容存到文件中 import java.io.*; public class Demo8_FlushClose { public static void main(String[] args) throws IOException { FileInputStream fis = new FileInputStream("test.txt"); FileOutputStream fos = new FileOutputStream("copy.txt"); BufferedInputStream bis = new BufferedInputStream(fis); BufferedOutputStream bos = new BufferedOutputStream(fos); int b ; while ( (b = bis.read()) != -1 ){ bos.write(b); bos.flush(); } bis.close(); bos.close(); } } 字节流读取中文有乱码 UTF-8中英文1个字节, 中文3个字节, 按字节读取都会读出乱码 import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; public class Demo9_CharIO { public static void main(String[] args) throws IOException { // Demo1(); FileOutputStream fos = new FileOutputStream("chinese.txt"); fos.write("你好啊, 世界!".getBytes(StandardCharsets.UTF_8)); fos.write("\r".getBytes(StandardCharsets.UTF_8)); fos.close(); } private static void Demo1() throws IOException { FileInputStream fis = new FileInputStream("chinese.txt"); byte[] arr = new byte[3]; String s; int len ; while ( ( len=fis.read(arr) ) != -1){ System.out.println(new String(arr,0,len)); } } } 异常处理 流初始化null try 关闭流 能关闭一个就关闭一个 import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; public class Demo10_IOException { public static void main(String[] args) throws IOException{ FileInputStream fis = null; FileOutputStream fos = null; try { fis = new FileInputStream("test.txt"); fos = new FileOutputStream("copy.txt"); } finally { try{ if(null != fis){ fis.close(); } } finally { if(null != fos){ fos.close(); } } } } } 图片加密解密 加密把输出的字节异或一个数, 解密时再异或这个数 import java.io.*; public class Demo12_Encrypt { public static void main(String[] args) throws IOException { String src = "beauty.png"; String dest = "copy.png"; String dest2 = "copy1.png"; // extracted(src, dest); extracted(dest, dest2); } private static void extracted( String src, String dest) throws IOException { BufferedInputStream fis = new BufferedInputStream(new FileInputStream(src)); BufferedOutputStream fos = new BufferedOutputStream(new FileOutputStream(dest)); int b ; while ( (b = fis.read()) != -1){ fos.write(b ^ 123 ); } fis.close(); fos.close(); } } 输入文件复制到当前路径下 import java.io.*; import java.util.Scanner; public class Demo13_CopyFile { public static void main(String[] args) throws IOException { Scanner sc = new Scanner(System.in); String src = null; if(sc.hasNext()){ src = sc.nextLine(); } BufferedInputStream fis =null; int b ; BufferedOutputStream fos = null; if(src != null){ File file = new File(src); fis = new BufferedInputStream(new FileInputStream(src)); fos = new BufferedOutputStream(new FileOutputStream("./"+file.getName())); if( file.isFile()){ while ( (b = fis.read()) != -1){ fos.write(b); } } else if( file.isDirectory()){ System.out.println("文件夹无法复制"); } } fis.close(); fos.close(); } } 练习, 录入输入字符到文件中 import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.Scanner; public class Demo14_InputKey { public static void main(String[] args) throws IOException { Scanner sc = new Scanner(System.in); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("test.txt", true)); String input = null; while ( sc.hasNext()){ input = sc.nextLine(); if( "quit".equals(input)){ break; } else{ bos.write(input.getBytes(StandardCharsets.UTF_8)); bos.write("\n".getBytes(StandardCharsets.UTF_8)); } } bos.close(); } }

August 30, 2021&nbsp;·&nbsp;4 分钟&nbsp;·&nbsp;Lizicai

Java的File类 Li.041

File 相对路径文件或目录 绝对路径文件或目录 File(String pathname) 文件路径或目录 File(String parent, String child) 父文件路径, 和子文件名 File(File parent, String child) 父文件路径file, 和子文件名 import java.io.File; public class Demo1_File { public static void main(String[] args) { // Demo1(); // Demo2(); File parentFile = new File("/usr/local/etc/nginx/"); String child = "nginx.conf"; File file = new File(parentFile, child); } private static void Demo2() { String parent = "/usr/local/etc/nginx/"; String child = "nginx.conf"; File file = new File(parent,child); System.out.println(file.exists()); } // a.c 与 src 在同级目录下 private static void Demo1() { File file = new File("/usr/local/etc/nginx/nginx.conf"); System.out.println(file.exists()); File file2 = new File("a.c"); System.out.println(file2.exists()); } } File 的方法 boolean createNewFile() throws IOException 如果没有则创建true, 有则不创建false. boolean mkdir() 无则创建文件夹, 有则不创建false boolean mkdirs() 无则创建多级文件夹, 有则不创建false import java.io.File; import java.io.IOException; public class Demo2_FileMethod { public static void main(String[] args) throws IOException { File file = new File("aaa.c"); System.out.println(file.createNewFile()); File file2 = new File("test"); System.out.println(file2.mkdir()); File file3 = new File("test/aaa"); System.out.println(file3.mkdirs()); } } boolean renameTo(File dest) 就是mv命令 boolean delete() 删除文件或删除空文件夹, 文件夹内有文件或文件夹(空的也算)则删除不了 import java.io.File; import java.io.IOException; public class Demo3_FileMethod { public static void main(String[] args) throws IOException { File file1 = new File("aaa.c"); File file2 = new File("bbb.c"); System.out.println(file1.renameTo(file2)); System.out.println(file2.delete()); File file3 = new File("test/aaa"); System.out.println(file3.delete()); File file4 = new File("test/ccc"); System.out.println(file4.mkdirs()); file4.delete(); File file5 = new File( "test"); System.out.println(file5.delete()); } } boolean isDirectory() 判断是否文件夹 boolean isFile() 判断是否文件 boolean exists() 判断是否存在 boolean canRead() 判断是否可读权限 boolean canWrite() 判断是否可写权限 boolean isHidden() 判断是否隐藏 import java.io.File; import java.io.IOException; public class Demo4_FileMethod { public static void main(String[] args) throws IOException { File file1 = new File("test"); System.out.println(file1.isDirectory()); File file2 = new File("test.c"); System.out.println(file1.isFile()); System.out.println(file2.isFile()); File file3 = new File("aaa.c"); System.out.println(file3.exists()); System.out.println(file3.createNewFile()); System.out.println(file3.exists()); File file4 = new File("ccc.c"); System.out.println(file4.createNewFile()); System.out.println(file4.canRead()); File file5 = new File("ddd.c"); System.out.println(file5.createNewFile()); System.out.println(file5.canWrite()); File file6 = new File("root.c"); System.out.println(file6.setReadable(false)); System.out.println(file6.canRead()); System.out.println(file6.canWrite()); File file7 = new File("test.c"); System.out.println(file7.isHidden()); File file8 = new File(".idea"); System.out.println(file8.isHidden()); } } String getAbsolutePath() String getPath() String getName() long length() long lastModified() String[] list() File[] listFiles() import java.io.File; import java.text.SimpleDateFormat; import java.util.Date; public class Demo5_FileMethod { public static void main(String[] args) { File file = new File("aaa.c"); File file2 = new File("/Users/test/IdeaProjects/day19/"); System.out.println(file.getAbsoluteFile()); System.out.println(file2.getAbsoluteFile()); System.out.println(file.getPath()); System.out.println(file2.getPath()); System.out.println(file.getName()); System.out.println(file2.getName()); System.out.println(file.length()); System.out.println(file2.length()); System.out.println(file.lastModified()); System.out.println(file2.lastModified()); Date date = new Date(file.lastModified()); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); System.out.println(simpleDateFormat.format(date)); String [] arr = file.list(); // for(String s: arr){ // System.out.println(s); // } String [] arr2 = file2.list(); for(String s: arr2){ System.out.println(s); } File[] list1 = file.listFiles(); // for(File f : list1){ // System.out.println(f); // } File[] list2 = file2.listFiles(); for(File f : list2){ System.out.println(f); } } } 练习 查找文件夹下所有的.c结尾的文件 遍历所有的文件, 碰到文件夹则进入遍历 文件名字正则匹配, 匹配输出 或使用String endsWith 匹配 import java.io.File; public class Demo6_FileTest { public static void main(String[] args) { File file = new File("/Users/test/workplace/test"); File file2 = new File("/Users/test/workplace/test"); File[] arrFile = file.listFiles(); File[] arrFile2 = file2.listFiles(); String regex = ".*[\\.][c]$"; String strEnd = ".c"; fileFind(arrFile, strEnd); fileFindRegex(arrFile2, regex); } public static void fileFind(File[] file, String strEnd){ for(File f : file){ if(f.isDirectory()){ fileFind(f.listFiles(), strEnd); } else{ if( f.getName().endsWith(strEnd) ){ System.out.println(f.getName()); } } } return ; } public static void fileFindRegex(File[] file, String regex){ for(File f : file){ if(f.isDirectory()){ fileFindRegex(f.listFiles(), regex); } else{ if( f.getName().matches(regex) ){ System.out.println(f.getName()); } } } return ; } } String[] list(FilenameFilter filter) 实现FilenameFilter 接口, 返回匹配的数组 原码 ...

August 29, 2021&nbsp;·&nbsp;3 分钟&nbsp;·&nbsp;Lizicai