PHP開啟一個二進位檔案,修改了內容如何再儲存回去呢?

來源:互聯網
上載者:User
我開啟了一個檔案(二進位)的,然後利用bin2hex函數,將其變成了十六進位的字串,並且修改了其中一個特定位置的數值,現在問題是,我想儲存回去,發現變成了ASCII檔案,請問各位,如何應該儲存成和源檔案格式一樣的代碼呢?

下面是代碼:

$fp=fopen("sample.bin",'rb');
$word='';
while(!feof($fp)){
$buf = bin2hex(fread($fp,48));
$pos = strpos($buf, '02000100'); // 尋找土地

//if $pos == 0 {
// echo "這是土地";
//}
echo $buf;
echo "\n-------------\n";
echo ($pos/2);

echo $buf2=str_replace("02000100","BE010000",$buf);
$word=$word.$buf2;

echo "\n";


}
fclose($fp);

echo $word;

$new= fopen('new.bin','w');
fwrite($new,$word);
fclose($new);
?>


回複討論(解決方案)

一個檔案一種格式,存兩種格式也沒有意義,可以在需要時候再取出來轉換,不用轉為十六進位

1、既然你用 $fp=fopen("sample.bin",' rb'); 開啟檔案,表示你的程式可在 window 系統下工作,那麼寫入時也應 $new= fopen('new.bin','w b');
b 表示二進位方式,window 下必須嚴格區別,linux 下無所謂

2、處理後的 $word 的內容是十六進位表示,你在寫入檔案時並沒有再轉回二進位
可用 $word = pack('H*', $word); 轉換

$word = '';
$from = pack('H*', '02000100');
$target = pack('H*', 'BE010000');
while(!feof($fp)){
$buf = bin2hex(fread($fp,48));
$buf2 = str_replace($from, $target, $buf);
$word .= $buf2;
}

這樣 $word 中依舊是位元據

$word = '';
$from = pack('H*', '02000100');
$target = pack('H*', 'BE010000');
while(!feof($fp)){
$buf = bin2hex(fread($fp,48));
$buf2 = str_replace($from, $target, $buf);
$word .= $buf2;
……

謝謝xuzuning的意見,我按照你的修改了代碼,如下:

$fp=fopen("old.bin",'rb');
$word='';
$from = pack('H*', '02000100');
$target = pack('H*', 'BE010000');
while(!feof($fp)){
$buf = bin2hex(fread($fp,48));
$buf2 = str_replace($from, $target, $buf);
$pos = strpos($buf, '02000100'); // 尋找土地

//if $pos == 0 {
// echo "這是土地";
//}
echo $buf;
echo "\n-------------\n";
echo ($pos/2);
echo $buf2;
//echo $buf2=str_replace("02000100","BE010000",$buf);
$word=$word.$buf2;

echo "\n";


}
fclose($fp);

//echo $word;

$new= fopen('new.bin','wb');
fwrite($new,$word);
fclose($new);
?>

但是產生的new.bin的大小依然是old.bin的兩倍,和之前沒有什麼區別,我的測試環境是在我的WIN2008的伺服器上,IIS7+PHP,您還有什麼建議嗎?

對不起,我 #3 的代碼錯了,應該是這樣
$word = '';
$from = pack('H*', '02000100');
$target = pack('H*', 'BE010000');
while(!feof($fp)){
$buf = fread($fp,48);
$buf2 = str_replace($from, $target, $buf);
$word .= $buf2;
}

完全按二進位方式操作

對不起,我 #3 的代碼錯了,應該是這樣
$word = '';
$from = pack('H*', '02000100');
$target = pack('H*', 'BE010000');
while(!feof($fp)){
$buf = fread($fp,48);
$buf2 = str_replace($from, $target, $buf);
$wo……

感謝,問題解決!

嘮叨說了關鍵了, windows的確區分文本和二進位檔案, 因為文本的末尾是以某個特殊位元組標示的.

WINDOWS下,不太瞭解的同學經常用fgetc函數以文本開啟二進位檔案, 試圖一個位元組一個位元組的讀取, 結果發現只能讀了一半就開始返回EOF了, 其實是因為恰好某個位元組是文本裡的作為結束符的特殊位元組。

但Linux一律以系統API : read返回0作為檔案末,所以b參數是被忽略的。

樓主的作法多餘了, 不就是想找到 土地 兩個字, 然後替換一下嗎 ?
不知道樓主所說的二進位檔案是怎麼產生的, 其實一切都是二進位, 只是在windows下b開啟和非b開啟得到的結果會有區別, 非b開啟和用文字編輯器編輯結果是一致的.

假設你原本的檔案就是一個utf8文字檔,裡面有“土地”兩個字,作法很簡單,UTF8多位元組編碼的,迴圈fread並不一定正好能將完整的“土地”兩個字的位元組讀到一個buffer裡,所以比較好的辦法是file_get_contents,之後直接str_replace("土地", “兄弟”)即, 在C語言裡其實就是記憶體映射後替換字串.

轉什麼十六進位, 純屬多此一舉, 而且迴圈讀是一定有bug的, 可能"土地"兩個字是被拆開讀進來的.

就連vim這種軟體都是記憶體映射的, 檔案太大它也沒辦法, 只能告訴你失敗.

請問怎麼可以調用儲存視窗儲存麼

  • 聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.