用到的开源工具包:hamcrest,junit
IDE:MyEclipse 2013 SR1
用到的工具:
1、String java.lang.String.format(Locale l,String format,Object... args)
l
- 格式化过程中要应用的语言环境。如果 l 为 null,则不进行本地化。
format
- 格式字符串
args
- 格式字符串中由格式说明符引用的参数。如果还有格式说明符以外的参数,则忽略这些额外的参数。参数的数目是可变的,可以为 0。参数的最大数目受Java Virtual Machine Specification 所定义的 Java 数组最大维度的限制。有关 null 参数的行为依赖于转换。
2、java.lang.StringBuilder
一个可变的字符序列。此类提供一个与 StringBuffer
兼容的 API,但不保证同步。该类被设计用作 StringBuffer
的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。如果可能,建议优先采用该类,因为在大多数实现中,它比StringBuffer
要快。
在 StringBuilder
上的主要操作是 append
和 insert
方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符追加或插入到字符串生成器中。append
方法始终将这些字符添加到生成器的末端;而insert
方法则在指定的点添加字符。
例如,如果 z
引用一个当前内容为 "start
" 的字符串的生成器对象,则该方法调用 z.append("le")
将使字符串生成器包含 "startle
",而z.insert(4, "le")
将更改字符串生成器,使之包含 "starlet
"。
通常,如果 sb 引用 StringBuilder
的实例,则 sb.append(x)
和 sb.insert(sb.length(), x)
具有相同的效果。每个字符串生成器都有一定的容量。只要字符串生成器所包含的字符序列的长度没有超出此容量,就无需分配新的内部缓冲区。如果内部缓冲区溢出,则此容量自动增大。
将 StringBuilder
的实例用于多个线程是不安全的。如果需要这样的同步,则建议使用 StringBuffer
。
利用1、2实现了十六进制字符的转换:
public static String byteToHexString(byte[] bytes, int start, int end) { if (bytes == null) { throw new IllegalArgumentException("bytes == null"); } StringBuilder s = new StringBuilder(); for (int i = start; i < end; i++) { s.append(format("%02x", bytes[i])); } return s.toString(); } /** Same as byteToHexString(bytes, 0, bytes.length). */ public static String byteToHexString(byte bytes[]) { return byteToHexString(bytes, 0, bytes.length); } /** The same as String.format(Locale.ENGLISH, format, objects). */ public static String format(final String format, final Object... objects) { return String.format(Locale.ENGLISH, format, objects); }
3、java.io.ByteArrayOutputStream
此类实现了一个输出流,其中的数据被写入一个 byte 数组。缓冲区会随着数据的不断写入而自动增长。可使用 toByteArray()
和toString()
获取数据。
关闭 ByteArrayOutputStream 无效。此类中的方法在关闭此流后仍可被调用,而不会产生任何 IOException。
4、java.io.DataOutputStream数据输出流允许应用程序以适当方式将基本 Java 数据类型写入输出流中。然后,应用程序可以使用数据输入流将数据读入。
5、java.io.ByteArrayInputStream
ByteArrayInputStream
包含一个内部缓冲区,该缓冲区包含从流中读取的字节。内部计数器跟踪 read
方法要提供的下一个字节。
关闭 ByteArrayInputStream 无效。此类中的方法在关闭此流后仍可被调用,而不会产生任何 IOException。
6、java.io.DataInputStream数据输入流允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型。应用程序可以使用数据输出流写入稍后由数据输入流读取的数据。
DataInputStream 对于多线程访问不一定是安全的。 线程安全是可选的,它由此类方法的使用者负责。
使用3、4、5、6分别实现一个序列化和一个反序列化方法:
public static byte[] serialize(Writable writable) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); DataOutputStream dataOut = new DataOutputStream(out); writable.write(dataOut); dataOut.close(); return out.toByteArray(); } public static byte[] deserialize(Writable writable, byte[] bytes) throws IOException { ByteArrayInputStream in = new ByteArrayInputStream(bytes); DataInputStream dataIn = new DataInputStream(in); writable.readFields(dataIn); dataIn.close(); return bytes; }
package org.apache.hadoop.io; import static org.hamcrest.Matchers.*; import static org.junit.Assert.assertThat; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.Locale; import org.junit.Test; public class THT_testWritable { @Test public void walkthroughWithNoArgsConstructor() throws IOException { IntWritable writable = new IntWritable(); writable.set(1234); checkWalkthrough(writable); } @Test public void walkthroughWithValueConstructor() throws IOException { IntWritable writable = new IntWritable(1234); checkWalkthrough(writable); } private void checkWalkthrough(IntWritable writable) throws IOException { byte[] bytes = serialize(writable); assertThat(bytes.length, is(4)); assertThat(byteToHexString(bytes), is("000004d2")); IntWritable newWritable = new IntWritable(); deserialize(newWritable, bytes); assertThat(newWritable.get(), is(1234)); } @Test public void comparator() throws IOException { RawComparator<IntWritable> comparator = WritableComparator .get(IntWritable.class); IntWritable w1 = new IntWritable(163); IntWritable w2 = new IntWritable(67); assertThat(comparator.compare(w1, w2), greaterThan(0)); byte[] b1 = serialize(w1); byte[] b2 = serialize(w2); assertThat(comparator.compare(b1, 0, b1.length, b2, 0, b2.length), greaterThan(0)); } @Test public void test() throws IOException { IntWritable src = new IntWritable(163); IntWritable dest = new IntWritable(); assertThat(writeTo(src, dest), is("000000a3")); assertThat(dest.get(), is(src.get())); } /** * Given an array of bytes it will convert the bytes to a hex string * representation of the bytes * * @param bytes * @param start * start index, inclusively * @param end * end index, exclusively * @return hex string representation of the byte array */ public static String byteToHexString(byte[] bytes, int start, int end) { if (bytes == null) { throw new IllegalArgumentException("bytes == null"); } StringBuilder s = new StringBuilder(); for (int i = start; i < end; i++) { s.append(format("%02x", bytes[i])); } return s.toString(); } /** Same as byteToHexString(bytes, 0, bytes.length). */ public static String byteToHexString(byte bytes[]) { return byteToHexString(bytes, 0, bytes.length); } /** The same as String.format(Locale.ENGLISH, format, objects). */ public static String format(final String format, final Object... objects) { return String.format(Locale.ENGLISH, format, objects); } public static byte[] serialize(Writable writable) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(); DataOutputStream dataOut = new DataOutputStream(out); writable.write(dataOut); dataOut.close(); return out.toByteArray(); } public static byte[] deserialize(Writable writable, byte[] bytes) throws IOException { ByteArrayInputStream in = new ByteArrayInputStream(bytes); DataInputStream dataIn = new DataInputStream(in); writable.readFields(dataIn); dataIn.close(); return bytes; } public static String writeTo(Writable src, Writable dest) throws IOException { byte[] data = deserialize(dest, serialize(src)); return byteToHexString(data); } public static String serializeToString(Writable src) throws IOException { return byteToHexString(serialize(src)); } }
运行结果如下: