java POI 读写 excel(项目实际需求)

本贴最后更新于 4029 天前,其中的信息可能已经时过境迁

这几天由于工作需要,需要做一个报表比对工具(找出两张报表的差异)。需求如下

1、做一个客户端工具,采用java,可以不用GUI(考虑到,我目前只懂j2ee相关的技术,其实这个需求用python(python版本)来做是最合适的,可是我目前不会,当然后面我会学习下这们语言)

2、两张报表的比队列需要灵活配置,通过配置文件来控制需要比对的列(可以是一列,可以是多列)

3、需要找出表A中有的一条数据,但是表B中没有的。或者表B中有的,表A中没有的。或者表A和表B同时都存在的一条数据,但是里面的某一些字段不一样。

4、两张报表的格式可能不一样,有可能为csv,xls,xlsx。两张报表的列数也是不固定的(这两张报表可以是任意的两张报表)

5、将比对结果再汇总到一张excel中(格式没有要求,我这里默认的是xls)

6、主键可能为复合主键,比对的报表,可能需要一次比对多组报表(由于这个需求,是今天才加上的,所以目前代码还处理这个问题,当然会很快加上)

思路一:

POI1-1

1、采用二维数组为主要的数据结构。因为,报表的列数不确定,所以不能构造对象,采用下标来控制每一列

2、将A表中的第一行的主键,然后搜索表B的主键,如果没搜到记下来,如果搜到了,比较所配置的列看是否相同,如果不同记下来,再反搜,表B中的主键来搜素表A,如果表B中有的,表A中没有的,记下来。

将记下来的数据重组,再导出excel。

效率:两张表都是30多列,52行,大概一秒左右比对完导出到excel中。

思路二

 POI1-2

1、主要采用了循环加map的方式,再比较是否有相等行的时候,直接用,表A的mapA.get(mapB.get("key"))如果数据不为空,说明在表A中有数据和表B匹配,这里的get有效的减少了一次循环。利用了map.get的方法速度更快。其他的。但是主要逻辑,还是如思路相同

接下来贴出,处理这个需求的主要代码。贴出代码的目的,主要是希望各位网友看到后,能够给指点一二,我这代码,肯定还需要优化,重构。或者说换思路。当然你有什么想法,通过评论,或者邮件告诉我。谢谢

ReadCSVExcel方法

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;

import au.com.bytecode.opencsv.CSVReader;

import com.qly.report.operate.facade.IReadExcel;

