`

Java 与 C 底层数据类型转换

阅读更多
前段时间一直忙着做J2EE服务器与C++客户端的项目。终于,项目告一段落,有一些收获在这里与大家分享。
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;

/**
 * 仅仅适用于 Java 与 C++ 通讯中,网络流解析与生成使用
 *
 * 高低位互换(Big-Endian 大头在前 & Little-Endian 小头在前)。
 * 举例而言,有一个4字节的数据0x01020304,要存储在内存中或文件中编号0˜3字节的位置,两种字节序的排列方式分别如下:
 * <pre>
 * Big Endian
 *  
 * 低地址                           高地址
 * ----------------------------------------------------&gt;
 * 地址编号
 * |     0      |      1     |     2       |      3    |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |     01     |      02    |     03      |     04    |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * 
 * Little Endian
 * 
 * 低地址                           高地址
 * ----------------------------------------------------&gt;
 * 地址编号
 * |     0      |      1     |     2       |      3    |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * |     04     |      03    |     02      |     01    |
 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 * </pre>
 * Java则统一使用big模式
 * c中的unsigned short  对应着java中的char两个字节,无符号
 * c的无符号int,short,byte字节数组,相应转换成java的long,char,short
 *
 * @author Snowolf
 * @version 1.0
 * @since 1.0
 */
public abstract class CIOUtil {
	public static final String CHARSET = "UTF-8";

	/**
	 * 从输入流中读布尔 
	 * 
	 * @param is
	 * @return
	 * @throws IOException
	 */
	public static boolean readBoolean(DataInputStream is) throws IOException {
		return is.readBoolean();
	}

	/**
	 * 从流中读定长度字节数组
	 * 
	 * @param is
	 * @param s
	 * @return
	 * @throws IOException
	 */
	public static byte[] readBytes(DataInputStream is, int i)
			throws IOException {
		byte[] data = new byte[i];
		is.readFully(data);

		return data;
	}

	/**
	 * 从输入流中读字符 
	 * 
	 * @param is
	 * @return
	 * @throws IOException
	 */
	public static char readChar(DataInputStream is) throws IOException {
		return (char) readShort(is);
	}

	/**
	 * 从输入流中读双精度 
	 * 
	 * @param is
	 * @return
	 * @throws IOException
	 */
	public static double readDouble(DataInputStream is) throws IOException {
		return Double.longBitsToDouble(readLong(is));
	}

	/**
	 * 从输入流中读单精度
	 * 
	 * @param is
	 * @return
	 * @throws IOException
	 */
	public static float readFloat(DataInputStream is) throws IOException {
		return Float.intBitsToFloat(readInt(is));
	}

	/**
	 * 从流中读整型
	 * 
	 * @param is
	 * @return
	 * @throws IOException
	 */
	public static int readInt(DataInputStream is) throws IOException {
		return Integer.reverseBytes(is.readInt());
	}

	/**
	 * 从流中读长整型
	 * 
	 * @param is
	 * @return
	 * @throws IOException
	 */
	public static long readLong(DataInputStream is) throws IOException {
		return Long.reverseBytes(is.readLong());
	}

	/**
	 * 从流中读短整型
	 * 
	 * @param is
	 * @return
	 * @throws IOException
	 */
	public static short readShort(DataInputStream is) throws IOException {
		return Short.reverseBytes(is.readShort());
	}

	/**
	 * 从输入流中读字符串 字符串 结构 为 一个指定字符串字节长度的短整型+实际字符串
	 * 
	 * @param is
	 * @return
	 * @throws IOException
	 */
	public static String readUTF(DataInputStream is) throws IOException {
		short s = readShort(is);
		byte[] str = new byte[s];

		is.readFully(str);

		return new String(str, CHARSET);
	}

	/**
	 * 向输出流中写布尔
	 * 
	 * @param os
	 * @param b
	 * @throws IOException
	 */
	public static void writeBoolean(DataOutputStream os, boolean b)
			throws IOException {
		os.writeBoolean(b);
	}

	/**
	 * 向输出流中写字节数组
	 * 
	 * @param os
	 * @param data
	 * @throws IOException
	 */
	public static void writeBytes(DataOutputStream os, byte[] data)
			throws IOException {
		os.write(data);
	}

	/**
	 * 向输出流中写字符
	 * 
	 * @param os
	 * @param b
	 * @throws IOException
	 */
	public static void writeChar(DataOutputStream os, char b)
			throws IOException {
		writeShort(os, (short) b);
	}

	/**
	 * 向输出流中写双精度
	 * 
	 * @param os
	 * @param d
	 * @throws IOException
	 */
	public static void writeDouble(DataOutputStream os, double d)
			throws IOException {
		writeLong(os, Double.doubleToLongBits(d));
	}

	/**
	 * 向输出流中写单精度
	 * 
	 * @param os
	 * @param f
	 * @throws IOException
	 */
	public static void writeFloat(DataOutputStream os, float f)
			throws IOException {
		writeInt(os, Float.floatToIntBits(f));
	}

	/**
	 * 向输出流中写整型
	 * 
	 * @param os
	 * @param i
	 * @throws IOException
	 */
	public static void writeInt(DataOutputStream os, int i) throws IOException {
		os.writeInt(Integer.reverseBytes(i));
	}

	/**
	 * 向输出流中写长整型
	 * 
	 * @param os
	 * @param l
	 * @throws IOException
	 */
	public static void writeLong(DataOutputStream os, long l)
			throws IOException {
		os.writeLong(Long.reverseBytes(l));
	}

	/**
	 * 向输出流中写短整型
	 * 
	 * @param os
	 * @param s
	 * @throws IOException
	 */
	public static void writeShort(DataOutputStream os, short s)
			throws IOException {
		os.writeShort(Short.reverseBytes(s));
	}

	/**
	 * 向输出流中写字符串 字符串 结构 为 一个指定字符串字节长度的短整型+实际字符串
	 * 
	 * @param os
	 * @param str
	 * @throws IOException
	 */
	public static void writeUTF(DataOutputStream os, String str)
			throws IOException {
		byte[] data = str.getBytes(CHARSET);
		writeShort(os, (short) data.length);
		os.write(data);
	}

}


再写个测试类
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;

import org.junit.Test;
import static org.junit.Assert.*;

/**
 * 
 * @author Snowolf
 * @version 1.0
 * @since 1.0
 */
public class CIOUtilTest {
	/**
	 * 测试布尔值
	 * 
	 * @throws IOException
	 */
	@Test
	public final void testBoolean() throws IOException {
		boolean input = true;
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		DataOutputStream os = new DataOutputStream(baos);

		CIOUtil.writeBoolean(os, input);

		byte[] b = baos.toByteArray();
		baos.flush();
		baos.close();

		ByteArrayInputStream bais = new ByteArrayInputStream(b);
		DataInputStream is = new DataInputStream(bais);

		boolean output = CIOUtil.readBoolean(is);

		bais.close();

		assertEquals(input, output);
	}

	/**
	 * 测试字节数组
	 * 
	 * @throws IOException
	 */
	@Test
	public final void testBytes() throws IOException {
		byte[] input = "中文".getBytes("UTF-8");
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		DataOutputStream os = new DataOutputStream(baos);

		CIOUtil.writeBytes(os, input);

		byte[] b = baos.toByteArray();
		baos.flush();
		baos.close();

		ByteArrayInputStream bais = new ByteArrayInputStream(b);
		DataInputStream is = new DataInputStream(bais);

		byte[] output = CIOUtil.readBytes(is, 6);

		bais.close();

		assertArrayEquals(input, output);
	}

	/**
	 * 测试字符
	 * 
	 * @throws IOException
	 */
	@Test
	public final void testChar() throws IOException {
		char input = '中';
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		DataOutputStream os = new DataOutputStream(baos);

		CIOUtil.writeChar(os, input);

		byte[] b = baos.toByteArray();
		baos.flush();
		baos.close();

		ByteArrayInputStream bais = new ByteArrayInputStream(b);
		DataInputStream is = new DataInputStream(bais);

		char output = CIOUtil.readChar(is);

		bais.close();

		assertEquals(input, output);
	}

	/**
	 * 测试双精度
	 * 
	 * @throws IOException
	 */
	@Test
	public final void testDouble() throws IOException {
		double input = 1.23456789d;
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		DataOutputStream os = new DataOutputStream(baos);

		CIOUtil.writeDouble(os, input);

		byte[] b = baos.toByteArray();
		baos.flush();
		baos.close();

		ByteArrayInputStream bais = new ByteArrayInputStream(b);
		DataInputStream is = new DataInputStream(bais);

		double output = CIOUtil.readDouble(is);

		bais.close();

		assertEquals(input, output, 9);
	}

	/**
	 * 测试单精度
	 * 
	 * @throws IOException
	 */
	@Test
	public final void testFloat() throws IOException {
		float input = 1.23456789f;
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		DataOutputStream os = new DataOutputStream(baos);

		CIOUtil.writeFloat(os, input);

		byte[] b = baos.toByteArray();
		baos.flush();
		baos.close();

		ByteArrayInputStream bais = new ByteArrayInputStream(b);
		DataInputStream is = new DataInputStream(bais);

		float output = CIOUtil.readFloat(is);

		bais.close();

		assertEquals(input, output, 9);
	}

	/**
	 * 测试整型
	 * 
	 * @throws IOException
	 */
	@Test
	public final void testInt() throws IOException {
		int input = 1;
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		DataOutputStream os = new DataOutputStream(baos);

		CIOUtil.writeInt(os, input);

		byte[] b = baos.toByteArray();
		baos.flush();
		baos.close();

		ByteArrayInputStream bais = new ByteArrayInputStream(b);
		DataInputStream is = new DataInputStream(bais);

		int output = CIOUtil.readInt(is);

		bais.close();

		assertEquals(input, output);
	}

	/**
	 * 测试长整型
	 * 
	 * @throws IOException
	 */
	@Test
	public final void testLong() throws IOException {
		long input = 1l;
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		DataOutputStream os = new DataOutputStream(baos);

		CIOUtil.writeLong(os, input);

		byte[] b = baos.toByteArray();
		baos.flush();
		baos.close();

		ByteArrayInputStream bais = new ByteArrayInputStream(b);
		DataInputStream is = new DataInputStream(bais);

		long output = CIOUtil.readLong(is);

		bais.close();

		assertEquals(input, output);
	}

	/**
	 * 测试短整型
	 * 
	 * @throws IOException
	 */
	@Test
	public final void testShort() throws IOException {
		short input = 1;
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		DataOutputStream os = new DataOutputStream(baos);

		CIOUtil.writeShort(os, input);

		byte[] b = baos.toByteArray();
		baos.flush();
		baos.close();

		ByteArrayInputStream bais = new ByteArrayInputStream(b);
		DataInputStream is = new DataInputStream(bais);

		short output = CIOUtil.readShort(is);

		bais.close();

		assertEquals(input, output);
	}

	/**
	 * 测试UTF-8字符串
	 * 
	 * @throws IOException
	 */
	@Test
	public final void testUTF() throws IOException {
		String input = "中文支持";
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		DataOutputStream os = new DataOutputStream(baos);

		CIOUtil.writeUTF(os, input);

		byte[] b = baos.toByteArray();
		baos.flush();
		baos.close();

		ByteArrayInputStream bais = new ByteArrayInputStream(b);
		DataInputStream is = new DataInputStream(bais);

		String output = CIOUtil.readUTF(is);

		bais.close();

		assertEquals(input, output);
	}

}

分享到:
评论

相关推荐

    java 与 flex 数据转换

    以下是一些主要的数据类型转换规则: 1. **Null**: - 在 ActionScript 和 Java 中,`null` 类型是相同的,无需转换。 2. **Number**: - ActionScript 的 `Number` 类型可以映射到 Java 的 `java.lang.Number` ...

    数据类型的转换数据类型的转换

    以下是对数据类型转换的详细阐述: 1. 基本数据类型:在大多数编程语言中,数据类型主要分为整型(如int)、浮点型(如float)、字符型(如char)、布尔型(如bool)和字符串型(如string)。这些类型各有其存储和...

    Java Web应用底层数据传递模式的分析与研究.pdf

    总的来说,Java Web应用的底层数据传递是一个多层面、多步骤的过程,涉及到HTTP协议、Servlet、JSP、数据类型转换以及各种框架的使用。开发者需要深入了解这些技术,才能构建出高效、可维护的Web应用。通过对这一...

    Java与C语言混合开发技术

    - 在数据类型转换上,Java 与 C 的差异需要通过 JNI 提供的转换函数进行适配,如 Java 字符串到 C 字符数组的转换,以及 C 整型到 Java 整型的转换。 2. 异常处理: - Java 使用 try-catch 语句处理异常,而 C ...

    Linux下Java与C的数据交换

    - **类型映射**:Java和C的数据类型在映射时需要特别注意。例如: - Java的`boolean`类型映射到C的`jboolean`类型。 - Java的`byte`类型映射到C的`jbyte`类型。 - Java的`char`类型映射到C的`jchar`类型。 - ...

    java转换C生产dat文件

    在跨语言编程环境中,例如Java程序需要处理由C语言生成的数据文件(dat文件),常常会遇到数据类型不一致导致的数据解析问题,尤其是当涉及到二进制数据时。这是因为Java和C语言对于基本数据类型的处理方式存在差异...

    进制转换C源码

    本文将基于标题“进制转换C源码”和描述,深入探讨C语言实现不同进制转换的原理及代码实现,同时会涉及与Java语言进制转换差异的讨论。 首先,进制转换是计算机科学中的基本概念,主要包括二进制、八进制、十进制和...

    Jni 项目 包含各种数据类型转换

    `c/c++`则负责实现这些方法的具体逻辑,可能涉及更底层的数据处理或性能敏感的操作。 在项目中,`C++头文件在JAVA项目目录里.txt`可能包含有关如何在Java项目结构中组织C++头文件的信息。`JAVA idea项目`和`C++ vs...

    java的底层开发工具

    3. 在Java和C/C++之间传递数据,JNative提供了自动的类型转换。 三、示例 一个简单的例子是,创建一个Java类,声明一个native方法,然后使用JNative在C++中实现这个方法,例如计算两个整数的和: Java代码: ```...

    C转java工具

    C转Java工具通过解析C语言源代码,将其转换为Java语言的等价表达,从而实现了两者之间的桥梁。 该工具的基本工作原理是:首先,它会读取C源代码文件,然后对C语言的语法结构进行分析,包括变量声明、函数定义、循环...

    使用java和C语言进行通信 并且使用结构体传输的代码实例 包含三个示例

    在Java和C之间传递结构体时,通常需要进行数据类型转换。比如,Java的`long`对应C的`int64_t`,Java的`boolean`对应C的`int`等。因此,需要在两端都进行相应的类型匹配和转换。 7. **错误处理和内存管理** 由于...

    Android Java代码与JNI交互 引用类型转换(五)

    这通常涉及到数据类型的转换,因为Java和C/C++的数据类型并不完全相同。 在Java中,引用类型主要包括对象引用(Object)、类引用(Class)、数组引用(Array)等。当我们需要在JNI中处理这些引用时,需要进行适当的...

    J2EE(错误之数据类型转换异常)

    在J2EE编程中,我们经常会遇到数据类型转换异常,这通常是由于不正确的类型强制转换导致的。在给定的“名片管理系统”示例中,问题出在`setAttribute`和`getAttribute`方法的使用上。这两个方法是Java Servlet API的...

    Java与C语言混合编程方法探讨.pdf

    引入生成的头文件,并在C语言代码中实现对应的本地方法,利用JNIEnv指针和相应的类型定义,如`jobject`,来处理Java对象和数据。 5. 编译和运行: 编译C语言源代码,生成动态链接库文件,然后在Java程序中加载并...

    使用java与C写的jni小例子

    整个过程中,Java和C/C++之间的通信依赖于JNI框架,它处理了底层数据类型的转换、异常处理和内存管理等细节。这个小例子展示了如何利用JNI将Java的跨平台性和C/C++的高效性相结合,实现特定的程序需求。

    CPlus_to_Java_Converter;C++转java工具

    1. **数据类型转换**:C++中的指针在Java中通常对应于引用。转换器需要将C++的指针操作转换为Java的引用操作,同时处理内存分配和释放的差异,因为Java的垃圾回收机制会自动管理内存。 2. **面向对象的差异**:C++...

    java与c交互传递字符串和整型

    在Java与C/C++的交互中,字符串和整型是最基本的数据类型之一。下面我们将详细讨论如何在Java和C之间传递这两种类型。 1. **字符串传递**:在Java中,字符串是对象,而在C中,字符串通常表示为字符数组。在JNI中,...

    netty 在java中的字节码转换

    netty通信时经常和底层数据交互,C语言和java的数据类型和范围不同,通信时需要转化或兼容,附件为字节码、进制常用的转换类。

    AndroidJNI 学习 java与c传数据

    数据传输通常涉及类型转换,因为Java和C/C++的数据类型并不完全相同。 例如,假设我们有一个Java方法需要传递一个整型数组到C++,并在那里进行处理: ```java public class JNITest { public native void ...

Global site tag (gtag.js) - Google Analytics