php合并txt文件,编码问题

时间:2017-06-28 17:20:01

标签: php

我在stackoverflow上找到了这个代码,来自用户@Attgun:

link:merge all files in directory to one text file

<?php

//Name of the directory containing all files to merge
$Dir = "directory";

//Name of the output file
$OutputFile = "filename.txt";

//Scan the files in the directory into an array
$Files = scandir ($Dir);

//Create a stream to the output file
$Open = fopen ($OutputFile, "w"); //Use "w" to start a new output file from 
zero. If you want to increment an existing file, use "a".

//Loop through the files, read their content into a string variable and 
write it to the file stream. Then, clean the variable.

foreach ($Files as $k => $v) {
    if ($v != "." AND $v != "..") {
        $Data = file_get_contents ($Dir."/".$v);
        fwrite ($Open, $Data);
    }
    unset ($Data);
}

//Close the file stream
fclose ($Open);
?>

代码正常但在合并时,php会在复制的每个文件的开头插入一个字符。我使用的文件编码是UCS-2 LE。 当我将编码更改为ANSI时,我可以查看该字符。

我的问题是我不能使用其他编码而不是UCS-2 LE。

有人可以帮我解决这个问题吗?

编辑:我不想改变文件编码。我想保持相同的编码,而不添加PHP添加另一个字符。

2 个答案:

答案 0 :(得分:0)

大多数PHP字符串函数与编码无关。它们只是将字符串视为字节集合。您可以在b来电附加fopen(),以确保换行不会受损,但代码中的任何内容都不应更改实际编码。

UCS-2(以及它的继承者UTF-16和UTF系列的其他成员)是一种特殊情况,因为Unicode标准定义了两个可能的方向来打印符合多字节字符的单个字节(有一个奇特的名称​​ endianness ),这种方向取决于byte order mark字符的存在,后跟可变数量的字节,这取决于编码并确定字节序的字节顺序。文件。

此类前缀是防止原始文件串联工作的原因。但是,它仍然是一种非常简单的格式。所需的只是从所有文件中删除BOM,但第一个。

说实话,我找不到UCS-2的BOM是什么(它是一个过时的编码,它在大多数Unicode文档中都不再存在)但是由于你有几个样本,你应该能够自己看到它。假设它是the same as in UTF-16FF FE)你只需要省略两个字节,例如:

$Data = file_get_contents ($Dir."/".$v);
fwrite ($Open, substr($Data, 2));

我编写了一个自成一体的例子。我没有任何能够处理UCS-2的编辑器所以我使用了UTF-16 LE。 BOM为0xFFFF(您可以使用像hexed.it这样的十六进制编辑器检查BOM:

file_put_contents('a.txt', hex2bin('FFFE6100'));
file_put_contents('b.txt', hex2bin('FFFE6200'));

$output = fopen('all.txt', 'wb');

$first = true;
foreach (scandir(__DIR__) as $position => $file) {
    if (pathinfo($file, PATHINFO_EXTENSION)==='txt' && $file!=='all.txt') {
        $data = file_get_contents($file);
        fwrite($output, $first ? $data : substr($data, 2));
        $first = false;
    }
}
fclose($output);

var_dump(
    bin2hex(file_get_contents('a.txt')),
    bin2hex(file_get_contents('b.txt')),
    bin2hex(file_get_contents('all.txt'))
);
string(8) "fffe6100"
string(8) "fffe6200"
string(12) "fffe61006200"

正如您所看到的,我们最终在顶部有一个BOM,并且没有其他字节被更改。当然,这假设您的所有文本文件具有相同的编码,编码正是您所想的编码。

答案 1 :(得分:0)

@AlexHowansky激励我去寻找其他方式。

它似乎工作的解决方案没有弄乱文件编码是这样的:

bat文件:

@echo on
copy *.txt all.txt
@pause 

现在,最终文件保留了读取文件的编码。 我的编译器没有像以前那样显示任何错误消息!