浏览 7023 次
锁定老帖子 主题:JAVA读取文件,排序再写出文件
该帖已经被评为新手帖
|
|
---|---|
作者 | 正文 |
发表时间:2011-01-25
最后修改:2011-01-25
今天在百度知道看到这么一个问题
原问题链接:http://zhidao.baidu.com/question/219278917.html#here 读取TXT文件的格式为:字母 数字 如: TOM 100 JACK 200 BILL 50 CATHY 150 然后按照数字大小排序(由大到小) 输出TXT文件格式为: JACK 200 CATHY 150 TOM 100 BILL 50 问题补充: 最后一行输出平均值=总和/人数 如:平均值=(200+150+100+50)/4=125 输出为一个新生成的TXT文件,不改变原文件 如读取文件为test.txt, 输出文件为text1.txt
觉得蛮有意思的,就动手做了个,大家也和我一起来 1.首先在D盘建了个name.txt文件,里面内容写上
TOM 100 JACK 200 BILL 50 CATHY 150 2.java 读取文件内容
我新建了个FeLongIoTest.class,新建了个读取文件内容通用方法
/** * 读取文件内容 * * @param path * 路径 * @return 文件内容string * @author 金鑫 * @version 3.0 时间:2010年1月23日 14:56:44 */ public static String getFileContent(String path){ File file = new File(path); //分配新的直接字节缓冲区 ByteBuffer byteBuffer = ByteBuffer.allocateDirect(186140); StringBuffer stringBuffer = new StringBuffer(186140); try{ FileInputStream fileInputStream = new FileInputStream(file); //用于读取、写入、映射和操作文件的通道。 FileChannel fileChannel = fileInputStream.getChannel(); //编码字符集和字符编码方案的组合,用于处理中文,可以更改 Charset charset = Charset.forName("GBK"); 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(); } 3.测试下这个方法行不行
@Test public void test(){ String file = "D:/name.txt"; String content = getFileContent(file); System.out.println(content); } 输出:
TOM 100
JACK 200 BILL 50 CATHY 150 ok的,我上面@Test 用了junit4.7, 没用过的你们可以换成main函数
4.数据可以读到了,应为题目中要排序,那么下一步就要把这些数据转换成集合
我这里用到了泛型, 建了一个User 实体类,存放名字和数据
package com.feilong.common.io; /** * 用户 * * @author <a href="mailto:venusdrogon@163.com">金鑫</a> * @version 1.0 2011-1-25 上午10:03:47 */ public class User{ /** * 姓名 */ private String name; /** * 数字 */ private int count; public String getName(){ return name; } public void setName(String name){ this.name = name; } public int getCount(){ return count; } public void setCount(int count){ this.count = count; } } 5.怎么把读到的数据转成list 呢? 这么来
讲解: 使用\r\n 把每行分割成数组
因为题目中要输出最后一句统计的字符串,所以我建了个StringBuilder 装相关数据(这地方别用+直接相连,性能不高)
@Test public void test(){ String file = "D:/name.txt"; String content = getFileContent(file); //将内容以换行符转成数组 String[] rowsContents = content.split("\r\n"); //内容总共行数 int rowCount = rowsContents.length; //总和 int sum = 0; //最后一句话的数字 (200+150+100+50) StringBuilder lastRowOutBuilder = new StringBuilder(); //集合 存储数据,这题最快的方法是用map 存储值,考虑到 扩展(是否姓名有重复,是否以后会增加属性字段) List<User> userList = new ArrayList<User>(); for (int i = 0; i < rowCount; i++){ String rowContent = rowsContents[i]; String[] nameAndCount = rowContent.split(" "); User user = new User(); user.setName(nameAndCount[0]); int count = Integer.parseInt(nameAndCount[1]); user.setCount(count); userList.add(user); sum += count; lastRowOutBuilder.append(count); if (i != rowCount - 1){ lastRowOutBuilder.append("+"); } } } 最后一句话拼接技巧: 循环的最后不加+号
把这个list 可以输出测试下,数据已经进去了
6.这下要到排序了
按照数字大小排序(由大到小)
因为list 本身不能排序的,需要使用Collections.sort,需要list 以及Comparator 两个参数
新建UserComparator 类,实现Comparator 接口
我在类里面增加了 排序枚举SortType,方便扩展(要是那一天改成从小到大,只要参数变一下就可以了)
import java.util.Comparator; /** * user 排序 * * @author <a href="mailto:venusdrogon@163.com">金鑫</a> * @version 1.0 2011-1-25 上午10:48:13 */ public class UserComparator implements Comparator{ /** *排序方式 * * @author <a href="mailto:venusdrogon@163.com">金鑫</a> * @version 1.0 2011-1-25 上午10:59:02 */ public enum SortType{ asc, desc } private SortType sortType; public UserComparator(SortType sortType){ this.sortType = sortType; } /* (non-Javadoc) * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) */ public int compare(Object arg0,Object arg1){ User user0 = (User) arg0; User user1 = (User) arg1; int count0 = user0.getCount(); int count1 = user1.getCount(); switch (sortType) { case asc: if (count0 > count1){ return 1; }else if (count0 < count1){ return -1; } break; case desc: if (count0 > count1){ return -1; }else if (count0 < count1){ return 1; } break; default: break; } return 0; } } 排序调用
Collections.sort(userList, new UserComparator(SortType.desc)); 8.再把排序好了的list 以及最后一句话 拼接成字符串
StringBuilder builder = new StringBuilder(); for (int i = 0; i < userList.size(); i++){ User user = userList.get(i); builder.append(user.getName()); builder.append(" "); builder.append(user.getCount()); builder.append("\r"); } String outString = "平均值=(" + lastRowOutBuilder.toString() + ")/" + rowCount + "=" + sum / rowCount + ""; builder.append(outString); System.out.println(builder.toString());
9.最后到输出到 文件了
我新建了个write 方法
/** * 将字符串写到文件中 * * @param filePath * 文件路径 * @param content * 字符串内容 */ public static void write(String filePath,String content){ try{ //向文本输出流打印对象的格式化表示形式 //会自动创建文件,替换覆盖文字(非追加) PrintWriter printWriter = new PrintWriter(filePath); printWriter.write(content); printWriter.close(); }catch (FileNotFoundException e){ e.printStackTrace(); } } 调用
write("D:/2.txt", builder.toString()); 10. 这段完整代码
@Test public void test(){ String file = "D:/name.txt"; String content = getFileContent(file); //将内容以换行符转成数组 String[] rowsContents = content.split("\r\n"); //内容总共行数 int rowCount = rowsContents.length; //总和 int sum = 0; //最后一句话的数字 (200+150+100+50) StringBuilder lastRowOutBuilder = new StringBuilder(); //集合 存储数据,这题最快的方法是用map 存储值,考虑到 扩展(是否姓名有重复,是否以后会增加属性字段) List<User> userList = new ArrayList<User>(); for (int i = 0; i < rowCount; i++){ String rowContent = rowsContents[i]; String[] nameAndCount = rowContent.split(" "); User user = new User(); user.setName(nameAndCount[0]); int count = Integer.parseInt(nameAndCount[1]); user.setCount(count); userList.add(user); sum += count; lastRowOutBuilder.append(count); if (i != rowCount - 1){ lastRowOutBuilder.append("+"); } } //排序 Collections.sort(userList, new UserComparator(SortType.desc)); StringBuilder builder = new StringBuilder(); for (int i = 0; i < userList.size(); i++){ User user = userList.get(i); builder.append(user.getName()); builder.append(" "); builder.append(user.getCount()); builder.append("\r"); } String outString = "平均值=(" + lastRowOutBuilder.toString() + ")/" + rowCount + "=" + sum / rowCount + ""; builder.append(outString); System.out.println(builder.toString()); write("D:/2.txt", builder.toString()); } 所有的完整代码,我传了附件
这是用纯java自带的类做的,当然有更简单的,比如使用common-io
声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2011-01-25
其实Collections.sort最终用的也是归并,但是不支持文件归并。这题考的应该是算法吧
|
|
返回顶楼 | |
发表时间:2011-01-25
yangyi 写道 其实Collections.sort最终用的也是归并,但是不支持文件归并。这题考的应该是算法吧
yang兄虽然你比较niubility,也不要总是把简单问题复杂化啊。 |
|
返回顶楼 | |
发表时间:2011-01-25
yangguo 写道 yangyi 写道 其实Collections.sort最终用的也是归并,但是不支持文件归并。这题考的应该是算法吧
yang兄虽然你比较niubility,也不要总是把简单问题复杂化啊。 呵呵,这个解决方案肯定是大型机不是分布式,而且是内存特大的那种。还没有用多路归并,多线程,MapReduce。:)) |
|
返回顶楼 | |
发表时间:2011-01-26
简单问题复杂化
|
|
返回顶楼 | |
发表时间:2011-01-26
毛毛k孤鸿 写道 简单问题复杂化
职业病 |
|
返回顶楼 | |
发表时间:2011-01-26
假如考虑到读取文件的大小,如:有100W条记录,那么排序、存入数据库的效率等都需要考虑的!支持楼主的做法
|
|
返回顶楼 | |
发表时间:2011-01-26
finally都不需要写?看来老师教错了
|
|
返回顶楼 | |
发表时间:2011-01-26
并没有用到泛型。
|
|
返回顶楼 | |
发表时间:2011-01-26
飞天奔月 写道
今天在百度知道看到这么一个问题
原问题链接:http://zhidao.baidu.com/question/219278917.html#here 读取TXT文件的格式为:字母 数字 如: TOM 100 JACK 200 BILL 50 CATHY 150 然后按照数字大小排序(由大到小) 输出TXT文件格式为: JACK 200 CATHY 150 TOM 100 BILL 50 问题补充: 最后一行输出平均值=总和/人数 如:平均值=(200+150+100+50)/4=125 输出为一个新生成的TXT文件,不改变原文件 如读取文件为test.txt, 输出文件为text1.txt
觉得蛮有意思的,就动手做了个,大家也和我一起来 1.首先在D盘建了个name.txt文件,里面内容写上
TOM 100 JACK 200 BILL 50 CATHY 150 2.java 读取文件内容
我新建了个FeLongIoTest.class,新建了个读取文件内容通用方法
/** * 读取文件内容 * * @param path * 路径 * @return 文件内容string * @author 金鑫 * @version 3.0 时间:2010年1月23日 14:56:44 */ public static String getFileContent(String path){ File file = new File(path); //分配新的直接字节缓冲区 ByteBuffer byteBuffer = ByteBuffer.allocateDirect(186140); StringBuffer stringBuffer = new StringBuffer(186140); try{ FileInputStream fileInputStream = new FileInputStream(file); //用于读取、写入、映射和操作文件的通道。 FileChannel fileChannel = fileInputStream.getChannel(); //编码字符集和字符编码方案的组合,用于处理中文,可以更改 Charset charset = Charset.forName("GBK"); 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(); } 3.测试下这个方法行不行
@Test public void test(){ String file = "D:/name.txt"; String content = getFileContent(file); System.out.println(content); } 输出:
TOM 100
JACK 200 BILL 50 CATHY 150 ok的,我上面@Test 用了junit4.7, 没用过的你们可以换成main函数
4.数据可以读到了,应为题目中要排序,那么下一步就要把这些数据转换成集合
我这里用到了泛型, 建了一个User 实体类,存放名字和数据
package com.feilong.common.io; /** * 用户 * * @author <a href="mailto:venusdrogon@163.com">金鑫</a> * @version 1.0 2011-1-25 上午10:03:47 */ public class User{ /** * 姓名 */ private String name; /** * 数字 */ private int count; public String getName(){ return name; } public void setName(String name){ this.name = name; } public int getCount(){ return count; } public void setCount(int count){ this.count = count; } } 5.怎么把读到的数据转成list 呢? 这么来
讲解: 使用\r\n 把每行分割成数组
因为题目中要输出最后一句统计的字符串,所以我建了个StringBuilder 装相关数据(这地方别用+直接相连,性能不高)
@Test public void test(){ String file = "D:/name.txt"; String content = getFileContent(file); //将内容以换行符转成数组 String[] rowsContents = content.split("\r\n"); //内容总共行数 int rowCount = rowsContents.length; //总和 int sum = 0; //最后一句话的数字 (200+150+100+50) StringBuilder lastRowOutBuilder = new StringBuilder(); //集合 存储数据,这题最快的方法是用map 存储值,考虑到 扩展(是否姓名有重复,是否以后会增加属性字段) List<User> userList = new ArrayList<User>(); for (int i = 0; i < rowCount; i++){ String rowContent = rowsContents[i]; String[] nameAndCount = rowContent.split(" "); User user = new User(); user.setName(nameAndCount[0]); int count = Integer.parseInt(nameAndCount[1]); user.setCount(count); userList.add(user); sum += count; lastRowOutBuilder.append(count); if (i != rowCount - 1){ lastRowOutBuilder.append("+"); } } } 最后一句话拼接技巧: 循环的最后不加+号
把这个list 可以输出测试下,数据已经进去了
6.这下要到排序了
按照数字大小排序(由大到小)
因为list 本身不能排序的,需要使用Collections.sort,需要list 以及Comparator 两个参数
新建UserComparator 类,实现Comparator 接口
我在类里面增加了 排序枚举SortType,方便扩展(要是那一天改成从小到大,只要参数变一下就可以了)
import java.util.Comparator; /** * user 排序 * * @author <a href="mailto:venusdrogon@163.com">金鑫</a> * @version 1.0 2011-1-25 上午10:48:13 */ public class UserComparator implements Comparator{ /** *排序方式 * * @author <a href="mailto:venusdrogon@163.com">金鑫</a> * @version 1.0 2011-1-25 上午10:59:02 */ public enum SortType{ asc, desc } private SortType sortType; public UserComparator(SortType sortType){ this.sortType = sortType; } /* (non-Javadoc) * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) */ public int compare(Object arg0,Object arg1){ User user0 = (User) arg0; User user1 = (User) arg1; int count0 = user0.getCount(); int count1 = user1.getCount(); switch (sortType) { case asc: if (count0 > count1){ return 1; }else if (count0 < count1){ return -1; } break; case desc: if (count0 > count1){ return -1; }else if (count0 < count1){ return 1; } break; default: break; } return 0; } } 排序调用
Collections.sort(userList, new UserComparator(SortType.desc)); 8.再把排序好了的list 以及最后一句话 拼接成字符串
StringBuilder builder = new StringBuilder(); for (int i = 0; i < userList.size(); i++){ User user = userList.get(i); builder.append(user.getName()); builder.append(" "); builder.append(user.getCount()); builder.append("\r"); } String outString = "平均值=(" + lastRowOutBuilder.toString() + ")/" + rowCount + "=" + sum / rowCount + ""; builder.append(outString); System.out.println(builder.toString());
9.最后到输出到 文件了
我新建了个write 方法
/** * 将字符串写到文件中 * * @param filePath * 文件路径 * @param content * 字符串内容 */ public static void write(String filePath,String content){ try{ //向文本输出流打印对象的格式化表示形式 //会自动创建文件,替换覆盖文字(非追加) PrintWriter printWriter = new PrintWriter(filePath); printWriter.write(content); printWriter.close(); }catch (FileNotFoundException e){ e.printStackTrace(); } } 调用
write("D:/2.txt", builder.toString()); 10. 这段完整代码
@Test public void test(){ String file = "D:/name.txt"; String content = getFileContent(file); //将内容以换行符转成数组 String[] rowsContents = content.split("\r\n"); //内容总共行数 int rowCount = rowsContents.length; //总和 int sum = 0; //最后一句话的数字 (200+150+100+50) StringBuilder lastRowOutBuilder = new StringBuilder(); //集合 存储数据,这题最快的方法是用map 存储值,考虑到 扩展(是否姓名有重复,是否以后会增加属性字段) List<User> userList = new ArrayList<User>(); for (int i = 0; i < rowCount; i++){ String rowContent = rowsContents[i]; String[] nameAndCount = rowContent.split(" "); User user = new User(); user.setName(nameAndCount[0]); int count = Integer.parseInt(nameAndCount[1]); user.setCount(count); userList.add(user); sum += count; lastRowOutBuilder.append(count); if (i != rowCount - 1){ lastRowOutBuilder.append("+"); } } //排序 Collections.sort(userList, new UserComparator(SortType.desc)); StringBuilder builder = new StringBuilder(); for (int i = 0; i < userList.size(); i++){ User user = userList.get(i); builder.append(user.getName()); builder.append(" "); builder.append(user.getCount()); builder.append("\r"); } String outString = "平均值=(" + lastRowOutBuilder.toString() + ")/" + rowCount + "=" + sum / rowCount + ""; builder.append(outString); System.out.println(builder.toString()); write("D:/2.txt", builder.toString()); } 所有的完整代码,我传了附件
这是用纯java自带的类做的,当然有更简单的,比如使用common-io
|
|
返回顶楼 | |