在文件 nameList.txt 中按下图格式存放着超过50万人的姓名与身份证信息。请使用您熟悉的编程语言(Java或C/C++)编写一段程序, 将出生日期落在1995年1月1日与1999年12月31日之间的个人信息取出,按年龄从大到小排列并输出到另一个txt文件中。 请重点考虑程序的健壮性和排序效率
小生想到思路:
1. 先读取文本内容;
2. 将头信息读取出来,并记录住;
3. 将真实数据按照行进行读取并封装到 javabean 中:每读取一行,将这行的数据用javabean封装,将这个javabean添加到 list 列表中:
4. 将得到的 list 列表进行排序,按照出生日期排序,这题正好:出生日期可以作为数字来看待,数字小的就是出生早的;
5. 将头信息和 list 列表再输出到指定文件中
注意:
题目是要求50万条数据记录进行读取排序,所以一定要想到包装类IO
还有就是要考虑健壮性和排序效率,健壮性,最完美的设计就是无论传递给程序什么javabean,程序都能把读到的数据封装成这个javabean
小生想到的就是动态代理和泛型。
具体实现代码如下(小生这里没有采用包装类了):
1 package com.hy.demo; 2 3 import java.io.File; 4 import java.io.FileInputStream; 5 import java.io.FileNotFoundException; 6 import java.io.FileOutputStream; 7 import java.io.IOException; 8 import java.lang.reflect.Constructor; 9 import java.nio.ByteBuffer; 10 import java.nio.CharBuffer; 11 import java.nio.channels.FileChannel; 12 import java.nio.charset.Charset; 13 import java.util.ArrayList; 14 import java.util.Collections; 15 import java.util.List; 16 17 import com.hy.demo.UserComparator.SortType; 18 19 public class DemoTest { 20 public static void main(String[] args) { 21 String inpathName = "D:/Workspaces/eclipse-marks-2/hire/src/name_list.txt"; 22 23 String content = getFileContent(inpathName); 24 25 // 得到用户数据列表 26 List<User> userList = getList(content, 3,"19950101","19991231"); 27 // 按照出生日期排序用户列表 28 String context = orderByUser(userList, SortType.ASC); 29 // 获取头信息 30 String header = getHeader(content, 3); 31 String outpathName = "D:/Workspaces/eclipse-marks-2/hire/src/a.txt"; 32 write(header, context, outpathName); 33 } 34 35 public static void write(String header,String context,String outPathName) { 36 FileOutputStream fos =null; 37 try { 38 fos = new FileOutputStream(outPathName); 39 fos.write(header.getBytes()); 40 fos.write(context.getBytes()); 41 42 fos.flush(); 43 } catch (IOException e) { 44 e.printStackTrace(); 45 } finally { 46 if(fos!=null) { 47 try { 48 fos.close(); 49 } catch (IOException e) { 50 e.printStackTrace(); 51 } 52 } 53 } 54 55 } 56 57 /** 58 * 对用户列表排序,并输出成文本格式 59 * @param list 60 * @param sortType ASC:按照出生日期升序,DESC:按照出生降序 61 * @return 62 */ 63 public static String orderByUser(List<User> list,SortType sortType) { 64 if(list!=null && list.size()>0) { 65 Collections.sort(list, new UserComparator(sortType)); 66 StringBuffer sb = new StringBuffer(); 67 68 for(int i=0;i<list.size();i++) { 69 User user = list.get(i); 70 sb.append(user.getName()).append(" \t\t"); 71 sb.append(user.getGener()).append("\t\t"); 72 sb.append(user.getIdCard()).append("\t\t"); 73 sb.append(user.getAddress()).append("\r\n"); 74 } 75 return sb.toString(); 76 } 77 return null; 78 } 79 80 /** 81 * 读取文本,获取数据源 82 * 83 * @param path 84 * @return 85 */ 86 public static String getFileContent(String path) { 87 File file = new File(path); 88 // 分配新的直接字节缓冲区 89 ByteBuffer byteBuffer = ByteBuffer.allocateDirect(1024); 90 StringBuffer stringBuffer = new StringBuffer(1024); 91 try { 92 FileInputStream fileInputStream = new FileInputStream(file); 93 // 用于读取、写入、映射和操作文件的通道。 94 FileChannel fileChannel = fileInputStream.getChannel(); 95 // 编码字符集和字符编码方案的组合,用于处理中文,可以更改 96 Charset charset = Charset.forName("UTF-8"); 97 while (fileChannel.read(byteBuffer) != -1) { 98 // 反转此缓冲区 99 byteBuffer.flip(); 100 CharBuffer charBuffer = charset.decode(byteBuffer); 101 stringBuffer.append(charBuffer.toString()); 102 byteBuffer.clear(); 103 } 104 fileInputStream.close(); 105 } catch (FileNotFoundException e) { 106 e.printStackTrace(); 107 } catch (IOException e) { 108 e.printStackTrace(); 109 } 110 return stringBuffer.toString(); 111 } 112 113 /** 114 * 获取数据列表 115 * @param <T> 116 * @param content 117 * @param num 指定头信息含有多少行 118 * @return 119 */ 120 public static List getList(String content, int num,String start, String end) { 121 122 // 将文本行信息按照行截取 123 String[] strs = content.split("\r\n"); 124 125 if(num>strs.length) { 126 throw new RuntimeException("文本头行数参数不能大于文本总行数!"); 127 } 128 129 // 接收数据,按照行接收 130 List<User> list = new ArrayList<User>(); 131 Integer date; 132 for (int i = num; i < strs.length; i++) { 133 // 将每一行的数据封装到User对象中 134 String[] userParams = strs[i].split("\t\t"); 135 User user = new User(); 136 user.setName(userParams[0]); 137 user.setGener(userParams[1]); 138 user.setIdCard(userParams[2]); 139 user.setAddress(userParams[3]); 140 // 将每一行数据添加到列表中 141 142 // 选择出生日期区间 143 if(start!=null&&!"".equals(start) && end!=null&&!"".equals(end)) { 144 date = Integer.parseInt(user.getIdCard().substring(6, 14)); 145 if(date>= Integer.parseInt(start)&&date<=Integer.parseInt(end) ) { 146 list.add(user); 147 } 148 } 149 } 150 return list; 151 } 152 153 /** 154 * 获取头信息 155 * @param context 指定要获取的文本内容 156 * @param num 指定获前几行 157 * @return 158 */ 159 public static String getHeader(String context, int num) { 160 // 将文本行信息按照行截取 161 String[] strs = context.split("\r\n"); 162 // 接收头信息 163 StringBuffer headStringBuffer = new StringBuffer(); 164 165 for (int i = 0; i < num; i++) { 166 headStringBuffer.append(strs[i]).append("\r\n"); 167 } 168 // 获取头信息 169 return headStringBuffer.toString(); 170 } 171 172 }
javabean封装类:
public class User { private String name; private String gener; private String idCard; private String address; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getGener() { return gener; } public void setGener(String gener) { this.gener = gener; } public String getIdCard() { return idCard; } public void setIdCard(String idCard) { this.idCard = idCard; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } @Override public String toString() { return "User [name=" + name + ", gener=" + gener + ", idCard=" + idCard + ", address=" + address + "]"; } }
javabean比较器:
public class UserComparator implements Comparator<User> { public enum SortType { ASC, DESC } public UserComparator(SortType sortType) { this.sortType = sortType; } private SortType sortType; @Override public int compare(User o1, User o2) { int o1Date = Integer.parseInt(o1.getIdCard().substring(6, 14)); int o2Date = Integer.parseInt(o2.getIdCard().substring(6, 14)); switch (sortType) { case ASC: if (o1Date > o2Date) { return 1; } else if (o1Date < o2Date) { return -1; } break; case DESC: if (o1Date > o2Date) { return -1; } else if (o1Date > o2Date) { return 1; } break; default: break; } return 0; } }
读者们,如果有更好思路和细节处理,欢迎留言讨论,谢谢!