2010-06-30 32 views
8

Tôi có một mảng đa chiều lớn đã được tuần tự hóa bởi PHP. Nó đã được lưu trữ trong MySQL và trường dữ liệu không đủ lớn ... kết thúc đã bị cắt bỏ ... Tôi cần trích xuất dữ liệu ... unserialize sẽ không hoạt động ... có ai biết mã nào có thể đóng tất cả các mảng ... tính lại độ dài chuỗi ... quá nhiều dữ liệu để thực hiện bằng tay.Regex/mã để sửa lỗi dữ liệu PHP được tuần tự hóa bị lỗi

Rất cám ơn.

+0

Đây có thể là một nguồn tài nguyên hữu ích cho một số người tìm kiếm câu hỏi này - Tôi đã sử dụng nó nhiều lần và nó làm việc tốt mỗi lần: https://github.com/Blogestudio/Fix-Serialization (được cấp điều này có thể sẽ không giúp ích khi phần lớn chuỗi bị cắt - chỉ khi bạn đã thực hiện tìm kiếm và thay thế và độ dài chuỗi là off) – billynoah

Trả lời

-4

Tôi nghĩ điều này gần như không thể. Trước khi bạn có thể sửa chữa mảng của bạn, bạn cần phải biết làm thế nào nó bị hư hỏng. Có bao nhiêu trẻ em mất tích? Nội dung là gì?

Xin lỗi, bạn không thể làm điều đó.

0

Tôi nghi ngờ bất cứ ai sẽ viết mã để lấy mảng đã lưu một phần :) Tôi sửa một thứ như thế này một lần nhưng bằng tay và mất hàng giờ, và sau đó tôi nhận ra tôi không cần phần đó của mảng ...

Trừ khi dữ liệu thực sự quan trọng của nó (và tôi có nghĩa là thực sự quan trọng), bạn muốn được tốt hơn để rời khỏi cái này đi

-1

serializing là hầu như luôn luôn xấu bởi vì bạn không thể tìm kiếm nó trong bất kỳ cách nào. Xin lỗi, nhưng có vẻ như là mặc dù bạn đang lùi vào một góc ...

30

này được tính lại theo chiều dài của các yếu tố trong một mảng serialized:

$fixed = preg_replace_callback(
    '/s:([0-9]+):\"(.*?)\";/', 
    function ($matches) { return "s:".strlen($matches[2]).':"'.$matches[2].'";';  }, 
    $serialized 
); 

Tuy nhiên, nó không hoạt động nếu bạn chuỗi chứa ";. Trong trường hợp đó, không thể tự động sửa chuỗi chuỗi được tuần tự hóa - cần chỉnh sửa thủ công.

+0

làm việc cho tôi như một sự quyến rũ! –

+0

tuyệt vời, cảm ơn :) – aidan

+0

Tôi tự hỏi ma thuật đằng sau điều này là gì :) – Aiphee

1

Sử dụng preg_replace_callback(), thay vì preg_replace(.../e) (vì /e công cụ sửa đổi là deprecated).

$fixed_serialized_String = preg_replace_callback('/s:([0-9]+):\"(.*?)\";/',function($match) { 
    return "s:".strlen($match[2]).':"'.$match[2].'";'; 
}, $serializedString); 

$correct_array= unserialize($fixed_serialized_String); 
-2

Bạn có thể trả lại dữ liệu tuần tự không hợp lệ trở lại bình thường, bằng cách của một mảng :)

str = "a:1:{i:0;a:4:{s:4:\"name\";s:26:\"20141023_544909d85b868.rar\";s:5:\"dname\";s:20:\"HTxRcEBC0JFRWhtk.rar\";s:4:\"size\";i:19935;s:4:\"dead\";i:0;}}"; 

preg_match_all($re, $str, $matches); 

