本文地址:http://www.cnblogs.com/archimedes/p/hadoop-writable-class.html,转载请注明源地址。

hadoop中自带的org.apache.hadoop.io包中有广泛的writable类可供选择,它们形成下图所示的层次结构:

java基本类型的Writable封装器

Writable类对java基本类型提供封装,short和char除外,所有的封装包含get()和set()两个方法用于读取或设置封装的值

java基本类型的Writable类

java原生类型

除char类型以外,所有的原生类型都有对应的Writable类,并且通过get和set方法可以他们的值。IntWritable和LongWritable还有对应的变长VIntWritable和VLongWritable类。固定长度还是变长的选用类似与数据库中的char或者vchar,在这里就不赘述了。

Text类型

Text类型使用变长int型存储长度,所以Text类型的最大存储为2G.

Text类型采用标准的utf-8编码,所以与其他文本工具可以非常好的交互,但要注意的是,这样的话就和java的String类型差别就很多了。

检索的不同

Text的chatAt返回的是一个整型,及utf-8编码后的数字,而不是象String那样的unicode编码的char类型。

public void testTextIndex(){
Text text=new Text("hadoop");
Assert.assertEquals(text.getLength(), 6);
Assert.assertEquals(text.getBytes().length, 6);
Assert.assertEquals(text.charAt(2),(int)'d');
Assert.assertEquals("Out of bounds",text.charAt(100),-1);
}

Text还有个find方法,类似String里indexOf方法:

public void testTextFind() {
Text text = new Text("hadoop");
Assert.assertEquals("find a substring",text.find("do"),2);
Assert.assertEquals("Find first 'o'",text.find("o"),3);
Assert.assertEquals("Find 'o' from position 4 or later",text.find("o",4),4);
Assert.assertEquals("No match",text.find("pig"),-1);
}

Unicode的不同

当uft-8编码后的字节大于两个时,Text和String的区别就会更清晰,因为String是按照unicode的char计算,而Text是按照字节计算。我们来看下1到4个字节的不同的unicode字符

4个unicode分别占用1到4个字节,u+10400在java的unicode字符重占用两个char,前三个字符分别占用1个char.

我们通过代码来看下String和Text的不同

import java.io.*;
import org.apache.hadoop.io.*;
import org.apache.hadoop.util.StringUtils;
import junit.framework.Assert;
public class textandstring {
public static void string() throws UnsupportedEncodingException {
String str = "\u0041\u00DF\u6771\uD801\uDC00";
Assert.assertEquals(str.length(), 5);
Assert.assertEquals(str.getBytes("UTF-8").length, 10); Assert.assertEquals(str.indexOf("\u0041"), 0);
Assert.assertEquals(str.indexOf("\u00DF"), 1);
Assert.assertEquals(str.indexOf("\u6771"), 2);
Assert.assertEquals(str.indexOf("\uD801\uDC00"), 3); Assert.assertEquals(str.charAt(0), '\u0041');
Assert.assertEquals(str.charAt(1), '\u00DF');
Assert.assertEquals(str.charAt(2), '\u6771');
Assert.assertEquals(str.charAt(3), '\uD801');
Assert.assertEquals(str.charAt(4), '\uDC00'); Assert.assertEquals(str.codePointAt(0), 0x0041);
Assert.assertEquals(str.codePointAt(1), 0x00DF);
Assert.assertEquals(str.codePointAt(2), 0x6771);
Assert.assertEquals(str.codePointAt(3), 0x10400);
} public static void text() {
Text text = new Text("\u0041\u00DF\u6771\uD801\uDC00");
Assert.assertEquals(text.getLength(), 10); Assert.assertEquals(text.find("\u0041"), 0);
Assert.assertEquals(text.find("\u00DF"), 1);
Assert.assertEquals(text.find("\u6771"), 3);
Assert.assertEquals(text.find("\uD801\uDC00"), 6); Assert.assertEquals(text.charAt(0), 0x0041);
Assert.assertEquals(text.charAt(1), 0x00DF);
Assert.assertEquals(text.charAt(3), 0x6771);
Assert.assertEquals(text.charAt(6), 0x10400);
}
public static void main(String[] args) {
// TODO Auto-generated method stub
text();
try {
string();
} catch(UnsupportedEncodingException ex) { }
}
}

