2013-12-01 3 views
3

Я пытаюсь написать C# программу, аналогичную той, на этом сайте: http://www.digital-detective.co.uk/freetools/decode.aspDecode найдены встроенные в бинарных файлах

Можете ли вы сказать мне, как я могу преобразовать шестнадцатеричные числа, перечисленные в следующие бюллетени для значений даты/времени.

  • Windows 64 бит (обратный порядок байт) шестнадцатеричное значение FF03D2315FE1C701 должен преобразует в = Sat, 18 August 2007 06:15:37 UTC
  • для Windows 64 битого OLE шестнадцатеричного значения FBE8DF975D3FE340 должно преобразуется в = Sun, 02 December 2007 22:11:42 UTC
  • Unix, 32 бит (большие байты) шестнадцатеричное значение 46C3B400 должен конвертируется в = Thu, 16 August 2007 02:18:40 UTC
  • Apple Mac Absolute шестнадцатеричное значение 219216022 должно преобразуется = Thu, 13 December 2007 05:20:22 UTC
  • HFS 32 бит (прямой порядок байтов) шестнадцатеричное значение CD4E55C3 должно конвертируется в = Mon, 05 November 2007 22:50:53 Local

Я пытался использовать следующий код, чтобы сделать это, но он не возвращает правильный результат:

double decValue = int.Parse("A2C3B446", System.Globalization.NumberStyles.HexNumber); 
System.DateTime dtDateTime = new DateTime(2013, 1, 1, 0, 0, 0, 0); 
dtDateTime = dtDateTime.AddSeconds(decValue).ToLocalTime(); 
Console.WriteLine("Decimal Value: " + decValue); 
Console.WriteLine(dtDateTime); 
+2

Пусть я начинаю с очевидного вопроса: проверили ли вы фактические спецификации для этих форматов? – quetzalcoatl

+0

BTW. вы имеете в виду [этот HFS] (http://en.wikipedia.org/wiki/Hierarchical_File_System)? – quetzalcoatl

ответ

17

Сначала вам понадобится метод утилиты, который считывает байты из потока и обрабатывает значение endian-ness. Это может выглядеть следующим образом:

public static byte[] ReadBytes(Stream s, int size, bool littleEndian) { 
     var bytes = new byte[size]; 
     var len = s.Read(bytes, 0, size); 
     if (len != size) throw new InvalidOperationException("Unexpected end of file"); 
     if (BitConverter.IsLittleEndian != littleEndian) Array.Reverse(bytes); 
     return bytes; 
    } 

даты Окна легко, поддерживаются DateTime.FromFileTimeUtc() непосредственно:

public static DateTime ConvertWindowsDate(byte[] bytes) { 
     if (bytes.Length != 8) throw new ArgumentException(); 
     return DateTime.FromFileTimeUtc(BitConverter.ToInt64(bytes, 0)); 
    } 

Тестирование это с значением:

var date1 = DateReaders.ConvertWindowsDate(DateReaders.ReadBytes(
        new MemoryStream(new byte[]{0xFF,0x03,0xD2,0x31,0x5F,0xE1,0xC7,0x01}), 8, true)); 

Производит {8/18/2007 6:15:37 AM}, как и ожидалось.


Даты OLE просты, поддерживаемые DateTime.FromOADate() непосредственно:

public static DateTime ConvertOLEDate(byte[] bytes) { 
     if (bytes.Length != 8) throw new ArgumentException(); 
     return DateTime.FromOADate(BitConverter.ToDouble(bytes, 0)); 
    } 

Тестирование это с значением:

var date2 = DateReaders.ConvertOLEDate(DateReaders.ReadBytes(
        new MemoryStream(new byte[] {0xFB,0xE8,0xDF,0x97,0x5D,0x3F,0xE3,0x40 }), 8, true)); 

Производит {12/2/2007 10:11:41 PM}


значения даты Unix являются миллисекунд с 1 января 1970 года, 0:00 утра UTC:

public static DateTime ConvertUnixDate(byte[] bytes) { 
     if (bytes.Length != 4) throw new ArgumentException(); 
     return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(
        BitConverter.ToUInt32(bytes, 0)); 
    } 

Тестирование это с вашим значением:

var date3 = DateReaders.ConvertUnixDate(DateReaders.ReadBytes(
        new MemoryStream(new byte[] {0x46,0xC3,0xB4,0x00}), 4, false)); 

Производит {8/16/2007 2:18:40 AM}


Apple Mac абсолютное время is documented зависеть CPU и требует преобразования на машине который породил его. Показанное значение «219216022» является изворотливым, оно представляется десятичным, а не шестнадцатеричным, как и все остальные. Я буду следовать примеру Baldrick с:

public static DateTime ConvertAppleDate(byte[] bytes) { 
    if (bytes.Length != 4) throw new ArgumentException(); 
    return new DateTime(2001, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(
       BitConverter.ToUInt32(bytes, 0)); 
} 

даты HFS являются секунд с 1 января 1904 года, 0:00 AM. Обратите внимание, что даты HFS - это местное время, но даты HFS Plus - UTC. Я предполагаю, местный, так как это результат, который вы документально:

public static DateTime ConvertHFSDate(byte[] bytes) { 
     if (bytes.Length != 4) throw new ArgumentException(); 
     return new DateTime(1904, 1, 1, 0, 0, 0, DateTimeKind.Local).AddSeconds(
        BitConverter.ToUInt32(bytes, 0)); 
    } 

Тестирование это с значением:

var date5 = DateReaders.ConvertHFSDate(DateReaders.ReadBytes(
        new MemoryStream(new byte[] {0xCD,0x4E,0x55,0xC3 }), 4, true)); 

Производит {11/5/2007 10:50:53 PM}

+0

Абсолютное время Apple (несмотря на документацию), как правило, определяется количеством секунд с 1 января 2001 года, хотя я думаю, что это отнюдь не гарантировано. Однако многие сайты цитируют этот подход, и я подозреваю, что это тот, который используется рассматриваемым инструментом. Следующий код дает ожидаемый результат Thu, 13 декабря 2007 г. 05:20:22: var date = new DateTime (2001,01,01) .AddSeconds (219216022); – Baldrick

+0

Спасибо, я буду использовать это. –

+0

@Bald @Hans Я понимаю, что это может быть глупый вопрос, но я подумал, что брошу кубики; Используя метод 'ConvertHFSDate (..)' с байтами из файла 'created on' из файла, результат по-прежнему остается в часе (согласно исследователю), даже когда я меняю 'DateTimeKind', возвращаемый час не изменяется от 3 : 13: 56 (должно быть 2:13:56). Я что-то упустил? .. Спасибо. (Великобритания) – n00dles

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