0

0

使用PHP高效解析固定宽度数据文件(.out)并导出为CSV或SQL格式

心靈之曲

心靈之曲

发布时间:2025-11-26 11:41:03

|

993人浏览过

|

来源于php中文网

原创

使用PHP高效解析固定宽度数据文件(.out)并导出为CSV或SQL格式

本教程详细介绍了如何使用php处理无分隔符的固定宽度数据文件(.out),并将其转换为更易于处理的csv或sql格式。核心在于利用php的`unpack`函数精确解析每条记录中的固定长度字段,然后通过`fputcsv`函数生成带有指定分隔符的csv文件,为数据转换提供了高效且灵活的解决方案。

理解固定宽度数据格式

固定宽度数据文件是一种常见的数据存储格式,其特点是每条记录中的每个字段都占据预设的固定字符长度,即使字段实际内容较短,也会用空格或其他填充字符补齐。与CSV或JSON等使用分隔符的数据格式不同,固定宽度文件没有明确的分隔符来区分字段,而是依赖于每个字段的起始位置和长度。

挑战:

  • 无分隔符: 无法直接通过逗号、制表符等分隔符进行解析。
  • 精确长度: 必须精确知道每个字段的名称及其对应的字符长度。
  • 空白字符: 空格在固定宽度数据中可能具有双重含义,既可以是填充字符,也可能代表字段的实际值(如NULL或空值)。

示例数据结构:

考虑以下.out文件中的两条记录示例,它们没有分隔符,但每个数据段都占据固定的长度。

立即学习PHP免费学习笔记(深入)”;

I299207075410 07  OCCLUSAL-HP                        LIQ17%                          LMedicis              B000001000000000001EA 8428010080529100   1072363   20030101000000016750000000016750000000000167500200101010000000000000000000000000000000001218000000000000000000000000000000000000000000000000020021231262436018510(W/BRUSH APPLICATOR)     TPLIQ     
 299207085060R01  LUZU                               CRE1%                           SBausch               C000006000000000001EA 8404080054930829 1 1309011   20180105000000590530000000098421700000000902967000000000000000000000000000000000000000000000000000000000000000000000000000000                                     TPCRE     

在这些记录中,即使是空白字符也可能构成一个独立的字段,或者作为某个字段的填充部分。例如,第一条记录的第一个字符是“I”,而第二条记录的第一个字符是空白,这可能表示一个长度为1的字段,其中空白代表NULL值。

PHP解析核心:unpack函数

PHP的unpack函数是处理固定宽度二进制或字符串数据的强大工具。它通过一个格式字符串来定义如何从输入数据中提取各个部分。

unpack函数的基本语法:

array unpack ( string $format , string $data )
  • $format:一个字符串,由一系列格式字符和可选的字段名组成,用于指定如何解析数据。
  • $data:要解析的字符串数据。

格式字符串构建:

对于固定宽度的字符串数据,我们主要使用以下格式字符:

Petalica Paint
Petalica Paint

用AI为你的画自动上色!

下载
  • A:表示一个字符串,它将从数据中读取指定长度的字符。
  • 长度:紧跟在A后面,表示要读取的字符数量。
  • 字段名:可选,用于给提取出的数据命名,使其在返回的关联数组中作为键。

例如,A12id2 表示读取12个字符并将其命名为id2。

为了解析整个固定宽度行,我们需要将所有字段的格式描述连接起来,并用斜杠/分隔,形成一个完整的格式字符串。

实现数据转换的PHP脚本

以下PHP脚本演示了如何读取一个.out文件,解析其固定宽度记录,并将其导出为CSV文件。

 1,      // 例如 'I' 或空白
    'id_number' => 12,
    'code_type' => 5,
    'product_name' => 35,
    'concentration' => 32,
    'manufacturer' => 22,
    'product_code' => 22,
    'batch_number' => 17,
    'status_flag' => 2,    // 可能是单个字符或空白
    'quantity' => 10,
    'details_long' => 186, // 这是一个较长的详细信息字段
    'product_category' => 10
];

// 5. 构建 unpack 格式字符串
$unpackFormats = [];
foreach ($fieldsDefinition as $name => $length) {
    $unpackFormats[] = 'A' . $length . $name;
}
$unpackString = implode('/', $unpackFormats);

