再次求助将十六进制文件转成十进制

儒林外史 2014-04-09 02:23:22
之前问题描述不够清楚,今天再发一个帖子。主要就是想把一个十六进制文本文件转换成十进制的CSV文件。
在本地D盘上有一个以十六进制存储的文本文件。此文件包含了很多个数据块,每个数据块在实际业务中是同一个ID下的多条记录(每条记录的字段都是一样的)。每个数据块都是以四个FF开始作为标识。用UE打开如下所示:


第一行是文件头信息,这个数据不需要,直接过滤掉即可。

以FF FF FF FF开头的每个数据块包含九个字段的数据内容。分别是ID、IDName、Date、Item01、Item02、Item03、Item04、Item05、Item06。其中,ID和IDName字段的数据只在每个数据块中的第一行和第二行出现一次,后面的七个字段内容是多次出现,即每两行一条记录,代表具体某一天的数据记录情况。

举第一个数据块为例:

ID ——53 48 36 30 30 30 30 30,用八个进制符位来表示,这个要转换成十进制的字符串。
IDName ——C6 D6 B7 A2 D2 F8 D0 D0,这个字段内容也是用八个进制符位来表示,这个也要转换成十进制的字符串。

注:每个数据块的第一行和第二行,只有上面16个进制符位的数据有用,这两行中剩余的其他16个进制符位数据不需要,直接跳过。

Date ——80 01 3A 53,这个日期字段的内容需要反向读取(即53 3A 01 80)来转换成十进制整型。它是以毫秒存储的,需要转换成短日期型,即不包含时间的日期(比如20140403)。
Item01 ——5C 8F 1A 41,这个字段内容需要转换成十进制浮点型,也是反向读取。
Item02 ——A4 70 1D 41,也是转换成十进制浮点型,反向读取。
Item03 ——7B 14 1A 41,转换成十进制浮点型,反向读取。
Item04 ——14 AE 1B 41,转换成十进制浮点型,反向读取。
Item05 ——F0 E0 93 49,转换成十进制浮点型,反向读取。
Item06 ——BA 69 8C 4E,转换成十进制浮点型,反向读取。


这个数据块内剩余的数据都是每两行为一条记录,重复上面Date到Item06这个七个字段的内容。
另外,上面的这九个字段的内容,除了ID和IDName两个字段的内容进行读取时不需要反向读取,其他均需要反向读取,然后转换成要求的不同数据类型的十进制数据。

我需要的就是按上面这样将十六进制的文本文件转换成含不同数据类型的十进制的CSV文件。


...全文
615 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
lxbccsu 2014-05-23
  • 打赏
  • 举报
回复
引用 19 楼 u014301433 的回复:
能否解释一下toStringHex(byte value)这个方法的逻辑?
你可以了解下Java基本类型的范围和16进制知识; 如:Java中数字都是有符号的; 0到9在16进制中是怎么表示的; 像对于字节byte:1、257、513.... 表示的都是1; 255、511... 表示的都是-1; 其实简单点可以这样处理 字节到16进制的转换: return Integer.toHexString((value & 0x00FF) | 0xFF00).substring(2, 4); 一行代码就可以了;
儒林外史 2014-05-22
  • 打赏
  • 举报
回复
引用 18 楼 lxbccsu 的回复:
[quote=引用 17 楼 lxbccsu 的回复:] [quote=引用 16 楼 u014301433 的回复:] 日期字段转换的不正确。都是“19700117”,字段少了一个Item06。
就不能自己改改,处理下,送佛得还得送上西; 那个日期做了处理的话,你得还原,也不清楚你原来是怎么处理,这就是简单*1000了;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Calendar;

public class HexParser {

	static Calendar cal = Calendar.getInstance();
	static SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
	
	static String fileFullPath = "E:/SUPERSTK.DAD";//Change it to the actual file path
	
	public static void main(String[] args) {
		try {
			readHexFile();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	public static void readHexFile()throws Exception{
		DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(fileFullPath)));
		in.skipBytes(16);
		
		byte[] bytes = new byte[16];
		int nCounts = 0;
		
		while((in.read(bytes)) != -1){
			String hexStr = toStringHex(bytes[0]) + toStringHex(bytes[1]) 
							+ toStringHex(bytes[2]) + toStringHex(bytes[3]);
			if(hexStr.equalsIgnoreCase("FFFFFFFF")){
				nCounts = 1;
			}else{
				nCounts++;
			}
			
			if(nCounts > 2){
				getDateAndItemx(bytes, nCounts);
			}else{
				getIDAndIDName(bytes, nCounts);
			}
		}
		
		in.close();
	}
	
	
	private static void getIDAndIDName(byte[] bytes, int nCounts) {
		if(nCounts == 1){
			System.out.print("ID: " + new String(bytes, 4, 8));
			System.out.print(", ");
		}else{
			System.out.print("IDName: " + new String(bytes, 4, 8, Charset.forName("GBK")));
			System.out.print(": ");
			System.out.println();
		}
		
	}


	private static void getDateAndItemx(byte[] bytes, int nCounts) {
		if(nCounts%2 == 0){
			getItemX(bytes, 0, 4, 4);
			getItemX(bytes, 4, 4, 5);
			getItemX(bytes, 8, 4, 6);
			System.out.println();
		}else{
			getDate(bytes);
			getItemX(bytes, 4, 4, 1);
			getItemX(bytes, 8, 4, 2);
			getItemX(bytes, 12, 4, 3);
		}
	}

	private static String getItemX(byte[] bytes, int start, int length, int itemIndex) {
		StringBuilder hexStr = new StringBuilder();
		for(int i = start + length - 1 ; i >= start; i--){
			hexStr.append(toStringHex(bytes[i]));
		}
		System.out.print("Item0" + itemIndex + ": " + hexStr.toString().toUpperCase());
		System.out.print(", ");
		
		return hexStr.toString();
	}


