我在阅读包含二进制格式股票价格的文件时遇到困难。我一直在尝试浏览这里的答案,并使用谷歌搜索任何使用DataInputStream的教程,但仍然没有运气。他们都没有工作。
我还读过Java中的大小端转换,但它仍然给我错误的值。有没有人有使用Java阅读* .mkt文件的经验?我得到的代码工作正常,但它是用C编写的,但要求是用Java重写它。
该方法的目的是从
指定的每个二进制数据块中获取几个字段 if (j == 1 || j == 4 || j == 9 || j == 11 || j == 12 || j == 13 || j == 14)
下面是二进制数据和我为测试编写的代码的规范。
标题
转码 - >短2字节
时间戳 - >长4字节
消息 - >短2字节数据
安全令牌 - >短2字节
最后交易价格 - >长4字节
百思买数量 - >长4字节
百思买价格 - >长4字节
畅销数量 - >长4字节
最畅销价格 - >长4字节
总交易数量 - >长4字节
平均交易价格 - >长4字节
开盘价 - >长4字节
高价 - >长4字节
低价 - >长4字节
ClosePrice - >长4字节
填充物 - >长4字节(空白)
总共50个字节
public static void main(String[] args) throws Exception {
FileInputStream inputStream = new FileInputStream(new File("<Path to the file>.mkt"));
List<String> results = readPriceFromStream(inputStream);
inputStream.close();
System.out.println(results.get(0));
}
public static List<String> readPriceFromStream(InputStream sourceInputStream) throws Exception {
List<String> result = new ArrayList<>();
DataInputStream inputStream = new DataInputStream(sourceInputStream);
int[] byteSequences = new int[]{2, 4, 2, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4};
int len = 50;
for (int i = 1; i <= inputStream.available(); i += len) {
StringBuilder sb = new StringBuilder();
int read = 0;
for (int j = 0; j < byteSequences.length; j++) {
byte[] buffer = new byte[byteSequences[j]];
if (j == 1 || j == 4 || j == 9 || j == 11 || j == 12 || j == 13 || j == 14) {
try {
sb.append(Integer.valueOf(inputStream.readLong())).append(",");
} catch (Exception e) {
e.printStackTrace();
sb.append("0").append(",");
}
} else {
read = inputStream.read(buffer, 0, byteSequences[j]);
}
}
if (read <= -1) {
break;
} else {
String price = sb.toString();
if (price.length() > 0) {
price = price.substring(0, price.lastIndexOf(","));
result.add(price);
}
}
}
if (result.size() > 0) {
result.remove(0);
}
inputStream.close();
return result;
}
**以下是用C **编写的代码片段
for(i = 0; i <= fileLen; i=i+58) {
fread(&TransCode, sizeof(signed short int), 1, input_filename);
fread(&TimeStamp, sizeof(signed long int), 1, input_filename);
... Truncated for clarity ...
示例数据
Transcode,Timestamp,MessageLength,SecurityToken,LastTradedPrice,BestBuyQuantity,BestBuyPrice,BestSellQuantity,BestSellPrice,TotalTradedQuantity,AverageTradedPrice,OpenPrice,HighPrice,LowPrice,ClosePrice,Blank
5,1435905898,58,7,34600,1,34585,29,34600,47479,34777,34560,35100,34500,34670,0
来自main(String[] args)
-2416744146710362880,-615304298158882816,-7614115823107390437,149649579050240,22110525258626,139753974434839,144387995842138645
如果这是重复另一个问题或之前已经回答,请帮助指出我的问题/答案因为我现在绝望(已经花了半天试图使它工作)我对这种知识知之甚少二进制的东西。感谢。
答案 0 :(得分:1)
丢失所有for (int i = 1; i <= inputStream.available(); i += len) {
内容。你做错了什么。
在DataInputStream inputStream = new DataInputStream(sourceInputStream);
之后创建一个类似于此的循环...
try {
while(true) { // An EOFException is thrown when there's no more data
short transcode = inputStream.readShort();
int timestamp = inputStream.readInt();
short message = inputStream.readShort();
// and so on
}
} catch(EOFException e) {
// File processed
}
不要忘记Java的签名与至少某些数据字段的无符号性。
编辑:由于您的数据实际上是Little Endian格式,因此最好使用ByteBuffer
类似的hinneLinks建议:
Path path = Paths.get("path/to/file");
byte[] byteArray= Files.readAllBytes(path);
ByteBuffer bbuffer = ByteBuffer.wrap(byteArray);
bbuffer.order(ByteOrder.LITTLE_ENDIAN); // Set the byte order
short numS = bbuffer.getShort();
System.out.println("short: " + numS);
答案 1 :(得分:1)
尝试
Path path = Paths.get("path/to/file");
byte[] byteArray= Files.readAllBytes(path);
ByteBuffer bbuffer = ByteBuffer.wrap(byteArray);
short numS = bbuffer.getShort();
System.out.println("short: " + numS);
如果Endian错误(例如1280而不是5),请尝试Short.reverseBytes(numS);
获取单个值,或bbuffer.order(ByteOrder.LITTLE_ENDIAN);
获取所有元素。
java.nio.ByteBuffer
也支持阅读特定职位,例如java.nio.ByteBuffer.getShort(int)
当然还有不同的数据类型。
只需使用ByteBuffer
逐行(或50字节块)读取文件。
答案 2 :(得分:0)
查看byteSequences
中您使用readLong
读取32位数字(4字节)值的值,但java中的长度实际上是64位值(8字节),所以你最终会读到两个值。