2015-07-03 3 views
0

У меня есть трудность при чтении файла содержит цену акций, которая находится в двоичном формате. Я пытаюсь найти ответ здесь и искать в любом учебнике по использованию DataInputStream, но все равно не повезло. Ни один из них не работает.Чтение двоичного файла с использованием java.io.DataInputStream приводит к неправильному значению

Я также прочитал о больших и малых преобразованиях endian в Java, но он по-прежнему дает мне неправильное значение. Есть ли у кого-нибудь опыт чтения файла * .mkt с помощью Java? Я получил код, который работает нормально, но написан на C, но требование переписать его в Java.

Цель метода, чтобы получить несколько поля из каждого блока двоичных данных, как указано

if (j == 1 || j == 4 || j == 9 || j == 11 || j == 12 || j == 13 || j == 14)

Ниже спецификации для двоичных данных и кода я написал для тестирования.

HEADER

перекодировать -> Короткие 2 Б
Отметка -> Long 4 байта
Сообщение -> Короткие 2 байта

DATA

маркеров безопасности -> Короткие 2 байта
Последний Торговали Цена -> 4 байта
Best Buy Количество -> Long 4 Bytes
Best Buy Цена -> Long 4 байтами
Лучший Sell Количество -> 4 байта
Лучшая Цена продажи -> 4 байта
Всего Торговали Количество -> 4 байта
Средняя Торговали Цена -> Long 4 Bytes
Цена открытия -> 4 байта
Высокая цена -> 4 байта
низкий Цена -> Длинные 4 байт
ClosePrice -> 4 байта
Наполнитель -> 4 байта (Blank)

Итого 50 Bytes

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 ... 

Сэм PLE данных Transcode, Отметка, MessageLength, SecurityToken, LastTradedPrice, BestBuyQuantity, BestBuyPrice, BestSellQuantity, BestSellPrice, TotalTradedQuantity, AverageTradedPrice, OpenPrice, HighPrice, LowPrice, ClosePrice, Бланк

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

Если это дублирует другой вопрос или есть ответ, пожалуйста, помогите мне точку на этот вопрос/ответ, потому что я теперь я отчаялся (потратил половину дня, чтобы заставить его работать), и у меня ограниченные знания в этой бинарной вещи. Благодарю.

+1

Java 'long' - это 8 байтов, а не 4 байта. – Kayaman

+0

Пробовал переходить на чтение с 'readInt' и' readShort', но все еще получил неправильное значение – kw1312

+0

Боже, ваш код ужасен. Удерживайте ... – Kayaman

ответ

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) и, конечно, разные типы данных. Просто прочтите файл строки за строкой (или в 50 байтовых кусках) с помощью ByteBuffer.

+0

Я попробовал ваше предложение и получил тот же результат с 'readShort' из DataInputStream. Вывод распечатки выше *** 1280 ***, тогда как это должно быть *** 5 ***, как я описал в образцах данных. – kw1312

+0

Можете ли вы разместить шестнадцатеричное значение этого файла (с помощью шестнадцатеричного редактора, такого как ультра-редактирование)? В Java Short '5' находится в двоичном формате: '0000000000000101' или это в шестнадцатеричном виде:' 0005', Short 58 - '0000000000111010' в двоичном формате или' 003A' в шестнадцатеричном формате – hinneLinks

+0

Это его проблема с Endian-Problem try .reverseBytes (numS); ' – hinneLinks

0

Если вы используете byteSequences, вы используете readLong для чтения значений, состоящих из 32-битных чисел (4 байта), но в Java на самом деле на самом деле 64-битное значение (8 байт), поэтому вы заканчиваете чтение двух значений.

+0

, как указано в спецификации. для Timestamp его тип значения длинный 4 байта. Итак, есть ли у вас какой-либо трюк или предложение, как использовать это, используя один из методов, предоставляемых DataInputStream? – kw1312

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 по сравнению с unsignedness, по крайней мере, некоторые из полей данных.

Edit: Так как ваши данные на самом деле в 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); 
+0

Просто попробовал. Все еще не работает. – kw1312

+0

Ваши данные имеют «неправильную» сущность (маленький конец 5 - большой конец 1280). У Guava есть LittleEndianDataInputStream. – Kayaman

Смежные вопросы