这样一比较就很明显了。

1.String的length()方法返回的是char的数量,Text的getLength()方法返回的是字节的数量。

2.String的indexOf()方法返回的是以char为单元的偏移量,Text的find()方法返回的是以字节为单位的偏移量。

3.String的charAt()方法不是返回的整个unicode字符,而是返回的是java中的char字符

4.String的codePointAt()和Text的charAt方法比较类似,不过要注意,前者是按char的偏移量,后者是字节的偏移量

Text的迭代

在Text中对unicode字符的迭代是相当复杂的,因为与unicode所占的字节数有关,不能简单的使用index的增长来确定。首先要把Text对象转换为java.nio.ByteBuffer对象,然后再利用缓冲区对Text对象反复调用bytesToCodePoint方法,该方法能获取下一代码的位置,并返回相应的int值,最后更新缓冲区中的位置。通过bytesToCodePoint()方法可以检测出字符串的末尾,并返回-1值。看一下示例代码:

import java.io.*;
import java.nio.ByteBuffer;
import org.apache.hadoop.io.*;
import org.apache.hadoop.util.StringUtils;
import junit.framework.Assert;
public class textandstring {
public static void main(String[] args) {
// TODO Auto-generated method stub
Text t = new Text("\u0041\u00DF\u6771\uD801\uDC00");
ByteBuffer buf = ByteBuffer.wrap(t.getBytes(), 0, t.getLength());
int cp;
while(buf.hasRemaining() && (cp = Text.bytesToCodePoint(buf)) != -1) {
System.out.println(Integer.toHexString(cp));
}
}
}

运行结果:

41
df
6771
10400

Text的修改

除了NullWritable是不可更改外,其他类型的Writable都是可以修改的。你可以通过Text的set方法去修改去修改重用这个实例。
public void testTextMutability() {
Text text = new Text("hadoop");
text.set("pig");
Assert.assertEquals(text.getLength(), 3);
Assert.assertEquals(text.getBytes().length, 3);
}

注意:在某些情况下,getBytes()方法返回的字节数组可能比getLength()函数返回的长度更长:

import java.io.*;
import java.nio.ByteBuffer;
import org.apache.hadoop.io.*;
import org.apache.hadoop.util.StringUtils;
import junit.framework.Assert;
public class textandstring {
public static void main(String[] args) {
// TODO Auto-generated method stub
Text t = new Text("hadoop");
t.set(new Text("pig"));
Assert.assertEquals(t.getLength(), 3);
Assert.assertEquals(t.getBytes().length, 6);
}
}

Text类并不像String类那样有丰富的字符串操作API,所以多数情况下,需要将Text对象转换成String对象。这一转换过程通过调用ToString()方法来实现