	private static String getDate(byte[] bytes){
		String hexStr = toStringHex(bytes[3]) + toStringHex(bytes[2])
				        + toStringHex(bytes[1]) + toStringHex(bytes[0]);
		cal.setTimeInMillis(((long)Integer.parseInt(hexStr, 16))*1000);
		System.out.print("Date: " + sdf.format(cal.getTime()));
		System.out.print(", ");
		
		return hexStr;
	}
	
	public static String toStringHex(byte value) {
		if(value < 0) value += 256; 
		if(value >= 0 && value <= 9) 
			return "0" + value;
		else
			return Integer.toHexString(value&0xFF);
	}
}
[/quote] 还有点小问题,修改了下, 用下面的替换原来的方法,其它的自己改了:

private static String getDate(byte[] bytes){
		String hexStr = toStringHex(bytes[3]) + toStringHex(bytes[2])
				        + toStringHex(bytes[1]) + toStringHex(bytes[0]);
		cal.setTimeInMillis(((long)Integer.parseInt(hexStr, 16))*1000);
		System.out.print("Date: " + sdf.format(cal.getTime()) + "|" + hexStr.toUpperCase());
		System.out.print(", ");
		
		return hexStr;
	}
	
	public static String toStringHex(byte value) {
		String hexStr = "";
		if(value < 0) value += 256; 
		if(value >= 0 && value <= 9) 
			hexStr = "0" + value;
		else{
			hexStr = Integer.toHexString(value&0xFF);
			if(hexStr.length() == 1){
				hexStr = "0" + hexStr ;
			}
		}
		return hexStr;
	}
[/quote] 能否解释一下toStringHex(byte value)这个方法的逻辑?
lxbccsu 2014-04-18
  • 打赏
  • 举报
回复
引用 12 楼 lxbccsu 的回复:
[quote=引用 10 楼 u014301433 的回复:] [quote=引用 9 楼 preferme 的回复:] 楼主对数据的编码,或者,数据结构 的了解,很缺乏呀。 上一个贴子就存在数据格式没有明确的问题, 这个贴子,倒是说明了,可惜很多地方都不明确,甚至不正确。 还有数据编码方面的知识,感觉也是一塌糊涂。 这些数据解析起来还是比较麻烦的。
不是计算机专业科班毕业的,自学JAVA基础不够好,嗯,以后是加强数据结构和数据编码方面的基础。 以上举的是以第一个数据块为例 [/quote] 不知道你是否清楚怎么编码为十六进制的数据文件,看了半天猜出ID, IDName应该是把字符串保存为十六进制,date是把整型 保存为十六进制;其它的就不清楚了; 再有是 把你的十六进制数据文件附件出来,帮你做个程序还得先创建个十六进制数据文件; 你那个数据文件格式都是固定的,就是解析下,只要你清楚怎么编码,解码就很容易; 示例:

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Calendar;

public class HexParser {

	static Calendar cal = Calendar.getInstance();
	static SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
	
	static String fileFullPath = "E:/data.dat";//Change it to the actual file path
	
	public static void main(String[] args) {
		try {
			readHexFile();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	public static void readHexFile()throws Exception{
		DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(fileFullPath)));
		in.skipBytes(16);
		
		byte[] bytes = new byte[16];
		int nCounts = 0;
		
		while((in.read(bytes)) != -1){
			String hexStr = Integer.toHexString(((bytes[0] << 24)&0xFFFF) 
					| ((bytes[1] << 16)&0xFFFF) 
					| ((bytes[2] << 8)&0xFFFF) 
					| (bytes[3]&0xFFFF));
			
			if(hexStr.equalsIgnoreCase("FFFF")){
				nCounts = 1;
			}else{
				nCounts++;
			}
			
			if(nCounts > 2){
				getDateAndItemx(bytes, nCounts);
			}else{
				getIDAndIDName(bytes, nCounts);
			}
		}
		
	}
	
	
	private static void getIDAndIDName(byte[] bytes, int nCounts) {
		if(nCounts == 1){
			System.out.print("ID: " + new String(bytes, 4, 8));
			System.out.print(", ");
		}else{
			System.out.print("IDName: " + new String(bytes, 4, 8, Charset.forName("GBK")));
			System.out.print(": ");
			System.out.println();
		}
		
	}


	private static void getDateAndItemx(byte[] bytes, int nCounts) {
		if(nCounts%2 == 0){
			getItemX(bytes, 0, 4, 3);
			getItemX(bytes, 4, 4, 4);
			getItemX(bytes, 8, 4, 5);
			System.out.println();
		}else{
			getDate(bytes);
			getItemX(bytes, 4, 4, 1);
			getItemX(bytes, 8, 4, 2);
		}
	}

	private static String getItemX(byte[] bytes, int start, int length, int itemIndex) {
		StringBuilder hexStr = new StringBuilder();
		for(int i = start + length - 1 ; i >= start; i--){
			hexStr.append(toStringHex(bytes[i]));
		}
		System.out.print("Item0" + itemIndex + ": " + hexStr.toString().toUpperCase());
		System.out.print(", ");
		
		return hexStr.toString();
	}


	private static String getDate(byte[] bytes){
		String hexStr = toStringHex(bytes[3]) + toStringHex(bytes[2])
				        + toStringHex(bytes[1]) + toStringHex(bytes[0]);
		cal.setTimeInMillis(Integer.parseInt(hexStr, 16));
		System.out.print("Date: " + sdf.format(cal.getTime()));
		System.out.print(", ");
		
		return hexStr;
	}
	
	public static String toStringHex(byte value) {
		if(value < 0) value += 256; 
		if(value >= 0 && value <= 9) 
			return "0" + value;
		else
			return Integer.toHexString(value&0xFF);
	}
}
[/quote] 还把 in.close(); 加上吧;
lxbccsu 2014-04-18
  • 打赏
  • 举报
