輸入內容為 VBScript (Visual Basic Script) 而非 PHP,副檔名通常為 .vbs。功能:使用 ADO (ActiveX Data Objects) 以文本驅動程式 (Microsoft.Jet.OLEDB.4.0) 開啟大型文本文件,按每 5000 行分割為多個小檔案。
' 參數處理
Set Arg = Wscript.Arguments
If Arg.Count = 0 Then Wscript.Quit
' 解析輸入路徑
path = Left(Arg(0), InStrRev(Arg(0), "\"))
Fname = Replace(Arg(0), path, "")
' ADO 連接文本文件
Set Conn = CreateObject("ADODB.Connection")
Conn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & path & ";Extended Properties=""text;HDR=NO;FMT=Delimited"""
' 統計總行數
Set Rs = CreateObject("ADODB.Recordset")
Rs.Open "Select count(*) FROM " & Fname, Conn, 3, 3, &H0001
allline = Rs(0)
' 逐批次讀取並寫入分割文件
Rs.Open "Select * FROM " & Fname, Conn, 3, 3, &H0001
Do Until Rs.EOF
n = 0
Do Until n = 5000
Set MyTables = fso.CreateTextFile(Arg(0) & i & ".txt", True)
MyTables.WriteLine Rs.Fields.Item(0).Value
Rs.MoveNext
n = n + 1
If Rs.EOF Then Exit Do
Loop
MyTables.Close
i = i + 1
Loop
| 項目 | 說明 | 問題/風險 |
|---|---|---|
| ADO 文本驅動 | 將文本視為資料表,每行一記錄,第一欄為內容 | 需安裝 Jet OLEDB Provider (Windows 內建但 64 位系統需 32 位兼容)、Schema.ini 定義格式 |
| 記憶體模型 | 游標類型 3 (adOpenStatic), 鎖類型 3 (adLockOptimistic) | 大文件可能佔用大量記憶體,非流式處理 |
| 分割邏輯缺陷 | 內層 Do Until n = 5000 中重複 CreateTextFile、WriteLine、Close | 嚴重效能問題:每行開關檔案,磁碟 I/O 暴增;正確做法:外層開檔、內層寫入、批次關閉 |
| 錯誤處理 | On Error Resume Next 忽略所有錯誤 | 靜默失敗,難以排查 (如權限不足、磁碟滿、ADO 連接失敗) |
| 變數作用域 | 未聲明變數 (Option Explicit 缺失) | 拼寫錯誤導致新變數隱性建立,邏輯錯誤難查 |
| 編碼假設 | 預設系統預設編碼 (ANSI/GBK) | UTF-8 文本可能讀取亂碼,需在 Extended Properties 指定 CharacterSet=65001 |
<?php
/**
* 大文本文件分割器
* 用法: php split.php input.txt 5000 [output_dir]
*/
$inputFile = $argv[1] ?? die("Usage: php split.php [output_dir]\n");
$linesPerFile = (int)($argv[2] ?? 5000);
$outputDir = $argv[3] ?? dirname($inputFile) . '/split_out';
if (!is_file($inputFile) || !is_readable($inputFile)) die("Input file not readable\n");
if (!is_dir($outputDir)) mkdir($outputDir, 0755, true);
$handle = fopen($inputFile, 'r');
if (!$handle) die("Cannot open input file\n");
$fileNum = 1;
$lineCount = 0;
$outHandle = null;
$baseName = basename($inputFile);
$baseName = preg_replace('/\.[^.]+$/', '', $baseName);
try {
while (($line = fgets($handle)) !== false) {
if ($lineCount === 0) {
$outFile = $outputDir . '/' . $baseName . '_part' . str_pad($fileNum, 3, '0', STR_PAD_LEFT) . '.txt';
$outHandle = fopen($outFile, 'w');
if (!$outHandle) throw new RuntimeException("Cannot create output file: $outFile");
}
fwrite($outHandle, $line);
$lineCount++;
if ($lineCount >= $linesPerFile) {
fclose($outHandle);
$outHandle = null;
$lineCount = 0;
$fileNum++;
}
}
} finally {
if ($handle) fclose($handle);
if ($outHandle) fclose($outHandle);
}
echo "Done. Split into $fileNum files in $outputDir\n";
?>
fgets 逐行讀取,記憶體常數級 (僅單行緩衝),支援 TB 級大文件。try/finally 確保資源釋放,錯誤可捕獲處理。