2017-12-25 130 views
10

Tôi đang sử dụng hàm bên dưới để tính hàm băm opensubtitles.org cho tệp phim. Nó hoạt động chủ yếu nhưng với các tập tin lớn tôi nhận được lỗi sau.Chức năng băm phụ đề không thành công đối với các tệp lớn

Tôi không thực sự hiểu nó vì luôn có dữ liệu có sẵn.

Có thể anyonep hướng tôi đi đúng hướng không?

PHP Warning: giải nén(): Loại v: không đủ đầu vào, cần 2, có 0 trong file.php trên đường dây 169

function OpenSubtitlesHash($file) 
{ 
    $handle = fopen($file, "rb"); 
    $fsize = filesize($file); 

    $hash = array(3 => 0, 
        2 => 0, 
        1 => ($fsize >> 16) & 0xFFFF, 
        0 => $fsize & 0xFFFF); 

    for ($i = 0; $i < 8192; $i++) 
    { 
     $tmp = ReadUINT64($handle); 
     $hash = AddUINT64($hash, $tmp); 
    } 

    $offset = $fsize - 65536; 
    fseek($handle, $offset > 0 ? $offset : 0, SEEK_SET); 

    for ($i = 0; $i < 8192; $i++) 
    { 
     $tmp = ReadUINT64($handle); 
     $hash = AddUINT64($hash, $tmp);   
    } 

    fclose($handle); 
     return UINT64FormatHex($hash); 
} 

function ReadUINT64($handle) 
{ 
    $u = unpack("va/vb/vc/vd", fread($handle, 8)); 
    return array(0 => $u["a"], 1 => $u["b"], 2 => $u["c"], 3 => $u["d"]); 
} 

function AddUINT64($a, $b) 
{ 
    $o = array(0 => 0, 1 => 0, 2 => 0, 3 => 0); 

    $carry = 0; 
    for ($i = 0; $i < 4; $i++) 
    { 
     if (($a[$i] + $b[$i] + $carry) > 0xffff) 
     { 
      $o[$i] += ($a[$i] + $b[$i] + $carry) & 0xffff; 
      $carry = 1; 
     } 
     else 
     { 
      $o[$i] += ($a[$i] + $b[$i] + $carry); 
      $carry = 0; 
     } 
    } 

    return $o; 
} 

function UINT64FormatHex($n) 
{ 
    return sprintf("%04x%04x%04x%04x", $n[3], $n[2], $n[1], $n[0]); 
} 
+0

Hãy chỉ cho chúng ta để dòng [email protected] – Justinas

+0

trong '$ u = unpack (" va/vb/vc/vd ", fread ($ handle, 8));' nếu bạn làm '$ var = fread ($ handle, 8); var_dump ($ var);' cái gì là đầu ra? nó thực sự đọc dữ liệu? – Tschallacka

Trả lời

1

Bạn không bao giờ kiểm tra xem $ xử lý của bạn có bất kỳ resoure, khi $ xử lý của bạn là null hay sai bạn sẽ nhận được lỗi tương tự

PHP Warning: unpack(): Type v: not enough input, need 2, have 0 in file.php on line 169 

Vì vậy, thêm một tấm séc trước khi bạn làm điều gì đó với $ xử lý

if(!is_null($handle)){ 
    // Do something.. 
} 
5

Nếu bạn cung cấp một số thông tin bổ sung: phiên bản hệ thống, phiên bản php, kích thước tệp lớn, loại tệp (tệp đơn giản, url, v.v) - nó sẽ cung cấp thêm thông tin cho câu trả lời chính xác.

Giả thiết chính là bạn đang sử dụng hệ thống 32 bit và gặp sự cố với filsize với các tệp lớn hơn 2GB. Từ tài liệu:

Lưu ý: Vì loại số nguyên của PHP được ký và nhiều nền tảng sử dụng số nguyên 32 bit, một số chức năng hệ thống tệp có thể trả lại kết quả không mong muốn cho các tệp lớn hơn 2GB.

Bạn có thể nhận sai giá trị filesize và do đó không thể đọc chính xác các byte theo sau. This comment giải thích cách nhận kích thước tệp lớn hơn và cũng lưu ý rằng fseek sử dụng int nội bộ để bạn không thể đặt con trỏ sau ngưỡng 2GB. Bạn sẽ cần phải fread đến vị trí này.

Có giả thuyết khác có thể được kiểm tra:

  • fread có thể đọc dữ liệu hơn yêu cầu theo một số circustances:

    nếu dòng được đọc đệm và nó không đại diện cho một tập tin đơn giản, tại nhất một lần đọc lên đến một số byte bằng kích thước chunk (thường là 8192) được tạo ra; tùy thuộc vào dữ liệu đã lưu trước đó, kích thước của dữ liệu được trả về có thể lớn hơn kích thước đoạn.

  • stat bộ nhớ cache giúp bạn không nhận được giá trị kích thước tệp chính xác;
0

Bạn không cần và không nên tính tổng kích thước tệp.Nếu filesize vượt PHP_INT_MAX thì kết quả sẽ không chính xác,

Một giải pháp tốt hơn là sử dụng fseek() từ ngày kết thúc của tập tin:

fseek($handle, -65536, SEEK_END); 
Các vấn đề liên quan