安卓开发-物理按键监听事件+POI和EasyExcel

本文档详细介绍了在安卓应用中如何监听物理按键,包括返回键、home键等,并提供了不同实现方式的代码示例。同时,对比了Apache POI和阿里巴巴EasyExcel在处理Excel文件时的用法,指出POI适合基础操作但内存消耗大,而EasyExcel简单高效但理解难度较高。文章还涵盖了大文件写入的优化策略以及读取Excel数据时的类型判断和公式计算。
摘要由CSDN通过智能技术生成

安卓开发-物理按键监听事件+POI和EasyExcel

本次项目需要对物理按键进行监听,并且要读取和写入数据到csv文件中,学习的过程中做一点记录,内容包含了安卓中物理按键的监听事件和阿帕奇的POI对excel的操作代码,以及阿里巴巴的EasyExcel对excel的操作代码。相对来说POI较为复杂,但是比较基础,easyExcel一行代码就能搞定文件的读取和写入,但是较为难理解。

监听返回键(🔙)

第一种方法:通过重写onBackPressed方法实现

/**super.onBackPressed()会自动调用finish()方法,关闭当前Activity。
*/
@Override
public void onBackPressed(){
    super.onBackPressed();
    Toast.makeText(this,TAG,Toast.LENGTH_SHORT).show();
}
//onBackPressed()提供的功能优先,它这是再退出之前通知onBackPressed()方法,并布恩那个改变用户原来的行为。

back键
Android的程序无需刻意的去退出,当你一按下手机的back键的时候,系统会默认调用程序栈中最上层Activity的Destroy()方法来, 销毁当前Activity。当此Activity又被其它Activity启动起来的时候,会重新调用OnCreate()方法进行创建,当栈中所有 Activity都弹出结束后,应用也就随之结束了.如果说程序中存在service之类的,则可以在恰当的位置监听处理下也就可以了。

Back按键默认把当前Activity给finish掉,Home按键只是把Activity给onStop掉(destory)。

利用onKeyDown()方法,实现

@Override
public boolean onKeyDown(){
	if(keyCode == keyEvent.KEYCODE_BACK){
        Toast.makeText(this,TAG,Toast.LENGTH_SHORT()).show();
        return false;
    }else{
        return super.onKeyDown(keyCode,event);
    }
}
//onKeyDown方法返回true表示退出,返回false便不退出。

通过跳转来实现退出

@Overide
public boolean onKeyDown(int keyCode,KeyEvent event){
	if(keyCode == KetEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN){
        Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.addCategory(Intent.CATEGORY_HOME);
        startActivity(intent);
    }
    return supper.onKeyDown(keyCode,event);
}

通过onKeyDown实现“再按一次返回退出程序的功能”

private long exitTime = 0;
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
       if(keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN){
             if((System.currentTimeMillis()-exitTime) > 2000){
                    Toast.makeText(getApplicationContext(), "再按一次退出程序", Toast.LENGTH_SHORT).show();
                   exitTime = System.currentTimeMillis();
             } else {
                    finish();
                    System.exit(0);
              }
        return true;
}
 return super.onKeyDown(keyCode, event);
}
	/**
	 * 重写onKeyDown方法可以拦截系统默认的处理
	 */
	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		// TODO Auto-generated method stub
		if (keyCode == KeyEvent.KEYCODE_BACK) {
			Toast.makeText(this, "后退键", Toast.LENGTH_SHORT).show();
			return true;
		} else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
			Toast.makeText(this, "声音+", Toast.LENGTH_SHORT).show();
			return false;
		} else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
			Toast.makeText(this, "声音-", Toast.LENGTH_SHORT).show();
			return false;
		} else if (keyCode == KeyEvent.KEYCODE_VOLUME_MUTE) {
			Toast.makeText(this, "静音", Toast.LENGTH_SHORT).show();
			return false;
		} else if (keyCode == KeyEvent.KEYCODE_HOME) {
			Toast.makeText(this, "Home", Toast.LENGTH_SHORT).show();
			return true;
		}
		return super.onKeyDown(keyCode, event);
	}

注意返回值:如果是true,就会屏蔽掉系统物理按键原来的功能,如果为false,系统原来的功能不会被屏蔽。

implementation ‘joda-time:joda-time:2.11.2’ 日期格式化工具,方便日期的调试

POI和POI-Excel

读跟写:IO相关的知识。使用原生IO进行读写也是可以,但是比较麻烦。

POI:开放式源码函数库,POI提供API给java程序员对Office格式档案读和写的功能。