回复
引用 10 楼 u014301433 的回复:
[quote=引用 9 楼 preferme 的回复:] 楼主对数据的编码,或者,数据结构 的了解,很缺乏呀。 上一个贴子就存在数据格式没有明确的问题, 这个贴子,倒是说明了,可惜很多地方都不明确,甚至不正确。 还有数据编码方面的知识,感觉也是一塌糊涂。 这些数据解析起来还是比较麻烦的。
不是计算机专业科班毕业的,自学JAVA基础不够好,嗯,以后是加强数据结构和数据编码方面的基础。 以上举的是以第一个数据块为例 [/quote] 不知道你是否清楚怎么编码为十六进制的数据文件,看了半天猜出ID, IDName应该是把字符串保存为十六进制,date是把整型 保存为十六进制;其它的就不清楚了; 再有是 把你的十六进制数据文件附件出来,帮你做个程序还得先创建个十六进制数据文件; 你那个数据文件格式都是固定的,就是解析下,只要你清楚怎么编码,解码就很容易; 示例:

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Calendar;

public class HexParser {

	static Calendar cal = Calendar.getInstance();
	static SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
	
	static String fileFullPath = "E:/data.dat";//Change it to the actual file path
	
	public static void main(String[] args) {
		try {
			readHexFile();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	public static void readHexFile()throws Exception{
		DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(fileFullPath)));
		in.skipBytes(16);
		
		byte[] bytes = new byte[16];
		int nCounts = 0;
		
		while((in.read(bytes)) != -1){
			String hexStr = Integer.toHexString(((bytes[0] << 24)&0xFFFF) 
					| ((bytes[1] << 16)&0xFFFF) 
					| ((bytes[2] << 8)&0xFFFF) 
					| (bytes[3]&0xFFFF));
			
			if(hexStr.equalsIgnoreCase("FFFF")){
				nCounts = 1;
			}else{
				nCounts++;
			}
			
			if(nCounts > 2){
				getDateAndItemx(bytes, nCounts);
			}else{
				getIDAndIDName(bytes, nCounts);
			}
		}
		
	}
	
	
	private static void getIDAndIDName(byte[] bytes, int nCounts) {
		if(nCounts == 1){
			System.out.print("ID: " + new String(bytes, 4, 8));
			System.out.print(", ");
		}else{
			System.out.print("IDName: " + new String(bytes, 4, 8, Charset.forName("GBK")));
			System.out.print(": ");
			System.out.println();
		}
		
	}


	private static void getDateAndItemx(byte[] bytes, int nCounts) {
		if(nCounts%2 == 0){
			getItemX(bytes, 0, 4, 3);
			getItemX(bytes, 4, 4, 4);
			getItemX(bytes, 8, 4, 5);
			System.out.println();
		}else{
			getDate(bytes);
			getItemX(bytes, 4, 4, 1);
			getItemX(bytes, 8, 4, 2);
		}
	}

	private static String getItemX(byte[] bytes, int start, int length, int itemIndex) {
		StringBuilder hexStr = new StringBuilder();
		for(int i = start + length - 1 ; i >= start; i--){
			hexStr.append(toStringHex(bytes[i]));
		}
		System.out.print("Item0" + itemIndex + ": " + hexStr.toString().toUpperCase());
		System.out.print(", ");
		
		return hexStr.toString();
	}


	private static String getDate(byte[] bytes){
		String hexStr = toStringHex(bytes[3]) + toStringHex(bytes[2])
				        + toStringHex(bytes[1]) + toStringHex(bytes[0]);
		cal.setTimeInMillis(Integer.parseInt(hexStr, 16));
		System.out.print("Date: " + sdf.format(cal.getTime()));
		System.out.print(", ");
		
		return hexStr;
	}
	
	public static String toStringHex(byte value) {
		if(value < 0) value += 256; 
		if(value >= 0 && value <= 9) 
			return "0" + value;
		else
			return Integer.toHexString(value&0xFF);
	}
}
lxbccsu 2014-04-18
  • 打赏
  • 举报
回复
引用 17 楼 lxbccsu 的回复:
[quote=引用 16 楼 u014301433 的回复:] 日期字段转换的不正确。都是“19700117”,字段少了一个Item06。
就不能自己改改,处理下,送佛得还得送上西; 那个日期做了处理的话,你得还原,也不清楚你原来是怎么处理,这就是简单*1000了;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Calendar;

public class HexParser {

	static Calendar cal = Calendar.getInstance();
	static SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
	
	static String fileFullPath = "E:/SUPERSTK.DAD";//Change it to the actual file path
	
	public static void main(String[] args) {
		try {
			readHexFile();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	public static void readHexFile()throws Exception{
		DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(fileFullPath)));
		in.skipBytes(16);
		
		byte[] bytes = new byte[16];
		int nCounts = 0;
		
		while((in.read(bytes)) != -1){
			String hexStr = toStringHex(bytes[0]) + toStringHex(bytes[1]) 
							+ toStringHex(bytes[2]) + toStringHex(bytes[3]);
			if(hexStr.equalsIgnoreCase("FFFFFFFF")){
				nCounts = 1;
			}else{
				nCounts++;
			}
			
			if(nCounts > 2){
				getDateAndItemx(bytes, nCounts);
			}else{
				getIDAndIDName(bytes, nCounts);
			}
		}
		
		in.close();
	}
	
	
	private static void getIDAndIDName(byte[] bytes, int nCounts) {
		if(nCounts == 1){
			System.out.print("ID: " + new String(bytes, 4, 8));
			System.out.print(", ");
		}else{
			System.out.print("IDName: " + new String(bytes, 4, 8, Charset.forName("GBK")));
			System.out.print(": ");
			System.out.println();
		}
		
	}


	private static void getDateAndItemx(byte[] bytes, int nCounts) {
		if(nCounts%2 == 0){
			getItemX(bytes, 0, 4, 4);
			getItemX(bytes, 4, 4, 5);
			getItemX(bytes, 8, 4, 6);
			System.out.println();
		}else{
			getDate(bytes);
			getItemX(bytes, 4, 4, 1);
			getItemX(bytes, 8, 4, 2);
			getItemX(bytes, 12, 4, 3);
		}
	}