public class ReadCsvImpl implements IReadExcel{
static String qlyStringArr[][] = new String[1000][1000];
static String otherStringArr[][] = new String[1000][1000];
static Map<String,Integer > qlycontent = new HashMap<String,Integer >();
static Map<String,Integer > othercontent = new HashMap<String,Integer >();

@Override
public Map&lt;String, Object&gt; readExcel(String path, String flag) {
	CSVReader reader = null;
	// 取特定列放到集合
	try {
		InputStream ins = new FileInputStream(new File(path));
		InputStreamReader in = new InputStreamReader(ins, &quot;gbk&quot;);
		reader = new CSVReader(in);
		int len = reader.readNext().length;
		String nextline[];
		int counter = 0;
		// 将不同的来源的csv文件分别存放到不同的二维数组中
		if (&quot;qly&quot;.equals(flag)) {
			Map&lt;String, Object&gt; qlyMap = new HashMap&lt;String, Object&gt;();
			while ((nextline = reader.readNext()) != null) {
				for (int i = 0; i &lt; len; i++) {
					qlyStringArr[counter][i] = nextline[i];
				}
				counter++;
			}
			qlycontent.put(&quot;colNum&quot;, len);
			qlycontent.put(&quot;rowNum&quot;, counter);
			qlyMap.put(&quot;qlyStringArr&quot;, qlyStringArr);
			qlyMap.put(&quot;qlycontent&quot;, qlycontent);
			return qlyMap;
		}

		if (&quot;other&quot;.equals(flag)) {
			Map&lt;String, Object&gt; otherMap = new HashMap&lt;String, Object&gt;();
			while ((nextline = reader.readNext()) != null) {
				for (int i = 0; i &lt; len; i++) {
					otherStringArr[counter][i] = nextline[i];
				}
				counter++;
			}
			othercontent.put(&quot;colNum&quot;, len);
			othercontent.put(&quot;rowNum&quot;, counter);
			otherMap.put(&quot;othercontent&quot;, othercontent);
			otherMap.put(&quot;otherStringArr&quot;, otherStringArr);
			return otherMap;
		}

	} catch (FileNotFoundException e) {
		e.printStackTrace();
	} catch (IOException e) {
		e.printStackTrace();
	} finally {
		try {
			reader.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	return null;
}

}

ReadXlsExcel 方法

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Map;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import com.qly.report.operate.facade.IReadExcel;
import com.qly.report.util.ReportUtil;

public class ReadXlsImpl implements IReadExcel{

public static HSSFWorkbook wb = null;
public static HSSFSheet hssfSheet =null;
public static HSSFRow hssfRow = null;
public static XSSFWorkbook xb = null;
public static XSSFSheet xssfSheet =null;
public static XSSFRow xssfRow =null;
public static String qlyStringArr[][] = new String[1000][1000];
public 	static String otherStringArr[][] = new String[1000][1000];
static Map&lt;String,Integer &gt; qlycontent = new HashMap&lt;String,Integer &gt;();
static Map&lt;String,Integer &gt; othercontent = new HashMap&lt;String,Integer &gt;();
@SuppressWarnings({ &quot;deprecation&quot; })
@Override
public Map&lt;String ,Object&gt; readExcel(String path, String flag) {
	int counter = 0;
	try {
		InputStream is = new FileInputStream(new File(path));

		wb = new HSSFWorkbook(is);
		hssfSheet = wb.getSheetAt(0);
		// 得到总行数
		int rowNum = hssfSheet.getLastRowNum();
		hssfRow = hssfSheet.getRow(1);

		int colNum = hssfRow.getPhysicalNumberOfCells();
		// 正文内容应该从第二行开始,第一行为表头内容
		if(&quot;qly&quot;.equals(flag)){
			Map&lt;String,Object&gt;qlyMap = new HashMap&lt;String, Object&gt;();
			for (int i = 1; i &lt; rowNum; i++) {
				hssfRow = hssfSheet.getRow(i);
				counter = 0;
				while (counter &lt; colNum) {
					qlyStringArr[i][counter] = get2003StringCellValue(
							hssfRow.getCell((short)counter)).trim();
					counter++;
				}
			}
			qlycontent.put(&quot;colNum&quot;, counter);
			qlycontent.put(&quot;rowNum&quot;, rowNum);
			qlyMap.put(&quot;qlyStringArr&quot;, qlyStringArr);
			qlyMap.put(&quot;qlycontent&quot;, qlycontent);
			return  qlyMap;
		}
		if(&quot;other&quot;.equals(flag)){
			Map&lt;String,Object&gt;otherMap = new HashMap&lt;String, Object&gt;();
			for (int i =1; i &lt; rowNum; i++) {
				hssfRow = hssfSheet.getRow(i);
				counter = 0;
				while (counter &lt; colNum) {
					otherStringArr[i][counter] = get2003StringCellValue(hssfRow.getCell((short) counter)).trim();
					
					counter++;
				}
			}
			othercontent.put(&quot;colNum&quot;, counter);
			othercontent.put(&quot;rowNum&quot;, rowNum);
			otherMap.put(&quot;othercontent&quot;, othercontent);
			otherMap.put(&quot;otherStringArr&quot;, otherStringArr);
			return otherMap;
		}


	} catch (FileNotFoundException e) {
		e.printStackTrace();
	} catch (IOException e) {
		e.printStackTrace();
	}	
	return null;
}
private static String get2003StringCellValue(HSSFCell cell) {
	String strCell = &quot;&quot;;
	
	if (null == cell) {
		return &quot;&quot;;
	}
	switch (cell.getCellType()) {
	case HSSFCell.CELL_TYPE_STRING:
		strCell = cell.getStringCellValue();
		break;
	case HSSFCell.CELL_TYPE_NUMERIC:
		//使用DecimalFormat类对科学计数法格式的数字进行格式化
		DecimalFormat df = new DecimalFormat(&quot;#&quot;);
		String str = String.valueOf(cell.getNumericCellValue());
		if(ReportUtil.isNumber(str)){
			strCell =  df.format(cell.getNumericCellValue());
		}else{
			strCell = str;
		}
		
		break;
	case HSSFCell.CELL_TYPE_BOOLEAN:
		
		strCell = String.valueOf(cell.getBooleanCellValue());
		break;
	case HSSFCell.CELL_TYPE_BLANK:
		strCell = &quot;&quot;;
		break;
	default:
		strCell = &quot;&quot;;
		break;
	}
	if (strCell.equals(&quot;&quot;) || null == strCell) {
		return &quot;&quot;;
	}
	return strCell;

}

}

ReadXlsxExcel方法

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Map;

import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import com.qly.report.operate.facade.IReadExcel;
import com.qly.report.util.ReportUtil;

public class ReadXlsxImpl implements IReadExcel {
public static HSSFWorkbook wb = null;
public static HSSFSheet hssfSheet =null;
public static HSSFRow hssfRow = null;
public static XSSFWorkbook xb = null;
public static XSSFSheet xssfSheet =null;
public static XSSFRow xssfRow =null;
public static String qlyStringArr[][] = new String[1000][1000];
public static String otherStringArr[][] = new String[1000][1000];
static Map<String,Integer > qlycontent = new HashMap<String,Integer >();
static Map<String,Integer > othercontent = new HashMap<String,Integer >();
@Override
public Map<String,Object> readExcel(String path, String flag) {
int counter = 0;
try {
InputStream is = new FileInputStream(new File(path));

		xb = new XSSFWorkbook(is);
		xssfSheet = xb.getSheetAt(0);
		// 得到总行数
		int rowNum = xssfSheet.getLastRowNum();
		xssfRow = xssfSheet.getRow(1);

		int colNum = xssfRow.getPhysicalNumberOfCells();
		// 正文内容应该从第二行开始,第一行为表头内容
		if(&quot;qly&quot;.equals(flag)){
			Map&lt;String,Object&gt;qlyMap = new HashMap&lt;String, Object&gt;();
			for (int i = 1; i &lt; rowNum; i++) {
				xssfRow = xssfSheet.getRow(i);
				counter = 0;
				while (counter &lt; colNum) {
					qlyStringArr[i][counter] = get2007StringCellValue(
							xssfRow.getCell((short) counter)).trim();
					counter++;
				}
			}
			qlycontent.put(&quot;colNum&quot;, counter);
			qlycontent.put(&quot;rowNum&quot;, rowNum);
			qlyMap.put(&quot;qlyStringArr&quot;, qlyStringArr);
			qlyMap.put(&quot;qlycontent&quot;, qlycontent);
			return  qlyMap;
		}
		if(&quot;other&quot;.equals(flag)){
			Map&lt;String,Object&gt;otherMap = new HashMap&lt;String, Object&gt;();
			for (int i = 1; i &lt; rowNum; i++) {
				xssfRow = xssfSheet.getRow(i);
				counter = 0;
				while (counter &lt; colNum) {
					otherStringArr[i][counter] = get2007StringCellValue(
							xssfRow.getCell((short) counter)).trim();
					counter++;
				}
			}
			othercontent.put(&quot;colNum&quot;, counter);
			othercontent.put(&quot;rowNum&quot;, rowNum);
			otherMap.put(&quot;othercontent&quot;, othercontent);
			otherMap.put(&quot;otherStringArr&quot;, otherStringArr);
			return otherMap;
		}
		
	} catch (FileNotFoundException e) {
		e.printStackTrace();
	} catch (IOException e) {
		e.printStackTrace();
	}
	return null;
}
private static String get2007StringCellValue(XSSFCell cell) {
	String strCell = &quot;&quot;;
	if (null == cell) {
		return &quot;&quot;;
	}
	switch (cell.getCellType()) {
	case XSSFCell.CELL_TYPE_STRING:
		strCell = cell.getStringCellValue();
		break;
	case XSSFCell.CELL_TYPE_NUMERIC:
		//使用DecimalFormat类对科学计数法格式的数字进行格式化
		
		DecimalFormat df = new DecimalFormat(&quot;#&quot;);
		String str = String.valueOf(cell.getNumericCellValue());
		if(ReportUtil.isNumber(str)){
			strCell =  df.format(cell.getNumericCellValue());
		}else{
			strCell = str;
		}
		
		break;
	case XSSFCell.CELL_TYPE_BOOLEAN:
		strCell = String.valueOf(cell.getBooleanCellValue());
		break;
	case XSSFCell.CELL_TYPE_BLANK:
		strCell = &quot;&quot;;
		break;
	default:
		strCell = &quot;&quot;;
		break;
	}
	if (strCell.equals(&quot;&quot;) || null == strCell) {
		return &quot;&quot;;
	}
	return strCell;

}

}

 

 

CompareExcel方法,比较算法在这里

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.qly.report.operate.facade.ICompareExcel;
import com.qly.report.util.ReportUtil;
/**

  • by guop 2013-7-12 上午 9:11:06

  • 比较 excel
    */
    public class CompareExcelImpl implements ICompareExcel{

    @Override
    public Map<String ,Object> compareExcel(String [][] qlyString, String [][] otherString,
    int[] qlycolumn, int[] othercolumn,
    Map<String,Integer> qlycontent, Map<String,Integer> othercontent,
    int qlyflag, int otherflag, int qlystartRow, int otherstartRow,
    String outReportPath) {

     // 761报表的行数
     int qlyRowNum = qlycontent.get(&quot;rowNum&quot;);
     // 761报表的列数
     int otherRowNum = othercontent.get(&quot;rowNum&quot;);
    
     List&lt;Map&lt;String, Integer&gt;&gt; listErrorStr = new ArrayList&lt;Map&lt;String, Integer&gt;&gt;();
     // 在这里比较下,用a表的标记字段扫描b表从1开始,0为表头
     for (int i = qlystartRow; i &lt; qlyRowNum; i++) {
     	boolean boolflag = false;
     	boolean boolother = true;
     	Map&lt;String, Integer&gt; errorMap = new HashMap&lt;String, Integer&gt;();
    
     	for (int j = otherstartRow; j &lt; otherRowNum; j++) {
     		// 按照配置的标记列,如761中的票号,和腾邦的票号
     		// 表a中的第一行某字段,遍历表b中的行中的这一字段,看是否相同0
     		if (ReportUtil.handleSpecialCharacter(qlyString[i][qlyflag].trim()).equals(ReportUtil.handleSpecialCharacter(otherString[j][otherflag].trim()))) {
     			boolother = false;
     			int rowother = j;
     			// 在寻找到b表中,有相同的字段后,比较其他字段是否相同
     			for (int a1 = 0; a1 &lt; qlycolumn.length;a1++) {
     				if(null == qlyString[i][qlycolumn[a1]] || null == otherString[rowother][othercolumn[a1]]){
     					break;
     				}
    
     				// 当a表和b表中的 票面号相同,比较里面的规定的字段的值是否相同
     					if (!ReportUtil.handleSpecialCharacter(qlyString[i][qlycolumn[a1]].trim()).equals(ReportUtil.handleSpecialCharacter(otherString[rowother][othercolumn[a1]].trim()))) {
     						errorMap.put(&quot;qlylinenumber&quot;, i);
     						errorMap.put(&quot;otherlinenumber&quot;, rowother);
     						listErrorStr.add(errorMap);
     						boolflag = true;
     						break;
     					} 
     				}
    
     			if (boolflag) {
     				break;
     			}
     		}
     	}
     	if (boolother) {
     		errorMap.put(&quot;qlylinenumber&quot;, i);
     		listErrorStr.add(errorMap);
     	}
     }
     //用b表扫描a表的某一个字段
     		// 在这里比较下,用a表的标记字段扫描b表
     for (int i = otherstartRow; i &lt; otherRowNum; i++) {
     	boolean boolother = true;
     	Map&lt;String, Integer&gt; errorMap = new HashMap&lt;String, Integer&gt;();
     	for (int j = qlystartRow; j &lt; qlyRowNum; j++) {
    
     		// 按照配置的标记列,如761中的票号,和腾邦的票号
     		// 表a中的第一行某字段,遍历表b中的行中的这一字段,看是否相同0
     		if (ReportUtil.handleSpecialCharacter(qlyString[j][qlyflag].trim()).equals(ReportUtil.handleSpecialCharacter(otherString[i][otherflag].trim()))) {
     			boolother = false;
     			// 在寻找到b表中,有相同的字段后,比较其他字段是否相同
     		}
     	}
     	if (boolother) {
     		errorMap.put(&quot;otherlinenumber&quot;, i);
     		listErrorStr.add(errorMap);
     	}
     }
    
     Map&lt;String,Object&gt; compareMap = new HashMap&lt;String, Object&gt;();
     compareMap.put(&quot;listErrorStr&quot;, listErrorStr);
    

    return compareMap;
    }

}

全部代码在这里,github,请多多指教

  • POI
    22 引用 • 21 回帖
  • Excel
    30 引用 • 28 回帖
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3169 引用 • 8208 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • someone

    老船长这个不是专栏是博客吧。哈哈。专栏不是这个意思吧。

推荐标签 标签

  • SendCloud

    SendCloud 由搜狐武汉研发中心孵化的项目,是致力于为开发者提供高质量的触发邮件服务的云端邮件发送平台,为开发者提供便利的 API 接口来调用服务,让邮件准确迅速到达用户收件箱并获得强大的追踪数据。

    2 引用 • 8 回帖 • 458 关注
  • 以太坊

    以太坊(Ethereum)并不是一个机构,而是一款能够在区块链上实现智能合约、开源的底层系统。以太坊是一个平台和一种编程语言 Solidity,使开发人员能够建立和发布下一代去中心化应用。 以太坊可以用来编程、分散、担保和交易任何事物:投票、域名、金融交易所、众筹、公司管理、合同和知识产权等等。

    34 引用 • 367 回帖
  • 锤子科技

    锤子科技(Smartisan)成立于 2012 年 5 月,是一家制造移动互联网终端设备的公司,公司的使命是用完美主义的工匠精神,打造用户体验一流的数码消费类产品(智能手机为主),改善人们的生活质量。

    4 引用 • 31 回帖 • 1 关注
  • Hadoop

    Hadoop 是由 Apache 基金会所开发的一个分布式系统基础架构。用户可以在不了解分布式底层细节的情况下,开发分布式程序。充分利用集群的威力进行高速运算和存储。

    86 引用 • 122 回帖 • 620 关注
  • CSDN

    CSDN (Chinese Software Developer Network) 创立于 1999 年,是中国的 IT 社区和服务平台,为中国的软件开发者和 IT 从业者提供知识传播、职业发展、软件开发等全生命周期服务,满足他们在职业发展中学习及共享知识和信息、建立职业发展社交圈、通过软件开发实现技术商业化等刚性需求。

    14 引用 • 155 回帖
  • abitmean

    有点意思就行了

    32 关注
  • 深度学习

    深度学习(Deep Learning)是机器学习的分支,是一种试图使用包含复杂结构或由多重非线性变换构成的多个处理层对数据进行高层抽象的算法。

    46 引用 • 40 回帖
  • Spring

    Spring 是一个开源框架,是于 2003 年兴起的一个轻量级的 Java 开发框架,由 Rod Johnson 在其著作《Expert One-On-One J2EE Development and Design》中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为 JavaEE 应用程序开发提供集成的框架。

    942 引用 • 1459 回帖 • 96 关注
  • GitHub

    GitHub 于 2008 年上线,目前,除了 Git 代码仓库托管及基本的 Web 管理界面以外,还提供了订阅、讨论组、文本渲染、在线文件编辑器、协作图谱(报表)、代码片段分享(Gist)等功能。正因为这些功能所提供的便利,又经过长期的积累,GitHub 的用户活跃度很高,在开源世界里享有深远的声望,并形成了社交化编程文化(Social Coding)。

    208 引用 • 2031 回帖
  • Gzip

    gzip (GNU zip)是 GNU 自由软件的文件压缩程序。我们在 Linux 中经常会用到后缀为 .gz 的文件,它们就是 Gzip 格式的。现今已经成为互联网上使用非常普遍的一种数据压缩格式,或者说一种文件格式。

    9 引用 • 12 回帖 • 129 关注
  • 禅道

    禅道是一款国产的开源项目管理软件,她的核心管理思想基于敏捷方法 scrum,内置了产品管理和项目管理,同时又根据国内研发现状补充了测试管理、计划管理、发布管理、文档管理、事务管理等功能,在一个软件中就可以将软件研发中的需求、任务、bug、用例、计划、发布等要素有序的跟踪管理起来,完整地覆盖了项目管理的核心流程。

    6 引用 • 15 回帖 • 169 关注
  • 安装

    你若安好,便是晴天。

    131 引用 • 1184 回帖 • 2 关注
  • Ant-Design

    Ant Design 是服务于企业级产品的设计体系,基于确定和自然的设计价值观上的模块化解决方案,让设计者和开发者专注于更好的用户体验。

    17 引用 • 23 回帖 • 3 关注
  • Notion

    Notion - The all-in-one workspace for your notes, tasks, wikis, and databases.

    5 引用 • 26 回帖
  • 区块链

    区块链是分布式数据存储、点对点传输、共识机制、加密算法等计算机技术的新型应用模式。所谓共识机制是区块链系统中实现不同节点之间建立信任、获取权益的数学算法 。

    91 引用 • 751 回帖
  • OpenShift

    红帽提供的 PaaS 云,支持多种编程语言,为开发人员提供了更为灵活的框架、存储选择。

    14 引用 • 20 回帖 • 617 关注
  • 友情链接

    确认过眼神后的灵魂连接,站在链在!

    24 引用 • 373 回帖 • 1 关注
  • LaTeX

    LaTeX(音译“拉泰赫”)是一种基于 ΤΕΧ 的排版系统,由美国计算机学家莱斯利·兰伯特(Leslie Lamport)在 20 世纪 80 年代初期开发,利用这种格式,即使使用者没有排版和程序设计的知识也可以充分发挥由 TeX 所提供的强大功能,能在几天,甚至几小时内生成很多具有书籍质量的印刷品。对于生成复杂表格和数学公式,这一点表现得尤为突出。因此它非常适用于生成高印刷质量的科技和数学类文档。

    9 引用 • 32 回帖 • 125 关注
  • Q&A

    提问之前请先看《提问的智慧》,好的问题比好的答案更有价值。

    7271 引用 • 33153 回帖 • 203 关注
  • Ngui

    Ngui 是一个 GUI 的排版显示引擎和跨平台的 GUI 应用程序开发框架,基于
    Node.js / OpenGL。目标是在此基础上开发 GUI 应用程序可拥有开发 WEB 应用般简单与速度同时兼顾 Native 应用程序的性能与体验。

    7 引用 • 9 回帖 • 370 关注
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3169 引用 • 8208 回帖
  • SQLServer

    SQL Server 是由 [微软] 开发和推广的关系数据库管理系统(DBMS),它最初是由 微软、Sybase 和 Ashton-Tate 三家公司共同开发的,并于 1988 年推出了第一个 OS/2 版本。

    19 引用 • 31 回帖
  • 资讯

    资讯是用户因为及时地获得它并利用它而能够在相对短的时间内给自己带来价值的信息,资讯有时效性和地域性。

    54 引用 • 85 回帖
  • iOS

    iOS 是由苹果公司开发的移动操作系统,最早于 2007 年 1 月 9 日的 Macworld 大会上公布这个系统,最初是设计给 iPhone 使用的,后来陆续套用到 iPod touch、iPad 以及 Apple TV 等产品上。iOS 与苹果的 Mac OS X 操作系统一样,属于类 Unix 的商业操作系统。

    84 引用 • 139 回帖 • 2 关注
  • IPFS

    IPFS(InterPlanetary File System,星际文件系统)是永久的、去中心化保存和共享文件的方法,这是一种内容可寻址、版本化、点对点超媒体的分布式协议。请浏览 IPFS 入门笔记了解更多细节。

    20 引用 • 245 回帖 • 249 关注
  • HHKB

    HHKB 是富士通的 Happy Hacking 系列电容键盘。电容键盘即无接点静电电容式键盘(Capacitive Keyboard)。

    5 引用 • 74 回帖 • 445 关注
  • Ubuntu

    Ubuntu(友帮拓、优般图、乌班图)是一个以桌面应用为主的 Linux 操作系统,其名称来自非洲南部祖鲁语或豪萨语的“ubuntu”一词,意思是“人性”、“我的存在是因为大家的存在”,是非洲传统的一种价值观,类似华人社会的“仁爱”思想。Ubuntu 的目标在于为一般用户提供一个最新的、同时又相当稳定的主要由自由软件构建而成的操作系统。

    123 引用 • 168 回帖