论坛首页 入门技术论坛

JAVA读取文件,排序再写出文件

浏览 7023 次
该帖已经被评为新手帖
作者 正文
   发表时间: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
  • io.rar (3.5 KB)
  • 下载次数: 125
   发表时间:2011-01-25  
其实Collections.sort最终用的也是归并,但是不支持文件归并。这题考的应该是算法吧
0 请登录后投票
   发表时间:2011-01-25  
yangyi 写道
其实Collections.sort最终用的也是归并,但是不支持文件归并。这题考的应该是算法吧


yang兄虽然你比较niubility,也不要总是把简单问题复杂化啊。
0 请登录后投票
   发表时间:2011-01-25  
yangguo 写道
yangyi 写道
其实Collections.sort最终用的也是归并,但是不支持文件归并。这题考的应该是算法吧


yang兄虽然你比较niubility,也不要总是把简单问题复杂化啊。


呵呵,这个解决方案肯定是大型机不是分布式,而且是内存特大的那种。还没有用多路归并,多线程,MapReduce。:))
0 请登录后投票
   发表时间:2011-01-26  
简单问题复杂化
0 请登录后投票
   发表时间:2011-01-26  
毛毛k孤鸿 写道
简单问题复杂化



职业病
0 请登录后投票
   发表时间:2011-01-26  
假如考虑到读取文件的大小,如:有100W条记录,那么排序、存入数据库的效率等都需要考虑的!支持楼主的做法
0 请登录后投票
   发表时间:2011-01-26  
finally都不需要写?看来老师教错了
0 请登录后投票
   发表时间:2011-01-26  
并没有用到泛型。
0 请登录后投票
   发表时间: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

 

0 请登录后投票
论坛首页 入门技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics