第15 章 : 文件操作
67 File类基本操作
文件操作系统操作类:
java.io.File
文件创建,删除,重命名
File类基本使用
File 实现了Comparable接口
// 构造方法 public File(String pathname) public File(String parent, String child) // 创建文件 public boolean createNewFile() throws IOException // 文件存在 public boolean exists() // 删除文件 public boolean delete()
示例:
import java.io.File; import java.io.IOException; class Demo { public static void main(String[] args) throws IOException { File file = new File("./demo.txt"); if(file.exists()){ boolean ret = file.delete(); System.out.println("删除结果:" + ret); } else{ boolean ret = file.createNewFile(); System.out.println("创建结果:" + ret); } } }
68 File类操作深入
1、路径分隔符
Windows分隔符 "\"
Linux分隔符 "/"
路径分隔符常量 File.separator
2、文件操作流程
程序 -> JVM -> 操作系统函数 -> 文件处理
重复删除或创建的时候会有延时情况,
建议:文件名不要重名
3、创建文件的时候父级目录必须存在
// 获取父路径 public File getParentFile() // 创建目录 public boolean mkdirs()
示例
import java.io.File; import java.io.IOException; class Demo { public static void main(String[] args) throws IOException { File file = new File("./dir/demo/demo.txt"); File parentFile = file.getParentFile(); if (!parentFile.exists()) { parentFile.mkdirs(); } file.createNewFile(); } }
69 获取文件信息
涉及文件本身操作,不涉及文件内容处理
// 是否可读 public boolean canRead() // 是否可写 public boolean canWrite() // 是否可执行 public boolean canExecute() // 是否为文件 public boolean isFile() // 是否为目录 public boolean isDirectory() // 获取文件长度 字节 public long length() // 最后修改时间 13位时间戳 public long lastModified() // 列出目录内容 public File[] listFiles()
示例
import java.io.File; class Demo { public static void main(String[] args) { File file = new File("./dir/demo"); System.out.println(file.canRead()); // true System.out.println(file.canWrite()); // true System.out.println(file.canExecute()); // false System.out.println(file.isFile()); // true System.out.println(file.isDirectory()); // false System.out.println(file.length()); // 135 字节 System.out.println(file.lastModified()); // 1574952161000 File[] list = file.listFiles(); for (File f : list) { System.out.println(f); } // ./dir/demo/demo.txt } }
70 综合案例:列出目录结构
import java.io.File; class Demo { public static void main(String[] args) { File file = new File("./dir"); listDir(file); } public static void listDir(File file){ if(file.isDirectory()){ File[] files = file.listFiles(); if(files != null){ for(File f: files){ listDir(f); } } } else{ System.out.println(file); } } }
71 综合案例:文件批量更名
import java.io.File; class Demo { public static void main(String[] args) { long start = System.currentTimeMillis(); File file = new File("./dir"); renameDir(file); long end = System.currentTimeMillis(); System.out.println("花费时间:" + (end - start)); } public static void renameDir(File file){ if(file.isDirectory()){ File[] files = file.listFiles(); if(files != null){ for(File f: files){ renameDir(f); } } } else{ if (file.getName().contains(".")){ int endPos = file.getName().lastIndexOf("."); String name = file.getName().substring(0, endPos); File newFile = new File(file.getParent(), name + ".txt"); System.out.println(file.getName()); System.out.println(newFile); file.renameTo(newFile); } } } }
第16章 字节流与字符流
72 流的基本概念
File类是唯一一个与文件本身有关的程序处理类
File类只能够操作文件本身,而不能操作文件内容
IO操作:输入输出操作
java.io 抽象类
输出 输入 字节流:OutputStream, InputStream 字符流:Writer, Reader
文件处理流程:
1、File找到一个文件
2、通过字节流或字符流的子类为父类对象实例化
3、利用字节流或字符流中的方法实现数据出入与输出操作
4、流的操作属于资源操作,资源操作必须进行关闭
73 OutputStream字节输出流
实现代码
public interface AutoCloseable { void close() throws Exception; } public interface Closeable extends AutoCloseable { public void close() throws IOException; } public interface Flushable { void flush() throws IOException; } public abstract class OutputStream implements Closeable, Flushable{ public abstract void write(int b) throws IOException; public void write(byte b[]) throws IOException; public void write(byte b[], int off, int len) throws IOException; } // 子类 public class FileOutputStream extends OutputStream{ // 覆盖 public FileOutputStream(File file) throws FileNotFoundException // 追加 public FileOutputStream(File file, boolean append) throws FileNotFoundException; }
内容输出到文件
import java.io.File; import java.io.FileOutputStream; import java.io.IOException; class Demo{ public static void main(String[] args) throws IOException { File file = new File("demo/demo.txt"); // 父级目录不存在则创建 if(!file.getParentFile().exists()){ file.getParentFile().mkdir(); } String message = "这是输出的内容"; // 将字符串转换为字节数组输出到文件,并关闭文件 FileOutputStream output = new FileOutputStream(file); output.write(message.getBytes()); output.close(); } }
自动关闭的写法
try(FileOutputStream output = new FileOutputStream(file)){ output.write(message.getBytes()); }catch (IOException e){ e.printStackTrace(); }
使用追加换行输出
String message = "这是输出的内容\r\n"; FileOutputStream output = new FileOutputStream(file, true); output.write(message.getBytes()); output.close();
74 InputStream字节输入流
public abstract class InputStream implements Closeable{ // 读取单个字节数据,读到文件底部返回-1 public abstract int read() throws IOException; // 读取一组字节数据,返回读取的个数,文件底部返回-1 public int read(byte b[]) throws IOException; public int read(byte b[], int off, int len) throws IOException; }
文件尾部返回 -1, 表示文件读取完成
子类
public class FileInputStream extends InputStream{ public FileInputStream(String name) throws FileNotFoundException public FileInputStream(File file) throws FileNotFoundException }
读取示例
import java.io.File; import java.io.FileInputStream; import java.io.IOException; class Demo{ public static void main(String[] args) throws IOException { File file = new File("demo/demo.txt"); FileInputStream input = new FileInputStream(file); // 开辟缓冲区读取数据 byte[] data = new byte[1024]; int len = input.read(data); System.out.println("[" + new String(data, 0, len) + "]"); input.close(); } }
75 Writer字符输出流
Writer可以直接输出字符串
public abstract class Writer implements Appendable, Closeable, Flushable{ public void write(char cbuf[]) throws IOException; public void write(String str) throws IOException; } public class OutputStreamWriter extends Writer public class FileWriter extends OutputStreamWriter{ public FileWriter(String fileName, boolean append); public FileWriter(String fileName) public FileWriter(File file) public FileWriter(File file, boolean append) }
代码实例
import java.io.File; import java.io.FileWriter; import java.io.IOException; class Demo{ public static void main(String[] args) throws IOException { File file = new File("demo/demo.txt"); FileWriter writer = new FileWriter(file); writer.write("hello java"); writer.append("你好!java!"); writer.close(); } }
76 Reader字符输入流
继承关系
public abstract class Reader implements Readable, Closeable public class InputStreamReader extends Reader public class FileReader extends InputStreamReader{ public FileReader(File file); public FileReader(String fileName); }
读取示例
import java.io.File; import java.io.FileReader; import java.io.IOException; class Demo{ public static void main(String[] args) throws IOException { File file = new File("demo/demo.txt"); FileReader reader = new FileReader(file); char[] data= new char[1024]; int len = reader.read(data); System.out.println(new String(data, 0, len)); reader.close(); } }
字符流读取只能按照数组数据读取
77 字节流与字符流的区别
不使用close关闭
使用字节流输出 OutputStream 正常输出
使用字符流输出 Writer 无法输出,使用了缓冲区
close会强制刷新缓冲区(flush)
字节流不使用缓冲区,字符流使用缓冲区
78 转换流
字节流与字符流操作的功能转换
import java.io.*; class Demo{ public static void main(String[] args) throws IOException { File file = new File("demo/demo.txt"); // 字节流转字符流操作 OutputStream out = new FileOutputStream(file); Writer wirter = new OutputStreamWriter(out); wirter.write("你好"); wirter.close(); } }
继承关系
OutputStream(Closeable, Flushable) -FileOutputStream InputStream(Closeable) -FileInputStream Writer(Appendable, Closeable, Flushable) -OutputStreamWriter -FileWriter Reader(Readable, Closeable) -InputStreamReader -FileReader
缓存,程序中间缓冲区
字节数据:101010101...
79 综合实战:文件拷贝
实现文件拷贝操作
使用字节流
方案一:
全部读取,一次性输出
方法二:
每次读取一部分,输出一部分
import java.io.*; class FileUtil { public static void copyFile(String src, String target) throws IOException { InputStream input = new FileInputStream(src); OutputStream output = new FileOutputStream(target); byte[] data = new byte[1024]; int len = 0; while ((len = input.read(data)) != -1) { output.write(data, 0, len); } input.close(); output.close(); } public static void copyDir(String src, String target) throws IOException { File srcFile = new File(src); File targetFile = new File(target); if (!targetFile.exists()) { targetFile.mkdirs(); } File[] results = srcFile.listFiles(); if (results != null) { for (File file : results) { String fileName = targetFile + File.separator + file.getName(); if (file.isDirectory()) { copyDir(file.getPath(), fileName); } else { copyFile(file.getPath(), fileName); } } } } } class Demo { public static void main(String[] args) throws IOException { FileUtil.copyDir("demo", "demo2"); System.out.println("拷贝完成"); } }
如果拷贝目录则使用递归拷贝
第17 章 : IO操作深入
80 字符编码
常用的编码
1、GBK/GB2312 国标编码, GB2312简体中文,GBK包含简体和繁体
2、ISO8859-1 国际通用编码,描述所有字母
3、UNICODE 16进制存储,描述所有问题
4、UTF 象形文字部分使用16进制,普通字母采用ISO8859-1,主要使用UTF-8
列出本机属性
System.getProperties().list(System.out);
项目中出现乱码问题就是编码和解码标准不统一
81 内存操作流
文件操作流 以文件为操作终端,InputStream、OutputStream
内存操作流
1、字节内存操作流 ByteArrayOutputStream ByteArrayInputStream
2、字符内存操作流 CharArrayWriter CharArrayReader
继承关系
OutputStream -FileOutputStream -ByteArrayOutputStream InputStream -FileInputStream -ByteArrayInputStream Writer -OutputStreamWriter -FileWriter -CharArrayWriter Reader -InputStreamReader -FileReader -CharArrayReader
示例:利用内存流小写转大写操作
import java.io.*; class Demo{ public static void main(String[] args) throws IOException { String message = "hello java"; // 将数据保存到内存流中 InputStream input = new ByteArrayInputStream(message.getBytes()); OutputStream output = new ByteArrayOutputStream(); int data = 0; // 每次读取一个数据 while ((data = input.read())!=-1){ output.write(Character.toUpperCase(data)); } System.out.println(output); // HELLO JAVA output.close(); input.close(); } }
82 管道流
发送信息 <- 管道 -> 接收信息
字节管道流 PipedInputStream, PipedOutputStream
字符管道流 PipedReader, PipedWriter
继承关系
InputStream -PipedInputStream OutputStream -PipedOutputStream Reader -PipedReader Writer -PipedWriter
管道发送接收数据
import java.io.*; class Sender implements Runnable { private PipedOutputStream output; public Sender() { this.output = new PipedOutputStream(); } @Override public void run() { try { this.output.write("你好".getBytes()); } catch (IOException e) { e.printStackTrace(); } try { this.output.close(); } catch (IOException e) { e.printStackTrace(); } } public PipedOutputStream getOutput() { return this.output; } } class Receiver implements Runnable { private PipedInputStream input; public Receiver() { this.input = new PipedInputStream(); } @Override public void run() { try { byte[] data = new byte[1024]; int len = this.input.read(data); System.out.println(new String(data, 0, len)); // 你好 } catch (IOException e) { e.printStackTrace(); } try { this.input.close(); } catch (IOException e) { e.printStackTrace(); } } public PipedInputStream getInput() { return this.input; } } class Demo { public static void main(String[] args) throws IOException { Sender sender = new Sender(); Receiver receiver = new Receiver(); // 管道连接 sender.getOutput().connect(receiver.getInput()); new Thread(sender).start(); new Thread(receiver).start(); } }
83 RandomAccessFile
随机读取类,可以移动文件指针
public RandomAccessFile(String name, String mode)
import java.io.*; class Demo { public static void main(String[] args) throws IOException { // 写入 RandomAccessFile writer = new RandomAccessFile("demo.txt", "rw"); writer.write("你好世界".getBytes()); writer.close(); // 读取 RandomAccessFile reader = new RandomAccessFile("demo.txt", "rw"); String line; while ((line = reader.readLine()) != null) { System.out.println(line); } writer.close(); } }
第18 章 : 输入与输出支持
84 打印流
设计思想:装饰设计模式
为OutputStream 类实现一层包装
PrintStream
PrintWriter
继承关系
OutputStream -FilterOutputStream -PrintStream Writer -PrintWriter
import java.io.*; class Demo { public static void main(String[] args) throws IOException { PrintWriter writer = new PrintWriter(new FileWriter("demo.txt")); // 换行输出 writer.println("你好"); // 格式化输出 writer.printf("姓名 %s, 年龄: %s", "小强", 23); writer.close(); } }
只要是文件内容输出时都使用打印流
85 System类对IO的支持
System是系统类
1、标准输出(显示器)
2、错误输出
3、标准输入(键盘)
public final class System { public final static InputStream in = null; public final static PrintStream out = null; // 黑色字体 public final static PrintStream err = null; // 红色字体 }
修改输出位置
import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintStream; class Demo { public static void main(String[] args) throws IOException { System.setErr(new PrintStream(new FileOutputStream(new File("demo.txt")))); System.err.println("你好"); } }
接收键盘输入(一般不用此方法)
import java.io.IOException; import java.io.InputStream; class Demo { public static void main(String[] args) throws IOException { InputStream input = System.in; System.out.println("请输入姓名:"); byte[] data = new byte[1024]; int len = input.read(data); System.err.println(new String(data, 0, len)); } }
86 BufferedReader缓冲输入流
JDK < 1.5
缓冲字符输入流
继承关系
Reader -BufferedReader
代码示例
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; class Demo { public static void main(String[] args) throws IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); System.out.println("请输入:"); String msg = reader.readLine(); System.out.println(msg); } }
87 Scanner扫描流
JDK > 1.5
替代BufferedReader
构造函数
判断是否有数据 public boolean hasNext()
读取数据 public String next()
设置分隔符
import java.io.IOException; import java.util.Scanner; class Demo { public static void main(String[] args) throws IOException { Scanner scanner = new Scanner(System.in); System.out.println("请输入年龄:"); if(scanner.hasNextInt()){ int age = scanner.nextInt(); System.out.println("您输入的年龄是:" + age); } else{ System.out.println("输入不正确"); } scanner.close(); } }
可以结合正则进行判断验证
import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Scanner; class Demo { public static void main(String[] args) throws ParseException { Scanner scanner = new Scanner(System.in); System.out.println("请输入生日:"); if (scanner.hasNext("\\d{4}-\\d{2}-\\d{2}")) { String msg = scanner.next("\\d{4}-\\d{2}-\\d{2}"); System.out.println("您输入的年龄是:" + new SimpleDateFormat("yyyy-MM-dd").parse(msg)); } else { System.out.println("输入不正确"); } scanner.close(); } }
读取文件
import java.io.File; import java.io.FileNotFoundException; import java.util.Scanner; class Demo { public static void main(String[] args) throws FileNotFoundException { Scanner scanner = new Scanner(new File("demo.txt")); // 设置换行分隔符 // scanner.useDelimiter("\n"); while (scanner.hasNext()) { System.out.println(scanner.next()); } scanner.close(); } }
开发中:
输出使用PrintWriter打印流
输入使用Scanner扫描流
第19 章 : 对象序列化
88 对象序列化基本概念
对象序列化:
将内存中保存的对象以二进制数据的形式处理,
实现对象的保存或者网络传输
保存到文件 堆内存 - 二进制转换 -> 保存到数据库 发送到服务器
要序列化的对象必须实现java.io.Serializable 接口
没有任何方法,只是描述一种能力
示例
import java.io.Serializable; class Person implements Serializable { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } }
89 序列化与反序列化处理
继承关系
InputStream(ObjectInput, ObjectStreamConstants) -ObjectInputStream OutputStream(ObjectOutput, ObjectStreamConstants) -ObjectOutputStream
代码示例
import java.io.*; class Person implements Serializable { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } } class Demo { private static final File SAVE_FILE = new File("demo.person"); public static void main(String[] args) throws IOException, ClassNotFoundException { Person person = new Person("Tom", 23); // saveObject(person); System.out.println(loadObject()); // Person@15aeb7ab } // 序列化 public static void saveObject(Object obj) throws IOException { ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(SAVE_FILE)); oos.writeObject(obj); oos.close(); } // 反序列化 public static Object loadObject() throws IOException, ClassNotFoundException { ObjectInputStream ois = new ObjectInputStream(new FileInputStream(SAVE_FILE)); Object obj = ois.readObject(); ois.close(); return obj; } }
实际开发中不直接操作ObjectInputStream、ObjectOutputStream
90 transient关键字
表示进行序列化处理时,不处理被transient关键字修饰的字段
不常用,知道即可
IO继承体系整合
// 字节流: OutputStream(Closeable, Flushable) -FileOutputStream -ByteArrayOutputStream -PipedOutputStream -FilterOutputStream -PrintStream -ObjectOutputStream InputStream(Closeable) -FileInputStream -ByteArrayInputStream -PipedInputStream -ObjectInputStream // 字符流: Writer(Appendable, Closeable, Flushable) -OutputStreamWriter -FileWriter -CharArrayWriter -PipedReader -PrintWriter -BufferedWriter Reader(Readable, Closeable) -InputStreamReader -FileReader -CharArrayReader -PipedWriter -BufferedReader
第20 章 : JavaIO编程案例
91 数字大小比较
输入3个整数,并求出3个整数最大值和最小值
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; class InputUtil { /** * 读取指定个数的整数输入 * * @param num 指定要输入的整数个数 * @return 所有读取的整数数组 * @throws IOException */ public static int[] getIntList(int num) throws IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); System.out.println("请输入" + num + "个整数:"); int[] list = new int[num]; int count = 0; while (count < num) { String msg = reader.readLine(); if (msg.matches("\\d+")) { list[count++] = Integer.parseInt(msg); } else { System.out.println("请输入整数"); } } reader.close(); return list; } } class NumberUtil { /** * 获取int 型数组中最大值和最小值 * * @param list 整数数组 * @return int[] {max, min} */ public static int[] getMaxMin(int[] list) { int max = list[0]; int min = list[0]; for (int x : list) { if (x > max) { max = x; } if (min > x) { min = x; } } return new int[]{max, min}; } } class Demo { public static void main(String[] args) throws IOException { // 读取3个数据 int[] list = InputUtil.getIntList(3); int[] data = NumberUtil.getMaxMin(list); System.out.println("最大值:" + data[0]); System.out.println("最小值:" + data[1]); } }
92 文件保存
从键盘输入文件名和文件内容,然后将文件内容保存到文件中
1、定义接口
2、工具类
3、实现接口类
4、工厂类
5、测试函数
import java.io.*; class InputUtil { private static final BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); public static String getInput(String prompt) { System.out.println(prompt); String msg = null; while (true) { try { msg = reader.readLine(); if (!"".equals(msg)) { break; } else { System.out.println("请输入非空字符串:"); } } catch (IOException e) { } } return msg; } } interface IFileService { public static final String FILE_DIR = "demo"; public boolean save(); } class FileServiceImpl implements IFileService { private String filename; private String content; public FileServiceImpl() { this.filename = InputUtil.getInput("请输入文件名"); this.content = InputUtil.getInput("请输入文件内容"); } @Override public boolean save() { String fullname = this.FILE_DIR + File.separator + this.filename; PrintWriter writer = null; try { writer = new PrintWriter(fullname); writer.print(this.content); } catch (FileNotFoundException e) { e.printStackTrace(); } finally { if (writer != null) { writer.close(); } } return false; } } class Factory{ private Factory(){} public static FileServiceImpl getInstance(){ return new FileServiceImpl(); } } class Demo { // 项目启动时创建文件夹 static { File file = new File(IFileService.FILE_DIR); if (!file.exists()) { file.mkdirs(); } } public static void main(String[] args) throws IOException { FileServiceImpl fileService = Factory.getInstance(); fileService.save(); } }
93 字符串逆序显示
键盘传入多个字符串到程序中,并将它们按照逆序输出到屏幕
设计考虑:
1、字符串内容随时修改,使用StringBuffer
2、由用户自己决定是否继续输入
实现步骤
1、定义接口 操作标准
2、定义实现类
3、定义工厂类
4、编写辅助类
5、编写测试类
实现代码
IStringService.java
public interface IStringService { public void append(String str); public String[] reverse(); }
StringServiceImpl.java
public class StringServiceImpl implements IStringService{ private StringBuffer data = new StringBuffer(); public void append(String str){ this.data.append(str).append("|"); } public String[] reverse(){ String[] list = this.data.toString().split("\\|"); String[] tmp = new String[list.length]; for(int i=0; i<list.length; i++){ tmp[i] = list[list.length - i - 1]; } return tmp; } }
InputUtil.java
import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; class InputUtil { private static final BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); public static String getString(String prompt) { System.out.println(prompt); String msg = null; while (true) { try { msg = reader.readLine(); if (!"".equals(msg)) { break; } else { System.out.println("请输入非空字符串:"); } } catch (IOException e) { } } return msg; } public static void main(String[] args) { System.out.println(InputUtil.getString("请输入")); } }
Factory.java
class Factory{ private Factory(){} public static StringServiceImpl getInstance(){ return new StringServiceImpl(); } }
Menu.java
import java.util.Arrays; public class Menu { private StringServiceImpl stringServiceImpl; public Menu() { this.stringServiceImpl = Factory.getInstance(); this.choose(); } public void choose() { help(); String msg = InputUtil.getString("请选择:"); switch (msg) { case "1": this.stringServiceImpl.append(InputUtil.getString("请输入字符串:")); choose(); case "2": System.out.println(Arrays.toString(this.stringServiceImpl.reverse())); choose(); case "0": System.exit(0); default: choose(); } } public static void help() { System.out.println("[1]输入内容:"); System.out.println("[2]输出反转内容:"); System.out.println("[0]退出"); } }
Demo.java
class Demo{ public static void main(String[] args) { new Menu(); } }
94 数据排序处理
键盘输入数据 姓名:成绩|姓名:成绩
eg:
Tom:89|Jack:91|Tony:86
按照成绩由高到低排序
思路:
Comparable + Arrays
代码实现
IStudentService.java
public interface IStudentService { Student[] getData(); }
Student.java
public class Student implements Comparable<Student>{ private String name; private double score; public Student(String name, double score) { this.name = name; this.score = score; } @Override public String toString() { return "Student<" + name + ", " + score + '>'; } @Override public int compareTo(Student obj) { return Double.compare(obj.score, this.score); } }
StudentServiceImpl.java
import java.util.Arrays; public class StudentServiceImpl implements IStudentService { private String content; private Student[] students; public StudentServiceImpl(String content) { this.content = content; this.handle(); } private void handle(){ String[] list = this.content.split("\\|"); this.students = new Student[list.length]; for(int i=0; i<list.length; i++){ String[] items = list[i].split(":"); this.students[i] = new Student(items[0], Double.parseDouble(items[1])); } } @Override public Student[] getData() { Arrays.sort(this.students); return this.students; } }
Factory.java
public class Factory { private Factory(){} public static StudentServiceImpl getInstance(){ return new StudentServiceImpl(InputUtil.getString("请输入数据:")); } }
Demo.java
import java.util.Arrays; public class Demo { public static void main(String[] args) { // Tom:89|Jack:91|Tony:86 System.out.println(Arrays.toString(Factory.getInstance().getData())); // [Student<Jack, 91.0>, Student<Tom, 89.0>, Student<Tony, 86.0>] } }
95 数据排序处理深入
扩展上一节内容,将输入信息保存到文件中,还可以添加信息,并且查看全部数据
确认保存位置
格式统一
FileUtil.java文件读取工具类
package util; import java.io.*; import java.util.Scanner; public class FileUtil { public static String read(File file) throws FileNotFoundException { Scanner scanner = new Scanner(file); StringBuilder contents = new StringBuilder(); while (scanner.hasNext()) { contents.append(scanner.next()); } scanner.close(); return contents.toString(); } public static void append(File file, String content) throws IOException { PrintWriter writer = new PrintWriter(new FileWriter(file, true)); writer.write(content); writer.close(); } public static void save(File file, String content) throws IOException { PrintWriter writer = new PrintWriter(file); writer.write(content); writer.close(); } public static void main(String[] args) throws IOException { File file = new File("demo.txt"); FileUtil.save(file, "你好"); FileUtil.append(file, "你也好"); System.out.println(FileUtil.read(file)); } }
96 奇偶数统计
输入字符串拆分后统计奇数,偶数个数
接口INumberService.java
public interface INumberService { public int[] handle(); }
实现类 NumberServiceImpl.java
import util.InputUtil; public class NumberServiceImpl implements INumberService{ private String str; public NumberServiceImpl(){ this.str = InputUtil.getString("请输入数字串:"); } @Override public int[] handle() { String[] numbers = this.str.split(""); // 偶数, 奇数 int[] result = new int[]{0, 0}; for(String num : numbers){ if(Integer.parseInt(num) % 2 == 0){ result[0] ++; } else{ result[1] ++; } } return result; } }
测试类 Demo.java
import java.util.Arrays; public class Demo { public static void main(String[] args) { System.out.println(Arrays.toString(new NumberServiceImpl().handle())); // 1234567890 // [5, 5] } }
97 用户登录
输入用户名和密码 root 123456
如果没有输入则提示输入
输入错误3次退出
提示登录成功
真实业务只实现核心功能,辅助逻辑处理交给代理控制
接口类
IUserService
isExit
login
实现类
UserServiceImpl
代理类
UserServiceProxy
工厂类
Factory
测试类
Demo
实现代码
IUserService.java
public interface IUserService { public boolean isExit(); public boolean login(String name, String password); }
UserServiceImpl.java
public class UserServiceImpl implements IUserService{ private int tryCount = 0; @Override public boolean isExit() { // 超过三次错误 return this.tryCount >= 3; } /** * 实现核心逻辑 */ @Override public boolean login(String name, String password) { this.tryCount ++; if("root".equals(name) && "123456".equals(password)){ return true; } else{ return false; } } }
UserServiceProxy.java
import util.InputUtil; public class UserServiceProxy implements IUserService { private IUserService userService; public UserServiceProxy(IUserService userService) { this.userService = userService; } @Override public boolean isExit() { return this.userService.isExit(); } /** * 实现辅助逻辑 */ @Override public boolean login(String name, String password) { while (!this.isExit()) { String inputName = InputUtil.getString("请输入用户名:"); String inputPassword = InputUtil.getString("请输入密码:"); if (this.userService.login(inputName, inputPassword)) { System.out.println("登录成功"); System.exit(0); } else { System.out.println("用户名或密码错误,请重试"); } } System.out.println("重试次数过多,请稍后重试"); return true; } }
Factory.java
import util.InputUtil; public class Factory { private Factory(){} public static IUserService getInstance(){ return new UserServiceProxy(new UserServiceImpl()); } }
Demo.java
public class Demo { public static void main(String[] args) { Factory.getInstance().login(null, null); } }
98 投票选举
1、输入候选人名单
2、统计每个候选人票数
3、显示最终投票结果
思路分析
1、定义数据结构: Student name sid vote 2、操作接口类 IVoteService void inc(int sid) Student[] result() 排序数据 Student[] getData() 未排序数据 3、实现类 VoteServiceImpl 4、工厂类 Factory 5、测试类 Demo
实现代码
数据结构 Student.java
public class Student implements Comparable<Student> { private String name; private int sid; private int vote; public Student(String name, int sid, int vote) { this.name = name; this.sid = sid; this.vote = vote; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getSid() { return sid; } public void setSid(int sid) { this.sid = sid; } public int getVote() { return vote; } public void setVote(int vote) { this.vote = vote; } @Override public int compareTo(Student obj) { return obj.vote - this.vote; } @Override public String toString() { return String.format("[%s] %s - %s", sid, name, vote); } }
接口 IVoteService.java
public interface IVoteService { public void inc(int sid); public Student result(); public Student[] getData(); }
实现类 VoteServiceImpl.java
import util.InputUtil; import java.util.Arrays; public class VoteServiceImpl implements IVoteService { private Student[] students; public VoteServiceImpl() { this.students = new Student[]{ new Student("张三", 1, 0), new Student("李四", 2, 0), new Student("王五", 3, 0), }; } @Override public void inc(int sid) { for(Student s : this.students){ if(s.getSid() == sid){ s.setVote(s.getVote() + 1); } } } @Override public Student result() { Arrays.sort(this.students); return this.students[0]; } @Override public Student[] getData() { return this.students; } }
工产类 Factory.java
public class Factory { private Factory(){} public static IVoteService getInstance(){ return new VoteServiceImpl(); } }
菜单类 Menu.java
import util.InputUtil; import java.util.Arrays; public class Menu { private IVoteService voteService; public Menu() { this.voteService = Factory.getInstance(); this.choose(); } public void choose(){ this.help(); String num = InputUtil.getString("请选择:"); switch (num){ case "1": String sid = InputUtil.getString("请输入候选人id"); this.voteService.inc(Integer.parseInt(sid)); this.choose(); break; case "2": System.out.println(Arrays.toString(this.voteService.getData())); this.choose(); break; case "3": System.out.println(this.voteService.result()); this.choose(); break; case "0": System.out.println("拜拜..."); System.exit(0); default: help(); this.choose(); } } public void help(){ System.out.println("【1】候选人增加票数"); System.out.println("【2】显示投票统计"); System.out.println("【3】显示统计结果"); System.out.println("【0】退出系统"); } }
测试类 Demo.java
public class Demo { public static void main(String[] args) { new Menu(); } }