基本功能:

  1. HSSF:提供读写Excel格式档案的功能 03版 65535行
  2. XSSF:提供读写Excel OOXML格式档案的功能。 07版 不限制行数
  3. HWPF:提供读写Word格式档案的功能。
  4. HSLF:提供PPT读写的功能。
  5. HDGF:提供Viso格式档案的功能。

POI相对有点麻烦。量比较大的时候可能会出现异常。

内存:POI会一次性先加载到内存,再写入到文件。如果数据较大,就会产生内存溢出。

java:万物皆对象

excel中的对象:

  1. 工作簿:
  2. 工作表:
  3. 行:
  4. 列:
public void testWrite03(){
    //创建一个工作簿
    Workbook workbook = new HSSFWorkbook();
    //创建一个工作表
    Sheet sheet = workbook.creatSheet("狂神观众统计表");
    //创建一行
    Row row = sheet.creatRow(0);
    //创建单元格(列)
    Cell cell = row.createCell(0);
    cell.setCellValue("今日新增观众");
    
    Cell cell1 = row.createCell(1);
    cell1.setCellValue(666);
    
    //构建流生成一张表 03版本就是使用xls结尾
    FileOutptStream fileOutputStream = new FileOutputStream(PATH + "狂神观众统计表.xls");
    workbook.write(fileOutputStream);
    fileOutputStream.close();
    System.out.println("EXCEL生成完毕!");
}

public void testWrite07(){
    //创建一个工作簿
    Workbook workbook = new XSSFWorkbook();
    //创建一个工作表
    Sheet sheet = workbook.creatSheet("狂神观众统计表");
    //创建一行
    Row row = sheet.creatRow(0);
    //创建单元格(列)
    Cell cell = row.createCell(0);
    cell.setCellValue("今日新增观众");
    
    Cell cell1 = row.createCell(1);
    cell1.setCellValue(666);
    
    //构建流生成一张表 07版本就是使用xlsx结尾
    FileOutptStream fileOutputStream = new FileOutputStream(PATH + "狂神观众统计表.xlsx");
    workbook.write(fileOutputStream);
    fileOutputStream.close();
    System.out.println("EXCEL生成完毕!");
}

大文件写入HSSF

使用03版的只能处理65535行。HSSF

使用07版的能处理的数据量不限,但是如果数据过大就会影响性能,所以需要使用加速的功能。XSSF

测试07版大文件写入代码如下(包含加速处理功能)

public void testWrite03BigData(){
    Long begin = System.currentTimeMills();
    //创建一个工作簿
    Workbook workbook = new HSSFWorkbok();
    //创建一张表
    Sheet sheet = woorkbook.createSheet();
    //写入数据
    for(int rowNum = 0; i < 65536; i ++){
        Row row = sheet.createRow(rowNum);
        for(int cellNum = 0 ; cellNum < 10; cellNum++){
            Cell cell = row.createCell(cellNum);
            cell.setCellVlaue(cellNum);
        }
    }
    System.out.println("done!");
    
    FileOutputStream fileOutStream = new FilOutputStream(PATH + testWrite03BigData.xls);
    
    workbook.write(fileOutputStream);
    fileOutputStream.close();
    Long end = System.currentTimeMills();
    
    System.out.println((double)(end - begin) / 1000);
}

如果超过65535行就会报错!

07版本的就可以处理超过65535行的数据,但是效率比较底下

public void testWrite7BigData(){
    Long begin = System.currentTimeMills();
    //创建一个工作簿
    Workbook workbook = new XSSFWorkbok();
    //创建一张表
    Sheet sheet = woorkbook.createSheet();
    //写入数据
    for(int rowNum = 0; i < 65536; i ++){
        Row row = sheet.createRow(rowNum);
        for(int cellNum = 0 ; cellNum < 10; cellNum++){
            Cell cell = row.createCell(cellNum);
            cell.setCellVlaue(cellNum);
        }
    }
    System.out.println("done!");
    
    FileOutputStream fileOutStream = new FilOutputStream(PATH + testWrite07BigData.xlsx);
    
    workbook.write(fileOutputStream);
    fileOutputStream.close();
    Long end = System.currentTimeMills();
    
    System.out.println((double)(end - begin) / 1000);
}

通过计算03的输出65535行数据耗时1.35s,07版耗时7.65s;

大文件写SXXSSF:可以写非常大的数据量,如100万条甚至更多条,写数据速度快,占用更少内存。

注意中间会产生临时文件,需要清理临时文件。

默认由100条记录被保存在内存中,如果超过这个数量,则最前面的数据被写入临时文件。

如果像自定义内存中的数据的数量,可以使用new SXSSFWorlbool(数量);

