Apache Hadoop Java API:Text.readFields()与Text.readString()的区别
我来帮你理清楚Apache Hadoop里Text类的readFields()和readString()到底有啥不一样——当初我刚接触Hadoop序列化的时候也搞混过这俩,结合源码和实际使用经验给你拆解下:
核心差异拆解
1. 方法定位与用途
Text.readFields(DataInput in):这是Writable接口强制要求的反序列化方法,属于Text实例的成员方法。它的作用是把输入流中的数据读取并填充到当前Text对象本身,会直接修改实例的内部状态。简单说:你得先有个Text对象,调用它的readFields才能把流里的内容“装进”这个对象里。Text.readString(DataInput in, int maxLength)(含无maxLength的重载):这是个静态工具方法,完全独立于Text实例。它的核心作用是直接从输入流读取UTF-8编码的内容,解码后返回一个Java String对象——不需要提前创建任何Text实例就能用,纯粹是个“读流转String”的工具。
2. 实现细节差异
从你贴的readString源码片段也能看出它的逻辑:
先通过
WritableUtils.readVIntInRange()读取可变长度的整数(用来标记后续字符串的字节长度,这种编码能节省空间),然后读取对应长度的字节数组,最后将字节数组解码为UTF-8字符串返回。
而readFields()的底层实现,本质是调用Text内部的重载方法,逻辑是:
- 同样读取可变长度整数作为字节长度
- 把读取到的字节直接存储到Text对象内部的字节数组里(Text底层就是用字节数组存储UTF-8编码内容,而非直接存String)
- 不会直接返回String,数据会留在当前Text实例中,后续你可以通过
toString()转成String,或者用Text的其他方法操作这些原始字节。
3. 使用场景区别
- 用
readFields():当你需要反序列化得到一个Text对象的时候,比如MapReduce任务中Reducer接收Text类型的键值对,框架内部就是调用这个方法把序列化流转换成Text实例。 - 用
readString():当你只需要从流里拿到一个字符串,不需要Text对象的时候,比如自定义Writable类中要读取一个字符串字段,直接调用这个静态方法拿到String就行,没必要额外创建Text实例。
举两个简单的代码示例:
使用readFields()的场景
// 先创建空的Text实例 Text text = new Text(); // 从输入流读取数据填充到text对象 text.readFields(dataInput); // 后续可以转成String使用 String content = text.toString();
使用readString()的场景
// 无需创建Text,直接从流读取UTF-8字符串 String content = Text.readString(dataInput); // 带maxLength的版本更安全,能限制读取的最大字节数,防止恶意数据 String limitedContent = Text.readString(dataInput, 1024);
4. 额外注意点
readString()的带maxLength参数版本可以限制读取的最大字节数,避免读取过大的恶意数据,安全性更高;readFields()如果要限制长度,需要调用其重载方法readFields(DataInput in, int maxLength)。- Text内部存储的是UTF-8原始字节,
readFields()后Text对象占用的内存更小;而readString()直接解码成Java String(UTF-16编码),会占用更多内存空间。
内容的提问来源于stack exchange,提问作者Gyanendra Dwivedi
相关产品推荐
相关产品推荐