if(is_array($matches) && !empty($matches[1]) && !empty($matches[2])) 
{ 
    foreach($matches[1] as $ksel => $serv) 
    { 
     if(!empty($serv)) 
     { 
      $retva[] = $serv; 
     }else{ 
      $retva[] = $matches[2][$ksel]; 
     } 
    } 

    $count = 0; 
    $arrk = array(); 
    $arrv = array(); 
    if(is_array($retva)) 
    { 
     foreach($retva as $k => $va) 
     { 
      ++$count; 
      if($count/2 == 1) 
      { 
       $arrv[] = $va; 
       $count = 0; 
      }else{ 
       $arrk[] = $va; 
      } 
     } 
     $returnse = array_combine($arrk,$arrv); 
    } 

} 

print_r($returnse); 
9

Tôi đã thử tất cả mọi thứ tìm thấy trong bài viết này và không có gì làm việc cho tôi. Sau những giờ phút đau đây là những gì tôi tìm thấy trong các trang sâu của google và cuối cùng làm việc:

function fix_str_length($matches) { 
    $string = $matches[2]; 
    $right_length = strlen($string); // yes, strlen even for UTF-8 characters, PHP wants the mem size, not the char count 
    return 's:' . $right_length . ':"' . $string . '";'; 
} 
function fix_serialized($string) { 
    // securities 
    if (!preg_match('/^[aOs]:/', $string)) return $string; 
    if (@unserialize($string) !== false) return $string; 
    $string = preg_replace("%\n%", "", $string); 
    // doublequote exploding 
    $data = preg_replace('%";%', "µµµ", $string); 
    $tab = explode("µµµ", $data); 
    $new_data = ''; 
    foreach ($tab as $line) { 
     $new_data .= preg_replace_callback('%\bs:(\d+):"(.*)%', 'fix_str_length', $line); 
    } 
    return $new_data; 
} 

Bạn gọi thói quen như sau:

//Let's consider we store the serialization inside a txt file 
$corruptedSerialization = file_get_contents('corruptedSerialization.txt'); 

//Try to unserialize original string 
$unSerialized = unserialize($corruptedSerialization); 

//In case of failure let's try to repair it 
if(!$unSerialized){ 
    $repairedSerialization = fix_serialized($corruptedSerialization); 
    $unSerialized = unserialize($repairedSerialization); 
} 

//Keep your fingers crossed 
var_dump($unSerialized); 
+0

đã làm việc cho tôi ngay lập tức. nhiều người rất biết ơn! – majick

+0

Bạn hoàn hảo, tôi yêu bạn <3 <3: D Tấn cảm ơn người đàn ông !!! – ThangTD

+0

Cảm ơn bạn rất nhiều! Đây là hy vọng cuối cùng của tôi ... Tôi gần như đã từ bỏ. Bạn là một anh hùng! –

0

Dựa trên @Emil M trả lời Đây là một cố định phiên bản hoạt động với văn bản có dấu ngoặc kép.

function fix_broken_serialized_array($match) { 
    return "s:".strlen($match[2]).":\"".$match[2]."\";"; 
} 
$fixed = preg_replace_callback(
    '/s:([0-9]+):"(.*?)";/', 
    "fix_broken_serialized_array", 
    $serialized 
); 
0

Đoạn mã sau sẽ cố gắng đọc & phân tích chuỗi được tuần tự bị hỏng đệ quy (dữ liệu blob). Ví dụ, nếu bạn được lưu trữ trong chuỗi cột cơ sở dữ liệu quá dài và nó đã bị cắt bỏ. Các số nguyên tố và bool được đảm bảo là hợp lệ, các chuỗi có thể bị cắt bỏ và/hoặc các khóa mảng có thể bị thiếu. Thông lệ có thể hữu ích, ví dụ: nếu khôi phục phần đáng kể (không phải tất cả) dữ liệu là giải pháp đủ cho bạn.