public void testWrite7BigDataS(){
    Long begin = System.currentTimeMills();
    //创建一个工作簿
    Workbook workbook = new SXSSFWorkbok();
    //创建一张表
    Sheet sheet = woorkbook.createSheet();
    //写入数据
    for(int rowNum = 0; i < 65536; i ++){
        Row row = sheet.createRow(rowNum);
        for(int cellNum = 0 ; cellNum < 10; cellNum++){
            Cell cell = row.createCell(cellNum);
            cell.setCellVlaue(cellNum);
        }
    }
    System.out.println("done!");
    
    FileOutputStream fileOutStream = new FilOutputStream(PATH + testWrite07BigDataS.xlsx);
    workbook.write(fileOutputStream);
    //清除临时文件
    ((SXSSFWorkbook)workbook).dispose();
    fileOutputStream.close();
    Long end = System.currentTimeMills();
    
    System.out.println((double)(end - begin) / 1000);
}

需要注意内存消耗情况。

POI-读数据-03版

//读测试
public void testRead03() throws Exception{
    //1,创建一个工作簿,使用EXCEL能操作的这边都可以操作
    //获取文件流
    FileInputStream fileInputStream - new FileInputStream(PATH + "狂神观众统计表.xls");
    Workbook workbook = new HSSFWorkbok(fileInputStream);
	//通过下标或者表名获取表格
    workbook.getSheetAt(0);
    //得到一列
    Row row = sheetgetRow(0);
    //得到一个单元格
    Cell cell = row.getCell(0);
    //cell.getValue():获取的是一个字符串
    System.out.println(cell.getValue());
    //获取的是一个数字
    System.out.println(cell.getNumericCellValue());
    fileInputStream.close();
    //读取值的时候一定要注意类型。
}

POI-读数据-07版

//读测试
public void testRead07() throws Exception{
    //1,创建一个工作簿,使用EXCEL能操作的这边都可以操作
    //获取文件流
    FileInputStream fileInputStream - new FileInputStream(PATH + "狂神观众统计表.xlsx");
    Workbook workbook = new XSSFWorkbok(fileInputStream);
	//通过下标或者表名获取表格
    workbook.getSheetAt(0);
    //得到一列
    Row row = sheetgetRow(0);
    //得到一个单元格
    Cell cell = row.getCell(0);
    //cell.getValue():获取的是一个字符串
    System.out.println(cell.getValue());
    //获取的是一个数字
    System.out.println(cell.getNumericCellValue());
    fileInputStream.close();
    //读取值的时候一定要注意类型。
}

如何获取不同的数据类型**(最麻烦的地方!)**

public void testCellType() throws Exception{
    //获取文件流
    FileInputStream inputStream = new FileInputStream(Path + "wenjianming.xls");
    //创建一个工作簿。:如果是07的版本记得换成相应的类
    Workbook workbook = new HSSFWorkbook(inputStream);
    Sheet sheet = workbook.getSheetAt(0);
    //获取标题内容
    Row rowTitle = sheet.getRow(0);
    if(rowTitle != null){
        int cellCount = rowTtile.getPhysicalNumberOfCells();
        for(int cellNum = 0; cellNum < cellCount; cellNum++){
            Cell cell = rowTitle.getCell(cellNum);
            if(cell != null){
                int cellType = cell.getCellType();
                String cellValue = cell.getStringCellVlaue();
                System.out.print(cellValue + "|");
            }
        }
        System.ut.println();
    }
    //获取表中的内容
    int rowCount = sheet.getPhysicalNumberOfRows();
    for(int rowNum = 1; rowNum < rowCount ;rowNum++){
        Row rowData = sheet.getRow(rowNum);
        if(rowData != null){
            //读取列
            int cellCount = rowTitle.getPhysicalNumberOfCells();
           for(int cellNum = 0; cellNum < celloumt; cellNum ++){
               System.out.print("["+(rowNum+1)+"-" + (cellNum+1)+"]");
               Cell cell = rowData.getCell(cellNum);
               //匹配列的数据类型
               if(cell 1= null){
                   int cellType = cell.getCellType();
                   String cellValue = "";
                   
                   switch(cellType){
                       case hssfcell.CELLTYPE_STRING:		//字符串类型
                           System.out.pprintln("[String类型!]");
                           cellValue = cell.getStringCellValue();
                           bresk;
                       case: hssfcell.CELLTYPE_TYPE_BOOLEAN:		//布尔类型
                           cellValue = String.valueOf(cell.getBooleanCellValue());
                           break;
                       case hssfcell.CELLTYPE_TYPE_BLANK:
                           break;
                       case hssfcell.CELLTYPE_TYPE_NUMEIC:
                           if(HSSFDataUtil.isCellDataFormatted(cell)){
                               //日期
                               Date date = cell.getDateCellValue();
                               cellValue = new DateTime(data).toString("yyyy-MM-dd");
                           }else{
                               //普通的数字,转换为字符串输出即可,不是日期格式,防止数字过长转换成字符串类型。
                               cell.setCellType(HSSFCell.CELL_TYPE_STRING);
                               cellValue = cell.toString();
                           }
                           break;
                       case HSSFCell.CELL_TYPE_ERROR:
                           break;
                   }
                   System.out.println("done");
               }               
           }
        }
    }
    inputStream.close();
}