// 6. 逐行解析数据
$parsedData = [];
foreach ($rawLines as $lineNumber => $line) {
    // 确保行长度足够,避免unpack警告
    // 实际应用中,如果行长不符合预期,可能需要更复杂的错误处理
    if (strlen($line) < array_sum($fieldsDefinition)) {
        echo "警告:第 " . ($lineNumber + 1) . " 行长度不符合预期,可能被截断或解析错误。\n";
        // 可以选择跳过此行或填充空白
        // $line = str_pad($line, array_sum($fieldsDefinition), ' ');
    }

    $parsedLine = unpack($unpackString, $line);

    // unpack 返回的数组键可能包含额外的数字索引,这里只保留命名的键
    $cleanParsedLine = [];
    foreach ($fieldsDefinition as $name => $length) {
        $cleanParsedLine[$name] = trim($parsedLine[$name]); // 移除字段前后的空白,根据需求决定是否保留
    }
    $parsedData[] = $cleanParsedLine;
}

// 调试输出解析结果(可选)
// var_dump($parsedData);

// 7. 导出到CSV文件
$exportFile = fopen($outputCsvFile, "w");

if ($exportFile === false) {
    die("错误:无法创建输出文件 '{$outputCsvFile}'。\n");
}

// 写入CSV头部(字段名)
fputcsv($exportFile, array_keys($fieldsDefinition), "|");

// 写入数据行
foreach ($parsedData as $row) {
    fputcsv($exportFile, $row, "|"); // 使用管道符 "|" 作为分隔符
}

// 关闭文件句柄
fclose($exportFile);

echo "数据已成功从 '{$inputFile}' 导出到 '{$outputCsvFile}',使用 '|' 作为分隔符。\n";

?>

代码解释:

  1. 文件路径定义: $inputFile 和 $outputCsvFile 分别指定了输入和输出文件的路径。
  2. 文件读取: file($inputFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) 函数用于读取整个.out文件。FILE_IGNORE_NEW_LINES 避免在每行末尾包含换行符,FILE_SKIP_EMPTY_LINES 跳过空行。
  3. 字段定义 ($fieldsDefinition): 这是一个关联数组,其键是自定义的字段名,值是该字段在每条记录中的精确字符长度。这是整个解析过程中最关键且需要手动配置的部分。 任何长度的偏差都可能导致数据解析错误。
  4. 构建unpack格式字符串: 脚本遍历 $fieldsDefinition 数组,为每个字段生成 A{长度}{字段名} 格式,然后使用 / 将它们连接起来,形成 unpack 函数所需的完整格式字符串。
  5. 逐行解析: 脚本遍历从.out文件读取的每一行。对于每行,它调用 unpack($unpackString, $line) 来解析数据。unpack返回一个关联数组,其中包含以字段名作为键的解析值。
    • trim($parsedLine[$name]):在将数据添加到 $cleanParsedLine 之前,使用 trim() 函数移除了字段值前后的空白字符。这对于那些空白仅作为填充而非实际数据的情况很有用。如果空白代表NULL值或有其他语义,则应根据具体需求决定是否保留。
  6. 导出到CSV:
    • fopen($outputCsvFile, "w") 以写入模式打开一个CSV文件。
    • fputcsv($exportFile, array_keys($fieldsDefinition), "|") 首先写入CSV文件的头部,即所有字段的名称。
    • fputcsv($exportFile, $row, "|") 遍历解析后的数据 $parsedData,将每一行数据以管道符 | 作为分隔符写入CSV文件。
    • fclose($exportFile) 关闭文件句柄。

导出到SQL文件(扩展)

虽然上述代码直接导出了CSV,但将其扩展为导出SQL文件也是可行的。在解析数据之后,你可以遍历 $parsedData 数组,为每一行数据生成一条 INSERT 语句。

示例代码片段(在CSV导出之后添加):

注意事项:

  • SQL转义: 在生成SQL语句时,务必对数据进行适当的SQL转义(例如使用 mysqli_real_escape_string 或 PDO 的预处理语句),以防止SQL注入攻击。
  • 数据类型: unpack 默认将所有字段解析为字符串。在生成SQL时,如果目标数据库字段是数值、日期等类型,你需要根据实际需求进行PHP端的数据类型转换。
  • 数据库连接: 上述SQL导出示例中,mysqli_real_escape_string 需要一个数据库连接。在实际应用中,你可能需要在脚本顶部建立一个临时的数据库连接,或者使用其他不依赖连接的转义函数(如 addslashes,但安全性较低)。

