HBase中关于中文的处理
1、HBase版本hbase-0.20.5,Hadoop的版本hadoop-0.20.2,JDK1.6
2、在HBase中创建了表,如果想通过控制台使用命令写入含有汉字的数据,录入是不成功的。
3、如果想对汉字进行录入,可以通过代码实现,这里我使用的是java,代码如下:
/**
* 向指定的表插入单个Put对象
*
* @param tablename
* @param conf
* @throws Exception
*/
public static void insertData(String tableName, HBaseConfiguration conf) {
HTable table = null;
try {
if (table == null) {
table = new HTable(conf, tableName);
}
// 这里我使用time+6位随机数为row关键字,确保不重复
String rowname = System.currentTimeMillis() / 1000 + "" + CommUtil.getSixRadom();
System.out.println("rowname = " + rowname);
Put p = new Put(Bytes.toBytes(rowname));
p.add("acc".getBytes(), new Long(System.currentTimeMillis()).longValue(), "大绝招".getBytes());
p.add("pwd".getBytes(), new Long(System.currentTimeMillis()).longValue(), "123456".getBytes());
p.add("sex".getBytes(), new Long(System.currentTimeMillis()).longValue(), "1".getBytes());
p.add("age".getBytes(), new Long(System.currentTimeMillis()).longValue(), "2222".getBytes());
table.put(p);
} catch (Exception e) {
e.printStackTrace();
} finally {
CommUtil.HBaseClose(table);
}
}
4、通过查询可以查找出汉字内容,代码如下:
/**
* 扫描HBase数据内容
*
* @param tablename
* @param conf
* @param table
*/
public static void scanData(String tableName, HBaseConfiguration conf) {
HTable table = null;
Scan s = null;
ResultScanner scanner = null;
try {
if (table == null) {
table = new HTable(conf, tableName);
}
s = new Scan();
s.addColumn(Bytes.toBytes("acc"));
scanner = table.getScanner(s);
for (Result r = scanner.next(); r != null; r = scanner.next()) {
byte[] value = r.getValue("acc".getBytes());
String m = new String(value);
System.out.println("Found row: " + m);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
scanner.close();
}
}
5、结果返回正常的汉字,这里指的是在windows环境下,eclipse控制台输出的是汉字。如果是在linux下先在控制台输出汉字,则和操作系统的编码格式有关系。
6、通过上面的步骤可以看出来,输入是通过代码循环录入,当然,上面我只是录入的一条数据内容。如果想把文件内容作为数据的输入,那么需要把代码修改,并打成jar包在linux上执行。这里涉及到了在hbase中采用MR代码来录入数据。至于如何配置,我会另外写一片文章来简单概述一下,这里我就默认已配置完成。
7、编写MR代码,读取文件数据,并录入到hbase表中,代码如下:
public class InsertDataToHBase {
public static class InsertDataToHBaseMapper extends Mapper<Object, Text, NullContext, NullWritable> {
public static String table1[] = { "field1", "field2", "field3"};
public static String table2[] = { "field1", "field2", "field3"};
public static String table3[] = { "field1", "field2", "field3"};
public static HTable table = null;
protected void setup(Context context) throws IOException, InterruptedException {
HBaseConfiguration conf = new HBaseConfiguration();
String table_name = context.getConfiguration().get("tabel_name");
if (table == null) {
table = new HTable(conf, table_name);
}
}
public void map(Object key, Text value, Context context) throws IOException, InterruptedException {
String arr_value[] = value.toString().split("\t");
String table_name = context.getConfiguration().get("tabel_name");
String temp_arr[] = table1;
int temp_value_length = 0;
if (table_name.trim().equals("table1")) {
temp_arr = table1;
temp_value_length = 3;
} else if (table_name.trim().equals("table2")) {
temp_arr = table2;
temp_value_length = 3;
} else if (table_name.trim().equals("table3")) {
temp_arr = table3;
temp_value_length = 3;
}
List<Put> list = new ArrayList<Put>();
if (arr_value.length == temp_value_length) {
String rowname = System.currentTimeMillis() / 1000 + "" + CommUtil.getSixRadom();
Put p = new Put(Bytes.toBytes(rowname));
for (int i = 0; i < temp_arr.length; i++) {
p.add(temp_arr[i].getBytes(), "".getBytes(), arr_value[i].getBytes());
}
list.add(p);
}
table.put(list);
table.flushCommits();
}
}
public static void main(String[] args) throws Exception {
Configuration conf = new Configuration();
String[] otherArgs = new GenericOptionsParser(conf, args).getRemainingArgs();
if (otherArgs.length != 3) {
System.err.println("Usage: InsertDataToHBase <inpath> <outpath> <tablename>");
System.exit(2);
}
conf.set("tabel_name", otherArgs[2]);
Job job = new Job(conf, "InsertDataToHBase");
job.setNumReduceTasks(0);
job.setJarByClass(InsertDataToHBase.class);
job.setMapperClass(InsertDataToHBaseMapper.class);
FileInputFormat.addInputPath(job, new Path(otherArgs[0]));
FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));
// job.submit();
System.exit(job.waitForCompletion(true) ? 0 : 1);
}
}
8、对于数据文件,如果有汉字,要求是UTF-8的编码格式,这样,在通过代码读取数据内容的时候才能显示成中文。这里有个地方需要注意一下,如果数据文件是在windows上,那么你通过另存为转成UTF-8的编码格式,汉字会有3个位的头,如果是这样的数据录入,查询出来之后,汉字的头前会显示一个“?”,这个是由于windows编码格式和Linux不同所致。处理这样的问题可以将文件拷贝到Linux下,做如下操作:
iconv -f GBK -t UTF-8 gbk.txt -o utf8.bcp
另外需要注意的是,如果文件后缀是txt,那么你即使转换之后,在windows再次打开,系统也会默认给你增加3个位的头。所以建议数据文件不要以txt后缀命名。
9、汉字录入HBase之后,使用命令查看显示如下:
1279677870714210 column=acc:, timestamp=1279677870656, value=\xB4\xF3\xBE\xF8\xD5\xD0
可以看到是ASCII编码,可以将这些内容拷贝到UE,以16进制查看,然后对应的修改,可以看到最终显示是汉字“大绝招”
10、总结一下,内容写的比较少,代码贴了一些,大家看看,如果觉得有写的不对的或是有疑问的地方,可以给我发邮件dajuezhao@gmail.com