class Unserializer 
{ 
    /** 
    * Parse blob string tolerating corrupted strings & arrays 
    * @param string $str Corrupted blob string 
    */ 
    public static function parseCorruptedBlob(&$str) 
    { 
     // array pattern: a:236:{...;} 
     // integer pattern: i:123; 
     // double pattern: d:329.0001122; 
     // boolean pattern: b:1; or b:0; 
     // string pattern: s:14:"date_departure"; 
     // null pattern:  N; 
     // not supported: object O:{...}, reference R:{...} 

     // NOTES: 
     // - primitive types (bool, int, float) except for string are guaranteed uncorrupted 
     // - arrays are tolerant to corrupted keys/values 
     // - references & objects are not supported 
     // - we use single byte string length calculation (strlen rather than mb_strlen) since source string is ISO-8859-2, not utf-8 

     if(preg_match('/^a:(\d+):{/', $str, $match)){ 
      list($pattern, $cntItems) = $match; 
      $str = substr($str, strlen($pattern)); 
      $array = []; 
      for($i=0; $i<$cntItems; ++$i){ 
       $key = self::parseCorruptedBlob($str); 
       if(trim($key)!==''){ // hmm, we wont allow null and "" as keys.. 
        $array[$key] = self::parseCorruptedBlob($str); 
       } 
      } 
      $str = ltrim($str, '}'); // closing array bracket 
      return $array; 
     }elseif(preg_match('/^s:(\d+):/', $str, $match)){ 
      list($pattern, $length) = $match; 
      $str = substr($str, strlen($pattern)); 
      $val = substr($str, 0, $length + 2); // include also surrounding double quotes 
      $str = substr($str, strlen($val) + 1); // include also semicolon 
      $val = trim($val, '"'); // remove surrounding double quotes 
      if(preg_match('/^a:(\d+):{/', $val)){ 
       // parse instantly another serialized array 
       return (array) self::parseCorruptedBlob($val); 
      }else{ 
       return (string) $val; 
      } 
     }elseif(preg_match('/^i:(\d+);/', $str, $match)){ 
      list($pattern, $val) = $match; 
      $str = substr($str, strlen($pattern)); 
      return (int) $val; 
     }elseif(preg_match('/^d:([\d.]+);/', $str, $match)){ 
      list($pattern, $val) = $match; 
      $str = substr($str, strlen($pattern)); 
      return (float) $val; 
     }elseif(preg_match('/^b:(0|1);/', $str, $match)){ 
      list($pattern, $val) = $match; 
      $str = substr($str, strlen($pattern)); 
      return (bool) $val; 
     }elseif(preg_match('/^N;/', $str, $match)){ 
      $str = substr($str, strlen('N;')); 
      return null; 
     } 
    } 
} 

// usage: 
$unserialized = Unserializer::parseCorruptedBlob($serializedString); 
5

Giải pháp cho tôi:

unserialize(serialize_corrector($serialized_string) ) ;

mã:

function serialize_corrector($serialized_string){ 
    // at first, check if "fixing" is really needed at all. After that, security checkup. 
    if (@unserialize($serialized_string) !== true && preg_match('/^[aOs]:/', $serialized_string)) { 
     $serialized_string = preg_replace_callback('/s\:(\d+)\:\"(.*?)\";/s', function($matches){return 's:'.strlen($matches[2]).':"'.$matches[2].'";'; }, $serialized_string); 
    } 
    return $serialized_string; 
} 

thử trực tuyến:

Serialized String Fixer (online tool)

+0

Chỉ có điều này làm việc cho tôi! Cảm ơn :) –

+0

Làm thế nào nên áp dụng điều này cho một kịch bản WordPress, nơi tôi tìm kiếm và thay thế .sql và dữ liệu serialized ra khỏi đồng bộ? Hãy giúp tôi! – Peanuts

+1

@Peanuts bạn có thể thử khắc phục bằng tay bằng cách sử dụng: http://protectpages.com/tools/serialization-fixer.php –

0

Giải pháp tốt nhất đối với tôi:

$output_array = unserialize(My_checker($serialized_string));

mã:

function My_checker($serialized_string){ 
    // securities 
    if (empty($serialized_string))      return ''; 
    if (!preg_match('/^[aOs]:/', $serialized_string)) return $serialized_string; 
    if (@unserialize($serialized_string) !== false) return $serialized_string; 

    return 
    preg_replace_callback(
     '/s\:(\d+)\:\"(.*?)\";/s', 
     function ($matches){ return 's:'.strlen($matches[2]).':"'.$matches[2].'";'; }, 
     $serialized_string) 
    ; 
} 
Các vấn đề liên quan