在文件 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
小生想到的就是動態代理和泛型。
具體實現代碼如下(小生這裏沒有采用包裝類了):
package com.hy.demo;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.hy.demo.UserComparator.SortType;
public class DemoTest {
public static void main(String[] args) {
String inpathName = "D:/Workspaces/eclipse-marks-2/hire/src/name_list.txt";
String content = getFileContent(inpathName);
// 得到用戶數據列表
List<User> userList = getList(content, 3,"19950101","19991231");
// 按照出生日期排序用戶列表
String context = orderByUser(userList, SortType.ASC);
// 獲取頭信息
String header = getHeader(content, 3);
String outpathName = "D:/Workspaces/eclipse-marks-2/hire/src/a.txt";
write(header, context, outpathName);
}
public static void write(String header,String context,String outPathName) {
FileOutputStream fos =null;
try {
fos = new FileOutputStream(outPathName);
fos.write(header.getBytes());
fos.write(context.getBytes());
fos.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(fos!=null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 對用戶列表排序,並輸出成文本格式
* @param list
* @param sortType ASC:按照出生日期升序,DESC:按照出生降序
* @return
*/
public static String orderByUser(List<User> list,SortType sortType) {
if(list!=null && list.size()>0) {
Collections.sort(list, new UserComparator(sortType));
StringBuffer sb = new StringBuffer();
for(int i=0;i<list.size();i++) {
User user = list.get(i);
sb.append(user.getName()).append(" \t\t");
sb.append(user.getGener()).append("\t\t");
sb.append(user.getIdCard()).append("\t\t");
sb.append(user.getAddress()).append("\r\n");
}
return sb.toString();
}
return null;
}
/**
* 讀取文本,獲取數據源
*
* @param path
* @return
*/
public static String getFileContent(String path) {
File file = new File(path);
// 分配新的直接字節緩衝區
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(1024);
StringBuffer stringBuffer = new StringBuffer(1024);
try {
FileInputStream fileInputStream = new FileInputStream(file);
// 用於讀取、寫入、映射和操作文件的通道。
FileChannel fileChannel = fileInputStream.getChannel();
// 編碼字符集和字符編碼方案的組合,用於處理中文,可以更改
Charset charset = Charset.forName("UTF-8");
while (fileChannel.read(byteBuffer) != -1) {
// 反轉此緩衝區
byteBuffer.flip();
CharBuffer charBuffer = charset.decode(byteBuffer);
stringBuffer.append(charBuffer.toString());
byteBuffer.clear();
}
fileInputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return stringBuffer.toString();
}
/**
* 獲取數據列表
* @param <T>
* @param content
* @param num 指定頭信息含有多少行
* @return
*/
public static List getList(String content, int num,String start, String end) {
// 將文本行信息按照行截取
String[] strs = content.split("\r\n");
if(num>strs.length) {
throw new RuntimeException("文本頭行數參數不能大於文本總行數!");
}
// 接收數據,按照行接收
List<User> list = new ArrayList<User>();
Integer date;
for (int i = num; i < strs.length; i++) {
// 將每一行的數據封裝到User對象中
String[] userParams = strs[i].split("\t\t");
User user = new User();
user.setName(userParams[0]);
user.setGener(userParams[1]);
user.setIdCard(userParams[2]);
user.setAddress(userParams[3]);
// 將每一行數據添加到列表中
// 選擇出生日期區間
if(start!=null&&!"".equals(start) && end!=null&&!"".equals(end)) {
date = Integer.parseInt(user.getIdCard().substring(6, 14));
if(date>= Integer.parseInt(start)&&date<=Integer.parseInt(end) ) {
list.add(user);
}
}
}
return list;
}
/**
* 獲取頭信息
* @param context 指定要獲取的文本內容
* @param num 指定獲前幾行
* @return
*/
public static String getHeader(String context, int num) {
// 將文本行信息按照行截取
String[] strs = context.split("\r\n");
// 接收頭信息
StringBuffer headStringBuffer = new StringBuffer();
for (int i = 0; i < num; i++) {
headStringBuffer.append(strs[i]).append("\r\n");
}
// 獲取頭信息
return headStringBuffer.toString();
}
}
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;
}
}
如果有更好思路和細節處理,歡迎留言討論,謝謝!