	private static String getItemX(byte[] bytes, int start, int length, int itemIndex) {
		StringBuilder hexStr = new StringBuilder();
		for(int i = start + length - 1 ; i >= start; i--){
			hexStr.append(toStringHex(bytes[i]));
		}
		System.out.print("Item0" + itemIndex + ": " + hexStr.toString().toUpperCase());
		System.out.print(", ");
		
		return hexStr.toString();
	}


	private static String getDate(byte[] bytes){
		String hexStr = toStringHex(bytes[3]) + toStringHex(bytes[2])
				        + toStringHex(bytes[1]) + toStringHex(bytes[0]);
		cal.setTimeInMillis(((long)Integer.parseInt(hexStr, 16))*1000);
		System.out.print("Date: " + sdf.format(cal.getTime()));
		System.out.print(", ");
		
		return hexStr;
	}
	
	public static String toStringHex(byte value) {
		if(value < 0) value += 256; 
		if(value >= 0 && value <= 9) 
			return "0" + value;
		else
			return Integer.toHexString(value&0xFF);
	}
}
[/quote] 还有点小问题,修改了下, 用下面的替换原来的方法,其它的自己改了:

private static String getDate(byte[] bytes){
		String hexStr = toStringHex(bytes[3]) + toStringHex(bytes[2])
				        + toStringHex(bytes[1]) + toStringHex(bytes[0]);
		cal.setTimeInMillis(((long)Integer.parseInt(hexStr, 16))*1000);
		System.out.print("Date: " + sdf.format(cal.getTime()) + "|" + hexStr.toUpperCase());
		System.out.print(", ");
		
		return hexStr;
	}
	
	public static String toStringHex(byte value) {
		String hexStr = "";
		if(value < 0) value += 256; 
		if(value >= 0 && value <= 9) 
			hexStr = "0" + value;
		else{
			hexStr = Integer.toHexString(value&0xFF);
			if(hexStr.length() == 1){
				hexStr = "0" + hexStr ;
			}
		}
		return hexStr;
	}
lxbccsu 2014-04-18
  • 打赏
  • 举报
回复
引用 16 楼 u014301433 的回复:
日期字段转换的不正确。都是“19700117”,字段少了一个Item06。
就不能自己改改,处理下,送佛得还得送上西; 那个日期做了处理的话,你得还原,也不清楚你原来是怎么处理,这就是简单*1000了;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Calendar;

public class HexParser {

	static Calendar cal = Calendar.getInstance();
	static SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
	
	static String fileFullPath = "E:/SUPERSTK.DAD";//Change it to the actual file path
	
	public static void main(String[] args) {
		try {
			readHexFile();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	public static void readHexFile()throws Exception{
		DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(fileFullPath)));
		in.skipBytes(16);
		
		byte[] bytes = new byte[16];
		int nCounts = 0;
		
		while((in.read(bytes)) != -1){
			String hexStr = toStringHex(bytes[0]) + toStringHex(bytes[1]) 
							+ toStringHex(bytes[2]) + toStringHex(bytes[3]);
			if(hexStr.equalsIgnoreCase("FFFFFFFF")){
				nCounts = 1;
			}else{
				nCounts++;
			}
			
			if(nCounts > 2){
				getDateAndItemx(bytes, nCounts);
			}else{
				getIDAndIDName(bytes, nCounts);
			}
		}
		
		in.close();
	}
	
	
	private static void getIDAndIDName(byte[] bytes, int nCounts) {
		if(nCounts == 1){
			System.out.print("ID: " + new String(bytes, 4, 8));
			System.out.print(", ");
		}else{
			System.out.print("IDName: " + new String(bytes, 4, 8, Charset.forName("GBK")));
			System.out.print(": ");
			System.out.println();
		}
		
	}


	private static void getDateAndItemx(byte[] bytes, int nCounts) {
		if(nCounts%2 == 0){
			getItemX(bytes, 0, 4, 4);
			getItemX(bytes, 4, 4, 5);
			getItemX(bytes, 8, 4, 6);
			System.out.println();
		}else{
			getDate(bytes);
			getItemX(bytes, 4, 4, 1);
			getItemX(bytes, 8, 4, 2);
			getItemX(bytes, 12, 4, 3);
		}
	}

	private static String getItemX(byte[] bytes, int start, int length, int itemIndex) {
		StringBuilder hexStr = new StringBuilder();
		for(int i = start + length - 1 ; i >= start; i--){
			hexStr.append(toStringHex(bytes[i]));
		}
		System.out.print("Item0" + itemIndex + ": " + hexStr.toString().toUpperCase());
		System.out.print(", ");
		
		return hexStr.toString();
	}


	private static String getDate(byte[] bytes){
		String hexStr = toStringHex(bytes[3]) + toStringHex(bytes[2])
				        + toStringHex(bytes[1]) + toStringHex(bytes[0]);
		cal.setTimeInMillis(((long)Integer.parseInt(hexStr, 16))*1000);
		System.out.print("Date: " + sdf.format(cal.getTime()));
		System.out.print(", ");
		
		return hexStr;
	}
	
	public static String toStringHex(byte value) {
		if(value < 0) value += 256; 
		if(value >= 0 && value <= 9) 
			return "0" + value;
		else
			return Integer.toHexString(value&0xFF);
	}
}
儒林外史 2014-04-18
  • 打赏
  • 举报
回复
日期字段转换的不正确。都是“19700117”,字段少了一个Item06。
儒林外史 2014-04-18
  • 打赏
  • 举报
回复
引用 14 楼 lxbccsu 的回复:
[quote=引用 楼主 u014301433 的回复:] 之前问题描述不够清楚,今天再发一个帖子。主要就是想把一个十六进制文本文件转换成十进制的CSV文件。 在本地D盘上有一个以十六进制存储的文本文件。此文件包含了很多个数据块,每个数据块在实际业务中是同一个ID下的多条记录(每条记录的字段都是一样的)。每个数据块都是以四个FF开始作为标识。用UE打开如下所示: 第一行是文件头信息,这个数据不需要,直接过滤掉即可。 以FF FF FF FF开头的每个数据块包含九个字段的数据内容。分别是ID、IDName、Date、Item01、Item02、Item03、Item04、Item05、Item06。其中,ID和IDName字段的数据只在每个数据块中的第一行和第二行出现一次,后面的七个字段内容是多次出现,即每两行一条记录,代表具体某一天的数据记录情况。 举第一个数据块为例: ID ——53 48 36 30 30 30 30 30,用八个进制符位来表示,这个要转换成十进制的字符串。 IDName ——C6 D6 B7 A2 D2 F8 D0 D0,这个字段内容也是用八个进制符位来表示,这个也要转换成十进制的字符串。 注:每个数据块的第一行和第二行,只有上面16个进制符位的数据有用,这两行中剩余的其他16个进制符位数据不需要,直接跳过。 Date ——80 01 3A 53,这个日期字段的内容需要反向读取(即53 3A 01 80)来转换成十进制整型。它是以毫秒存储的,需要转换成短日期型,即不包含时间的日期(比如20140403)。 Item01 ——5C 8F 1A 41,这个字段内容需要转换成十进制浮点型,也是反向读取。 Item02 ——A4 70 1D 41,也是转换成十进制浮点型,反向读取。 Item03 ——7B 14 1A 41,转换成十进制浮点型,反向读取。 Item04 ——14 AE 1B 41,转换成十进制浮点型,反向读取。 Item05 ——F0 E0 93 49,转换成十进制浮点型,反向读取。 Item06 ——BA 69 8C 4E,转换成十进制浮点型,反向读取。 这个数据块内剩余的数据都是每两行为一条记录,重复上面Date到Item06这个七个字段的内容。 另外,上面的这九个字段的内容,除了ID和IDName两个字段的内容进行读取时不需要反向读取,其他均需要反向读取,然后转换成要求的不同数据类型的十进制数据。 我需要的就是按上面这样将十六进制的文本文件转换成含不同数据类型的十进制的CSV文件。
接上面写了下编码与解码的完整例子,全贴出来,自己改改优化下: 没有对Item1到5做什么处理,原样读出。

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Calendar;

public class HexEecodeAndDecodeDemo {

	static Calendar cal = Calendar.getInstance();
	static SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
	
	static String fileFullPath = "E:/data.dat";//Change it to the actual file path
	
	public static void main(String[] args) {
		try {
			writeHexFile();
			readHexFile();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	
	public static void readHexFile()throws Exception{
		DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(fileFullPath)));
		in.skipBytes(16);
		
		byte[] bytes = new byte[16];
		int nCounts = 0;
		
		while((in.read(bytes)) != -1){
			String hexStr = toStringHex(bytes[0]) + toStringHex(bytes[1]) 
							+ toStringHex(bytes[2]) + toStringHex(bytes[3]);
			if(hexStr.equalsIgnoreCase("FFFFFFFF")){
				nCounts = 1;
			}else{
				nCounts++;
			}
			
			if(nCounts > 2){
				getDateAndItemx(bytes, nCounts);
			}else{
				getIDAndIDName(bytes, nCounts);
			}
		}
		
		in.close();
	}
	
	
	private static void getIDAndIDName(byte[] bytes, int nCounts) {
		if(nCounts == 1){
			System.out.print("ID: " + new String(bytes, 4, 8));
			System.out.print(", ");
		}else{
			System.out.print("IDName: " + new String(bytes, 4, 8, Charset.forName("GBK")));
			System.out.print(": ");
			System.out.println();
		}
		
	}


	private static void getDateAndItemx(byte[] bytes, int nCounts) {
		if(nCounts%2 == 0){
			getItemX(bytes, 0, 4, 3);
			getItemX(bytes, 4, 4, 4);
			getItemX(bytes, 8, 4, 5);
			System.out.println();
		}else{
			getDate(bytes);
			getItemX(bytes, 4, 4, 1);
			getItemX(bytes, 8, 4, 2);
		}
	}

	private static String getItemX(byte[] bytes, int start, int length, int itemIndex) {
		StringBuilder hexStr = new StringBuilder();
		for(int i = start + length - 1 ; i >= start; i--){
			hexStr.append(toStringHex(bytes[i]));
		}
		System.out.print("Item0" + itemIndex + ": " + hexStr.toString().toUpperCase());
		System.out.print(", ");
		
		return hexStr.toString();
	}


	private static String getDate(byte[] bytes){
		String hexStr = toStringHex(bytes[3]) + toStringHex(bytes[2])
				        + toStringHex(bytes[1]) + toStringHex(bytes[0]);
		cal.setTimeInMillis(Integer.parseInt(hexStr, 16));
		System.out.print("Date: " + sdf.format(cal.getTime()));
		System.out.print(", ");
		
		return hexStr;
	}
	
