使用fwrite写入大文件出现损坏,求PHP脚本修复帮助
Fixing File Corruption Issues with Your PHP DCC File-Writing Script
Hey there, let's figure out why your PHP file-writing script is causing corruption, especially with large files. I’ve looked at your code and spotted a few key issues that are likely the culprit, plus some best practices to fix them for good.
What’s Wrong with the Original Script?
Your savetofile() function has two critical problems:
fgets()is text-oriented, not binary-safe:fgets()stops reading when it hits a newline character (\nor\r\n). If your DCC stream contains binary data (like images, archives, or other non-text files), any byte that matches a newline will truncate the chunk you’re reading—leading to missing data and corrupted files.- Only reads one chunk: The function only reads 512 bytes once, so it’ll never fully write large files. You need to loop until the entire stream is processed.
Fixed Script with Binary-Safe Handling
Here’s a revised version of your function that addresses these issues, plus adds error checking to catch write failures:
function saveToFile($dccStream, $fileHandle) { $totalBytesWritten = 0; $chunkSize = 512; // Keep your original chunk size, or adjust to 4096 for better performance // Loop until we reach the end of the DCC stream while (!feof($dccStream)) { // Read a binary-safe chunk from the stream $chunk = fread($dccStream, $chunkSize); if ($chunk === false) { throw new RuntimeException("Failed to read from DCC stream"); } $chunkLength = strlen($chunk); if ($chunkLength === 0) { break; // No more data to read } // Write the chunk to the file, and verify all bytes were written $bytesWritten = fwrite($fileHandle, $chunk); if ($bytesWritten === false || $bytesWritten !== $chunkLength) { throw new RuntimeException( "File write failed: only wrote $bytesWritten out of $chunkLength bytes" ); } $totalBytesWritten += $bytesWritten; } return $totalBytesWritten; }
How to Use This Function Correctly
To avoid further corruption, make sure you open both your DCC stream and output file in binary mode (using rb/wb flags). This prevents Windows systems from automatically converting newline characters, which breaks binary files.
// Example usage $dccSource = "path/to/your/dcc/stream"; // Replace with your actual stream source $outputFile = "path/to/save/file.bin"; // Replace with your target file path // Open DCC stream in binary read mode $dccStream = fopen($dccSource, 'rb'); if (!$dccStream) { die("Failed to open DCC stream: " . error_get_last()['message']); } // Open output file in binary write mode (overwrites existing file) $fileHandle = fopen($outputFile, 'wb'); if (!$fileHandle) { fclose($dccStream); die("Failed to open output file: " . error_get_last()['message']); } try { $totalBytes = saveToFile($dccStream, $fileHandle); echo "Success! Wrote $totalBytes bytes to $outputFile"; } catch (RuntimeException $e) { echo "Error: " . $e->getMessage(); } finally { // Always close file handles to avoid resource leaks fclose($fileHandle); fclose($dccStream); }
Key Best Practices to Remember
- Binary mode is non-negotiable: Use
rbfor reading andwb/abfor writing when dealing with non-text files. - Avoid global variables: Pass streams/file handles as parameters instead of relying on
$GLOBALS—this makes your code more reusable and less prone to bugs. - Check return values: Both
fread()andfwrite()can fail silently if you don’t check their return values. Always verify that you’ve read/written the expected number of bytes. - Use reasonable chunk sizes: 512 bytes works, but 4096 bytes (4KB) is closer to typical filesystem block sizes and can improve performance for large files.
内容的提问来源于stack exchange,提问作者Ikuria
相关产品推荐
相关产品推荐