计算公式

读取公式并计算

public void testFunction(){
    FileInputStream inputStream = new FileInputStream(PATH + "文件名");
    HSSFWorkbook  workbook = new HSSFWorkbook(inputStream);
    Sheet sheet = workbook.getSheetAt(0);
    Row row = sheet.getRow(4);
    Cell cell = row.getCell(0);
    //拿到计算公式
    FormulaEvaluator forMulaEvaluator = new HSSFFormulaEvaluator((HSSFWorkbook)workbook);
    //输出单元格的内容
    cell.getType = cell.getCellType();
    switch(cellType){
        case Cell.CELL_TYPE_FORMULA:	//公式
            String formula = cell.getCellFormula();
            System.out.println(formula);
            //计算
            CellValue evaluate = FormulaEvaluator.evaluate(cell);
            String cellValue = evaluate.formatAsString();
            //输出结果
            System.out.println(cellVlaue);
    }
}

EasyExcel

阿里巴巴开源的系统,做了优化,所以比较方便简洁。

public static void CsvToXlsx(String oripath, String despath, String sheet) 
{		
	ExcelWriter excelWriter = null;
    File destFile = new File(despath);
    File oriFile = new File(oripath);
    File transFile = new File(destFile.getParent(),"trans.xlsx");
    try {
        if (destFile.exists()) 
        {
        	//创建中转文件
            //追加数据,中转文件与目标文件不能是同一个文件名
            //withTemplate()指定模板文件,即复制一份; file() 中间文件名; autoCloseStream() 必须为True,自动关闭输入流     	
            excelWriter = EasyExcel.write().withTemplate(destFile)
                    //.file() 指定目标文件,不能与模板文件是同一个文件
                    .file(transFile).autoCloseStream(true).build(); //
        } 
        else 
        {
            excelWriter = EasyExcel.write(destFile).build();
        }
        WriteSheet writeSheet = EasyExcel.writerSheet(sheet).needHead(false).build();

        List<Map<Integer,Object>> list = importdata(oriFile); //返回的数据全部都是String类型的
        
        //将列表中值为数字的字符串转化为Double型
        Pattern pattern = Pattern.compile("-?[0-9]+.?[0-9]*");
        for(int i=0;i<list.size();i++)
        {
        	Map<Integer, Object> map = list.get(i);
        	for(int j=0;j<map.size();j++)
        	{
        		if(map.get(j)==null)continue;
        		String value = map.get(j).toString();
        		if(pattern.matcher(value).matches())
        		{
        			map.put(j, Double.parseDouble(value));
        		}
        		else
        		{
        			map.put(j, value);
        		}
        	}
        	list.set(i, map);
        }
        
        excelWriter.write(list, writeSheet);
    } 
    finally 
    {
    	
    	if (excelWriter != null)
    	{
    		excelWriter.finish();
    	}
    }
    
    if (transFile.exists()) 
    {
        //删除原文件
    	destFile.delete();	
        boolean result = transFile.renameTo(destFile);
        if(result)System.out.println("改名成功");
        else System.out.println("改名失败");
    }					
}

//导入数据
public static List<Map<Integer,Object>> importdata(File file) 
{		
	List<Map<Integer,Object>> list = new LinkedList<>();
	
	EasyExcel.read(file)
			.excelType(ExcelTypeEnum.CSV) //如果原始为.xlsx文件则改成.XLSX
			.sheet()
			.registerReadListener(new AnalysisEventListener<Map<Integer,Object>>() {

				@Override
				public void invoke(Map<Integer, Object> integerStringMap, AnalysisContext analysisContext) {
					// TODO Auto-generated method stub
					list.add(integerStringMap);
				}

				@Override
				public void doAfterAllAnalysed(AnalysisContext context) {
					// TODO Auto-generated method stub
					System.out.println("数据读取完毕");
				}
			}).headRowNumber(0).doRead();
	return list;
}

小结-学习方式

了解面向对象的思想,学会面向接口编程。理解使用测试API。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

NoSuchManException

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值