hadoop中的序列化与Writable类的更多相关文章

  1. hadoop中的序列化与Writable接口

    本文地址:http://www.cnblogs.com/archimedes/p/hadoop-writable-interface.html,转载请注明源地址. 简介 序列化和反序列化就是结构化对象 ...

  2. 1 weekend110的复习 + hadoop中的序列化机制 + 流量求和mr程序开发

    以上是,weekend110的yarn的job提交流程源码分析的复习总结 下面呢,来讲weekend110的hadoop中的序列化机制 1363157985066      13726230503  ...

  3. 一脸懵逼学习Hadoop中的序列化机制——流量求和统计MapReduce的程序开发案例——流量求和统计排序

    一:序列化概念 序列化(Serialization)是指把结构化对象转化为字节流.反序列化(Deserialization)是序列化的逆过程.即把字节流转回结构化对象.Java序列化(java.io. ...

  4. hadoop中的序列化

    此文已由作者肖凡授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 最近在学习hadoop,发现hadoop的序列化过程和jdk的序列化有很大的区别,下面就来说说这两者的区别都有 ...

  5. 实战Hadoop中遇到的几个类、接口说明

    1. Configuration :public 类型接口,这个接口包含的多数方法是进行与数据属性<key,value>有关的操作. 几个方法: 1)addProperty(String ...

  6. Hadoop序列化与Writable接口(一)

    Hadoop序列化与Writable接口(一) 序列化 序列化(serialization)是指将结构化的对象转化为字节流,以便在网络上传输或者写入到硬盘进行永久存储:相对的反序列化(deserial ...

  7. Hadoop中Writable类之四

    1.定制Writable类型 Hadoop中有一套Writable实现,例如:IntWritable.Text等,但是,有时候可能并不能满足自己的需求,这个时候,就需要自己定制Writable类型. ...

  8. Hadoop中Writable类之三

    1.BytesWritable <1>定义 ByteWritable是对二进制数据组的封装.它的序列化格式为一个用于指定后面数据字节数的整数域(4个字节),后跟字节本身. 举个例子,假如有 ...

  9. hadoop中典型Writable类详解

    本文地址:http://www.cnblogs.com/archimedes/p/hadoop-writable.html,转载请注明源地址. Hadoop将很多Writable类归入org.apac ...

随机推荐

  1. 使用log4j输出日志

    今天在倒腾log4j,其实蛮简单的. 一.首先是下载log4j的jar包. 二.将下载的jar包添加到web工程的WEB-INF/lib包下 三.在src/config包下新建log4j.proper ...

  2. Python基础篇:从0开始学python

    目录 数据类型 基本数据类型 整形Int的内置方法 字符串Str的内置方法 列表(待补充) 流程控制 分支结构if...else... for循环 循环控制 while循环 函数 函数的名称与格式 参 ...

  3. 【最小生成树】BZOJ1682[Usaco2005 Mar]-Out of Hay 干草危机

    ...最小生成树裸题,9月最后一天刷水刷水. #include<iostream> #include<cstdio> #include<algorithm> usi ...

  4. 使用openssl生成双向加密证书(转)

    要生成证书的目录下建立几个文件和文件夹,有./demoCA/./demoCA/newcerts/./demoCA/private/./demoCA/index.txt (空文件,生成证书时会将数据记录 ...

  5. CROC 2016 - Elimination Round (Rated Unofficial Edition) B. Mischievous Mess Makers 贪心

    B. Mischievous Mess Makers 题目连接: http://www.codeforces.com/contest/655/problem/B Description It is a ...

  6. 一步一步创建JAVA线程

    (一)创建线程 要想明白线程机制,我们先从一些基本内容的概念下手. 线程和进程是两个完全不同的概念,进程是运行在自己的地址空间内的自包容的程序,而线程是在进程中的一个单一的顺序控制流,因此,单个进程可 ...

  7. MYSQL学习笔记 (三)JOIN用法

    数据库的操作分开增删改查,其中查询操作基本占系统的90%,大家所说的优化SQL语句基本是优化查询语句.接下来将学习JOIN的用法,JOIN包括:INNER JOIN(内连接).LEFT JOIN(左外 ...

  8. Bipolar transistor boosts switcher's current by 12 times

    The circuit in Figure 1 uses a minimal number of external parts to raise the maximum output current ...

  9. Spartan-6 FPGA Configuration

    These configuration pins serve as the interface for a number of different configuration modes: • JTA ...

  10. Windows下配置Git服务器和客户端

    http://www.cnblogs.com/lwme/archive/2012/12/25/configuring-git-server-and-client-on-windows.html] 选择 ...