注意事项与最佳实践

  1. 精确定义字段长度: 这是固定宽度数据解析的基石。任何一个字段的长度定义错误都可能导致后续所有字段的解析错位。务必仔细核对数据字典或样本数据,确保 $fieldsDefinition 数组的准确性。
  2. 处理空白字符: 明确空白字符在你的数据中是作为填充还是代表实际的NULL值。如果空白是填充,使用 trim() 是合适的。如果空白表示NULL,则不应 trim(),而应在后续处理中将其转换为数据库的NULL或其他特定值。
  3. 错误处理: 脚本中加入了文件是否存在、文件读取失败、行长度不匹配等基本的错误检查。对于生产环境,应考虑更健壮的错误日志记录和异常处理机制。
  4. 内存管理: 对于非常大的.out文件,file() 函数会将整个文件加载到内存中。如果文件大小达到GB级别,这可能导致内存耗尽。此时,可以考虑逐行读取文件(例如使用 fgets 配合 while (!feof($file)) 循环),而不是一次性加载所有行。
  5. 数据类型转换: unpack 函数将所有字段都作为字符串返回。如果你的数据包含数字、日期、布尔值等,你需要在解析后进行显式的数据类型转换,以便在导出到数据库或进行进一步分析时保持数据完整性。
  6. 代码可维护性: 将字段定义放在脚本顶部,使其易于查找和修改。为字段选择有意义的名称,提高代码可读性。

总结

通过PHP的unpack函数,我们可以有效地解析无分隔符的固定宽度数据文件。结合文件读取和CSV/SQL写入功能,可以构建一个强大的数据转换工具。关键在于准确地定义每个固定宽度字段的名称和长度,并根据具体需求处理空白字符和数据类型转换。掌握这一技术,将使你在处理传统数据格式时更加得心应手。

相关专题

更多
php文件怎么打开
php文件怎么打开

打开php文件步骤:1、选择文本编辑器;2、在选择的文本编辑器中,创建一个新的文件,并将其保存为.php文件;3、在创建的PHP文件中,编写PHP代码;4、要在本地计算机上运行PHP文件,需要设置一个服务器环境;5、安装服务器环境后,需要将PHP文件放入服务器目录中;6、一旦将PHP文件放入服务器目录中,就可以通过浏览器来运行它。

2483

2023.09.01

php怎么取出数组的前几个元素
php怎么取出数组的前几个元素

取出php数组的前几个元素的方法有使用array_slice()函数、使用array_splice()函数、使用循环遍历、使用array_slice()函数和array_values()函数等。本专题为大家提供php数组相关的文章、下载、课程内容,供大家免费下载体验。

1580

2023.10.11

php反序列化失败怎么办
php反序列化失败怎么办

php反序列化失败的解决办法检查序列化数据。检查类定义、检查错误日志、更新PHP版本和应用安全措施等。本专题为大家提供php反序列化相关的文章、下载、课程内容,供大家免费下载体验。

1478

2023.10.11

php怎么连接mssql数据库
php怎么连接mssql数据库

连接方法:1、通过mssql_系列函数;2、通过sqlsrv_系列函数;3、通过odbc方式连接;4、通过PDO方式;5、通过COM方式连接。想了解php怎么连接mssql数据库的详细内容,可以访问下面的文章。

952

2023.10.23

php连接mssql数据库的方法
php连接mssql数据库的方法

php连接mssql数据库的方法有使用PHP的MSSQL扩展、使用PDO等。想了解更多php连接mssql数据库相关内容,可以阅读本专题下面的文章。

1414

2023.10.23

html怎么上传
html怎么上传

html通过使用HTML表单、JavaScript和PHP上传。更多关于html的问题详细请看本专题下面的文章。php中文网欢迎大家前来学习。

1234

2023.11.03

PHP出现乱码怎么解决
PHP出现乱码怎么解决

PHP出现乱码可以通过修改PHP文件头部的字符编码设置、检查PHP文件的编码格式、检查数据库连接设置和检查HTML页面的字符编码设置来解决。更多关于php乱码的问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

1445

2023.11.09

php文件怎么在手机上打开
php文件怎么在手机上打开

php文件在手机上打开需要在手机上搭建一个能够运行php的服务器环境,并将php文件上传到服务器上。再在手机上的浏览器中输入服务器的IP地址或域名,加上php文件的路径,即可打开php文件并查看其内容。更多关于php相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

1305

2023.11.13

php与html混编教程大全
php与html混编教程大全

本专题整合了php和html混编相关教程,阅读专题下面的文章了解更多详细内容。

3

2026.01.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
MySQL 教程
MySQL 教程

共48课时 | 1.7万人学习

MySQL 初学入门(mosh老师)
MySQL 初学入门(mosh老师)

共3课时 | 0.3万人学习

简单聊聊mysql8与网络通信
简单聊聊mysql8与网络通信

共1课时 | 787人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号