	public static String toStringHex(byte value) {
		if(value < 0) value += 256; 
		if(value >= 0 && value <= 9) 
			return "0" + value;
		else
			return Integer.toHexString(value&0xFF);
	}
	
	
	public static void writeHexFile() throws Exception{
		DataOutputStream out = new DataOutputStream(new FileOutputStream(fileFullPath));
		writeInt(out);
		writeInt(out);
		writeInt(out);
		writeInt(out);
		
		out.writeInt(-1);
		writeID("SH600000", out);
		writeInt(out);
		writeInt(out);
		writeIDName("浦发银行", out);
		writeInt(out);
		
		writeDate(1396310400, out);
		writeItemX(Integer.valueOf("411A8F5C", 16),out);
		writeItemX(Integer.valueOf("411D70A4", 16),out);
		writeItemX(Integer.valueOf("411A147B", 16),out);
		writeItemX(Integer.valueOf("411BAE14", 16),out);
		writeItemX(Integer.valueOf("4993E0F0", 16),out);
		writeItemX(Integer.valueOf("418C69BA", 16),out);
		writeInt(out);
		
		writeDate(1396396800, out);
		writeItemX(Integer.valueOf("411A8F5C", 16),out);
		writeItemX(Integer.valueOf("411D70A4", 16),out);
		writeItemX(Integer.valueOf("411A147B", 16),out);
		writeItemX(Integer.valueOf("411BAE14", 16),out);
		writeItemX(Integer.valueOf("4993E0F0", 16),out);
		writeItemX(Integer.valueOf("418C69BA", 16),out);
		writeInt(out);
		
		
		
		out.writeInt(-1);
		writeID("SH600001", out);
		writeInt(out);
		writeInt(out);
		writeIDName("上海银行", out);
		writeInt(out);
		
		writeDate(1396310400, out);
		writeItemX(Integer.valueOf("411A8F5C", 16),out);
		writeItemX(Integer.valueOf("411D70A4", 16),out);
		writeItemX(Integer.valueOf("411A147B", 16),out);
		writeItemX(Integer.valueOf("411BAE14", 16),out);
		writeItemX(Integer.valueOf("4993E0F0", 16),out);
		writeItemX(Integer.valueOf("418C69BA", 16),out);
		writeInt(out);
		
		writeDate(1396396800, out);
		writeItemX(Integer.valueOf("411A8F5C", 16),out);
		writeItemX(Integer.valueOf("411D70A4", 16),out);
		writeItemX(Integer.valueOf("411A147B", 16),out);
		writeItemX(Integer.valueOf("411BAE14", 16),out);
		writeItemX(Integer.valueOf("4993E0F0", 16),out);
		writeItemX(Integer.valueOf("418C69BA", 16),out);
		writeInt(out);
		
		out.close();
		
	}
	
	private static void writeIDName(String IDName, DataOutputStream out) throws IOException {
		byte[] bytes = IDName.getBytes(Charset.forName("GBK"));
		for(int i=0; i<bytes.length; i++)
		{
			out.writeByte(bytes[i]);
		}
    }

	private static void writeInt(DataOutputStream out)throws IOException{
		out.writeInt(0);
	}


	private static void writeID(String ID, DataOutputStream out) throws IOException {
		byte[] bytes = ID.getBytes();
		for(int i = 0; i < bytes.length; i++)
		{
			out.writeByte(bytes[i]);
		}
	}
	
	private static void writeDate(int milSeconds, DataOutputStream out)throws IOException{
		reverseOrder(milSeconds, out);
	}

	private static void writeItemX(int itemX, DataOutputStream out)throws IOException{
		reverseOrder(itemX, out);
	}
    
	private static void reverseOrder(int value, DataOutputStream out) throws IOException{
		String hexStr = Integer.toHexString(value);
		for(int i = hexStr.length(); i > 0; i -= 2 ){
			out.write(Integer.valueOf(hexStr.substring(i-2, i), 16));
		}
	}
}
[/quote] 附件我上传了:http://download.csdn.net/detail/u014301433/7213471
lxbccsu 2014-04-18
  • 打赏
  • 举报
回复
引用 楼主 u014301433 的回复:
之前问题描述不够清楚,今天再发一个帖子。主要就是想把一个十六进制文本文件转换成十进制的CSV文件。 在本地D盘上有一个以十六进制存储的文本文件。此文件包含了很多个数据块,每个数据块在实际业务中是同一个ID下的多条记录(每条记录的字段都是一样的)。每个数据块都是以四个FF开始作为标识。用UE打开如下所示: 第一行是文件头信息,这个数据不需要,直接过滤掉即可。 以FF FF FF FF开头的每个数据块包含九个字段的数据内容。分别是ID、IDName、Date、Item01、Item02、Item03、Item04、Item05、Item06。其中,ID和IDName字段的数据只在每个数据块中的第一行和第二行出现一次,后面的七个字段内容是多次出现,即每两行一条记录,代表具体某一天的数据记录情况。 举第一个数据块为例: ID ——53 48 36 30 30 30 30 30,用八个进制符位来表示,这个要转换成十进制的字符串。 IDName ——C6 D6 B7 A2 D2 F8 D0 D0,这个字段内容也是用八个进制符位来表示,这个也要转换成十进制的字符串。 注:每个数据块的第一行和第二行,只有上面16个进制符位的数据有用,这两行中剩余的其他16个进制符位数据不需要,直接跳过。 Date ——80 01 3A 53,这个日期字段的内容需要反向读取(即53 3A 01 80)来转换成十进制整型。它是以毫秒存储的,需要转换成短日期型,即不包含时间的日期(比如20140403)。 Item01 ——5C 8F 1A 41,这个字段内容需要转换成十进制浮点型,也是反向读取。 Item02 ——A4 70 1D 41,也是转换成十进制浮点型,反向读取。 Item03 ——7B 14 1A 41,转换成十进制浮点型,反向读取。 Item04 ——14 AE 1B 41,转换成十进制浮点型,反向读取。 Item05 ——F0 E0 93 49,转换成十进制浮点型,反向读取。 Item06 ——BA 69 8C 4E,转换成十进制浮点型,反向读取。 这个数据块内剩余的数据都是每两行为一条记录,重复上面Date到Item06这个七个字段的内容。 另外,上面的这九个字段的内容,除了ID和IDName两个字段的内容进行读取时不需要反向读取,其他均需要反向读取,然后转换成要求的不同数据类型的十进制数据。 我需要的就是按上面这样将十六进制的文本文件转换成含不同数据类型的十进制的CSV文件。
接上面写了下编码与解码的完整例子,全贴出来,自己改改优化下: 没有对Item1到5做什么处理,原样读出。

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Calendar;

public class HexEecodeAndDecodeDemo {

	static Calendar cal = Calendar.getInstance();
	static SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
	
	static String fileFullPath = "E:/data.dat";//Change it to the actual file path
	
