2016-05-22 2 views
1

Я пытаюсь написать C# алгоритм, чтобы получить хэш от интернет-видео-файла для поиска субтитров на (https://trac.opensubtitles.org/projects/opensubtitles/wiki/HashSourceCodes)Что не так с моим алгоритмом хэша OSDB?

Моя идея заключается в том, что алгоритм подается URL-адрес в видеофайл и возвращает хэш. Просто. Проблема в том, что я не получаю правильное значение. Согласно странице, с которой я связан, this file должен вернуть 8e245d9679d31e12, но я получаю 00c4fcb4aa6f763e. Вот мой C#:

public static async Task<byte[]> ComputeMovieHash(string filename) 
{ 
    long filesize = 0; 

    //Get File Size 
    HttpWebRequest req = (HttpWebRequest)WebRequest.Create(filename); 
    req.Method = "HEAD"; 
    var resp = await req.GetResponseAsync(); 
    filesize = resp.ContentLength; 
    long lhash = filesize; 

    //Get first 64K bytes 
    byte[] firstbytes = new byte[0]; 
    using (HttpClient client = new HttpClient()) 
    { 
     client.DefaultRequestHeaders.Add("Range", "bytes=0-65536"); 
     using (HttpResponseMessage response = await client.GetAsync(filename)) 
     { 
      Debug.WriteLine("getting first bytes (bytes=0-65536)"); 
      firstbytes = await response.Content.ReadAsByteArrayAsync(); 
     } 
    } 
    lhash += BitConverter.ToInt64(firstbytes, 0); 

    //Get last 64K bytes 
    byte[] lastbytes = new byte[0]; 
    using (HttpClient client = new HttpClient()) 
    { 
     client.DefaultRequestHeaders.Add("Range", "bytes=" + (filesize - 65536) + "-" + filesize); 
     using (HttpResponseMessage response = await client.GetAsync(filename)) 
     { 
      Debug.WriteLine("getting last bytes (" + "bytes=" + (filesize - 65536) + "-" + filesize + ")"); 
      lastbytes = await response.Content.ReadAsByteArrayAsync(); 
     } 
    } 
    lhash += BitConverter.ToInt64(lastbytes, 0); 

    //Return result 
    byte[] result = BitConverter.GetBytes(lhash); 
    Array.Reverse(result); 
    Debug.WriteLine("RESULT=" + ToHexadecimal(result)); 
    return result; 
} 

Что я делаю неправильно? Я сравнил его код, указанный на opensubtitles.org, и кажется, что она должна иметь один и тот же результат:/

ответ

1

У вас есть несколько ошибок в коде:

  1. Range bytes=0-65536 возвратит вас 6553 байтов, что слишком много.

  2. Вы не вычисляете 64-битную контрольную сумму, потому что BitConverter.ToInt64(firstbytes, 0) берет первые 8 байтов и преобразует их в число, остальные 65536-8 байтов полностью игнорируются.

Фиксированная версия должна быть чем-то вроде этого:

public static async Task<byte[]> ComputeMovieHash(string filename) { 
    long filesize = 0; 

    //Get File Size 
    HttpWebRequest req = (HttpWebRequest) WebRequest.Create(filename); 
    req.Method = "HEAD"; 
    var resp = await req.GetResponseAsync(); 
    filesize = resp.ContentLength; 
    long lhash = filesize; 

    //Get first 64K bytes 
    byte[] firstbytes; 
    using (HttpClient client = new HttpClient()) { 
     client.DefaultRequestHeaders.Add("Range", "bytes=0-65535"); 
     using (HttpResponseMessage response = await client.GetAsync(filename)) { 
      Debug.WriteLine("getting first bytes (bytes=0-65535)"); 
      firstbytes = await response.Content.ReadAsByteArrayAsync(); 
     } 
    } 
    for (int i = 0; i < firstbytes.Length; i += sizeof (long)) { 
     lhash += BitConverter.ToInt64(firstbytes, i); 
    } 

    //Get last 64K bytes 
    byte[] lastbytes; 
    using (HttpClient client = new HttpClient()) { 
     client.DefaultRequestHeaders.Add("Range", "bytes=" + Math.Max(filesize - 65536, 0) + "-" + filesize); 
     using (HttpResponseMessage response = await client.GetAsync(filename)) { 
      Debug.WriteLine("getting last bytes (" + "bytes=" + (filesize - 65536) + "-" + filesize + ")"); 
      lastbytes = await response.Content.ReadAsByteArrayAsync(); 
     } 
    } 
    for (int i = 0; i < lastbytes.Length; i += sizeof (long)) { 
     lhash += BitConverter.ToInt64(lastbytes, i); 
    } 

    //Return result 
    byte[] result = BitConverter.GetBytes(lhash); 
    Array.Reverse(result); 
    return result; 
} 
+0

@ user2950509 также обеспечить (тест), что он правильно работает с файлами с размером менее 64 Кбайт. – Evk

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

  • Нет связанных вопросов^_^