	public static void main(String[] args) {
		try {
			writeHexFile();
			readHexFile();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	
	public static void readHexFile()throws Exception{
		DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream(fileFullPath)));
		in.skipBytes(16);
		
		byte[] bytes = new byte[16];
		int nCounts = 0;
		
		while((in.read(bytes)) != -1){
			String hexStr = toStringHex(bytes[0]) + toStringHex(bytes[1]) 
							+ toStringHex(bytes[2]) + toStringHex(bytes[3]);
			if(hexStr.equalsIgnoreCase("FFFFFFFF")){
				nCounts = 1;
			}else{
				nCounts++;
			}
			
			if(nCounts > 2){
				getDateAndItemx(bytes, nCounts);
			}else{
				getIDAndIDName(bytes, nCounts);
			}
		}
		
		in.close();
	}
	
	
	private static void getIDAndIDName(byte[] bytes, int nCounts) {
		if(nCounts == 1){
			System.out.print("ID: " + new String(bytes, 4, 8));
			System.out.print(", ");
		}else{
			System.out.print("IDName: " + new String(bytes, 4, 8, Charset.forName("GBK")));
			System.out.print(": ");
			System.out.println();
		}
		
	}


	private static void getDateAndItemx(byte[] bytes, int nCounts) {
		if(nCounts%2 == 0){
			getItemX(bytes, 0, 4, 3);
			getItemX(bytes, 4, 4, 4);
			getItemX(bytes, 8, 4, 5);
			System.out.println();
		}else{
			getDate(bytes);
			getItemX(bytes, 4, 4, 1);
			getItemX(bytes, 8, 4, 2);
		}
	}

	private static String getItemX(byte[] bytes, int start, int length, int itemIndex) {
		StringBuilder hexStr = new StringBuilder();
		for(int i = start + length - 1 ; i >= start; i--){
			hexStr.append(toStringHex(bytes[i]));
		}
		System.out.print("Item0" + itemIndex + ": " + hexStr.toString().toUpperCase());
		System.out.print(", ");
		
		return hexStr.toString();
	}


	private static String getDate(byte[] bytes){
		String hexStr = toStringHex(bytes[3]) + toStringHex(bytes[2])
				        + toStringHex(bytes[1]) + toStringHex(bytes[0]);
		cal.setTimeInMillis(Integer.parseInt(hexStr, 16));
		System.out.print("Date: " + sdf.format(cal.getTime()));
		System.out.print(", ");
		
		return hexStr;
	}
	
	public static String toStringHex(byte value) {
		if(value < 0) value += 256; 
		if(value >= 0 && value <= 9) 
			return "0" + value;
		else
			return Integer.toHexString(value&0xFF);
	}
	
	
	public static void writeHexFile() throws Exception{
		DataOutputStream out = new DataOutputStream(new FileOutputStream(fileFullPath));
		writeInt(out);
		writeInt(out);
		writeInt(out);
		writeInt(out);
		
		out.writeInt(-1);
		writeID("SH600000", out);
		writeInt(out);
		writeInt(out);
		writeIDName("浦发银行", out);
		writeInt(out);
		
		writeDate(1396310400, out);
		writeItemX(Integer.valueOf("411A8F5C", 16),out);
		writeItemX(Integer.valueOf("411D70A4", 16),out);
		writeItemX(Integer.valueOf("411A147B", 16),out);
		writeItemX(Integer.valueOf("411BAE14", 16),out);
		writeItemX(Integer.valueOf("4993E0F0", 16),out);
		writeItemX(Integer.valueOf("418C69BA", 16),out);
		writeInt(out);
		
		writeDate(1396396800, out);
		writeItemX(Integer.valueOf("411A8F5C", 16),out);
		writeItemX(Integer.valueOf("411D70A4", 16),out);
		writeItemX(Integer.valueOf("411A147B", 16),out);
		writeItemX(Integer.valueOf("411BAE14", 16),out);
		writeItemX(Integer.valueOf("4993E0F0", 16),out);
		writeItemX(Integer.valueOf("418C69BA", 16),out);
		writeInt(out);
		
		
		
		out.writeInt(-1);
		writeID("SH600001", out);
		writeInt(out);
		writeInt(out);
		writeIDName("上海银行", out);
		writeInt(out);
		
		writeDate(1396310400, out);
		writeItemX(Integer.valueOf("411A8F5C", 16),out);
		writeItemX(Integer.valueOf("411D70A4", 16),out);
		writeItemX(Integer.valueOf("411A147B", 16),out);
		writeItemX(Integer.valueOf("411BAE14", 16),out);
		writeItemX(Integer.valueOf("4993E0F0", 16),out);
		writeItemX(Integer.valueOf("418C69BA", 16),out);
		writeInt(out);
		
		writeDate(1396396800, out);
		writeItemX(Integer.valueOf("411A8F5C", 16),out);
		writeItemX(Integer.valueOf("411D70A4", 16),out);
		writeItemX(Integer.valueOf("411A147B", 16),out);
		writeItemX(Integer.valueOf("411BAE14", 16),out);
		writeItemX(Integer.valueOf("4993E0F0", 16),out);
		writeItemX(Integer.valueOf("418C69BA", 16),out);
		writeInt(out);
		
		out.close();
		
	}
	
	private static void writeIDName(String IDName, DataOutputStream out) throws IOException {
		byte[] bytes = IDName.getBytes(Charset.forName("GBK"));
		for(int i=0; i<bytes.length; i++)
		{
			out.writeByte(bytes[i]);
		}
    }

	private static void writeInt(DataOutputStream out)throws IOException{
		out.writeInt(0);
	}


	private static void writeID(String ID, DataOutputStream out) throws IOException {
		byte[] bytes = ID.getBytes();
		for(int i = 0; i < bytes.length; i++)
		{
			out.writeByte(bytes[i]);
		}
	}
	
	private static void writeDate(int milSeconds, DataOutputStream out)throws IOException{
		reverseOrder(milSeconds, out);
	}

	private static void writeItemX(int itemX, DataOutputStream out)throws IOException{
		reverseOrder(itemX, out);
	}
    
	private static void reverseOrder(int value, DataOutputStream out) throws IOException{
		String hexStr = Integer.toHexString(value);
		for(int i = hexStr.length(); i > 0; i -= 2 ){
			out.write(Integer.valueOf(hexStr.substring(i-2, i), 16));
		}
	}
}
儒林外史 2014-04-14
  • 打赏
  • 举报
回复
日期那个字段是以秒存储的,还需要转化成短日期型。
儒林外史 2014-04-14
  • 打赏
  • 举报
回复
引用 9 楼 preferme 的回复:
楼主对数据的编码,或者,数据结构 的了解,很缺乏呀。
上一个贴子就存在数据格式没有明确的问题,
这个贴子,倒是说明了,可惜很多地方都不明确,甚至不正确。

还有数据编码方面的知识,感觉也是一塌糊涂。
这些数据解析起来还是比较麻烦的。


不是计算机专业科班毕业的,自学JAVA基础不够好,嗯,以后是加强数据结构和数据编码方面的基础。



以上举的是以第一个数据块为例
冰思雨 2014-04-14
  • 打赏
  • 举报
回复
楼主对数据的编码,或者,数据结构 的了解,很缺乏呀。 上一个贴子就存在数据格式没有明确的问题, 这个贴子,倒是说明了,可惜很多地方都不明确,甚至不正确。 还有数据编码方面的知识,感觉也是一塌糊涂。 这些数据解析起来还是比较麻烦的。
tony4geek 2014-04-13
  • 打赏
  • 举报
回复
顶起来顶起来
儒林外史 2014-04-13
  • 打赏
  • 举报
回复
找了很多资料都没有说到对十六进制数据的操作。期待对这方面了解的高手。自己顶起来。
「已注销」 2014-04-11
  • 打赏
  • 举报
回复
java的话,不知有没有这种api,要不用jni调用本地C++函数
儒林外史 2014-04-11
  • 打赏
  • 举报
回复
各位大侠,大家对这种I/O问题了解的都不多吗?
儒林外史 2014-04-10
  • 打赏
  • 举报
回复
引用 1 楼 zhangyonghui2117 的回复:
楼主得到指定位置的字节就可实现你的需求了,下面是测试过的代码:

#include<stdio.h>
#include <windows.h>

unsigned char ReadByte(char* szFilePath,int noffset){
	HANDLE hHexFile=CreateFile(
		szFilePath,               //被操作的资源名称
		GENERIC_READ|GENERIC_WRITE,      //对资源的读写操作权限
		FILE_SHARE_READ|FILE_SHARE_WRITE,//共享模式
		0,                               //指向安全属性的指针
		OPEN_EXISTING,                   // 如何操作,这里是打开存在的资源
		FILE_ATTRIBUTE_NORMAL,           // 文件属性
		NULL                             //如果不为零,则指定一个文件句柄,新文件将从这个文件中复制扩展属性
		);
	
	LARGE_INTEGER lDistance;            //LARGE_INTEGER结构体,用于SetFilePointer
	unsigned char buf[1];             
	lDistance.QuadPart=noffset*1;//指针距离	
	DWORD dwi;                          //用于ReadFile作参数
	
	//设置指针移动位置,FILE_BEGIN代表从这个资源的开始位置往后的偏移
	SetFilePointer(hHexFile,lDistance.LowPart,&lDistance.HighPart,FILE_BEGIN);
	
	//将数据读入buf
	ReadFile(hHexFile,buf,1,&dwi,NULL);
	CloseHandle(hHexFile);
	
	//得到指定位置的字节,并返回
	unsigned char byNum;
	byNum=buf[0];
	return byNum;

}


int main(void)
{

for (int noffset = 0; noffset < 10 ; noffset++)
{
	unsigned char byRes=ReadByte("D:\\HexFile.dat",noffset);
	printf("第%d个字节为:%02X \n",noffset,byRes);

}

      return 0;
}
可以用JAVA实现吗?不想再去折腾C了。
「已注销」 2014-04-10
  • 打赏
  • 举报
回复
忘了附上窗口结果:
「已注销」 2014-04-10
  • 打赏
  • 举报
回复
楼主得到指定位置的字节就可实现你的需求了,下面是测试过的代码:

#include<stdio.h>
#include <windows.h>

unsigned char ReadByte(char* szFilePath,int noffset){
HANDLE hHexFile=CreateFile(
szFilePath, //被操作的资源名称
GENERIC_READ|GENERIC_WRITE, //对资源的读写操作权限
FILE_SHARE_READ|FILE_SHARE_WRITE,//共享模式
0, //指向安全属性的指针
OPEN_EXISTING, // 如何操作,这里是打开存在的资源
FILE_ATTRIBUTE_NORMAL, // 文件属性
NULL //如果不为零,则指定一个文件句柄,新文件将从这个文件中复制扩展属性
);

LARGE_INTEGER lDistance; //LARGE_INTEGER结构体,用于SetFilePointer
unsigned char buf[1];
lDistance.QuadPart=noffset*1;//指针距离
DWORD dwi; //用于ReadFile作参数

//设置指针移动位置,FILE_BEGIN代表从这个资源的开始位置往后的偏移
SetFilePointer(hHexFile,lDistance.LowPart,&lDistance.HighPart,FILE_BEGIN);

//将数据读入buf
ReadFile(hHexFile,buf,1,&dwi,NULL);
CloseHandle(hHexFile);

//得到指定位置的字节,并返回
unsigned char byNum;
byNum=buf[0];
return byNum;

}


int main(void)
{

for (int noffset = 0; noffset < 10 ; noffset++)
{
unsigned char byRes=ReadByte("D:\\HexFile.dat",noffset);
printf("第%d个字节为:%02X \n",noffset,byRes);

}

return 0;
}

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