在PHP中解析文件没有分隔符

时间:2016-09-12 01:35:28

标签: php parsing

我正在开发一个项目,该项目要求将一些财务文件解析为数据库。这些文件没有分隔符,每条记录本质上都是一个巨大的字符串,它们为我提供了什么位置是什么字段的地图。

这是一条记录:

GCA0000000188T0544291021BW1079    021BW1079    JOE88TSUSD2015041420150414000000001053060070+000000001053060070+000000001053060070+000000000000000000+000000000000000000+000000000000000000+000000000000000000+000000000000000000+000000000000000000+000000000000000000+000000000000000000+000000000000000000+000000000000000000+000000000000000000+000000000000000000+000000000001053060+000000000001053060+000000000000263265+000000000000000000+021BW107904 042 000000000000000000+00000000000000000000000000000000000000000000PEPPERS AN034   04100003ALTERNATIVE FOCUS   BLUETREND L.P.      HOLDBACK                                                                           NUSD000000000010530600+0000000000+000000010000000000+000000000010530600+USD 

映射是这样的:

position 000-002 -> Field X

position 003-012 -> Field Y

position 013-023 -> Field Z

等等。

问题:最好的方法是什么?我在PHP堆栈上。我正在考虑为每个字段创建方法,传入整个字符串,并返回值。有没有可用于帮助的包裹?

2 个答案:

答案 0 :(得分:2)

sscanf的

内置函数sscanf()适用于这样的固定宽度字段 - 如果格式正确,它会将其解析为数组。该格式在sprintf()(与其对应)的文档中描述,只有few differences

这很简单:

  • %3s - 3字节长字符串
  • %10s - 10字节长的字符串
  • %11s - 11字节长字符串

示例1:

$fields = sscanf($record, '%3s%10s%11s');
var_dump($fields);

结果:

array(3) {
  [0]=>
  string(3) "GCA"
  [1]=>
  string(10) "0000000188"
  [2]=>
  string(11) "T0544291021"
}

如果您更喜欢举例:

  • 将第二个字段视为带符号的小数,并将其作为整数返回
  • 跳过以下T
  • 也将第三个字段视为带符号的十进制数,并将其作为整数返回

您可以使用:

  • %3s - 3字节长字符串
  • %10d - 10个字符宽的带符号十进制
  • T - 字面意思" T" (未退回)
  • %10d - 10个字符宽的带符号十进制

示例2:

$fields = sscanf($record, '%3s%10dT%10d');
var_dump($fields);

结果:

array(3) {
  [0]=>
  string(3) "GCA"
  [1]=>
  int(188)
  [2]=>
  int(544291021)
}

解包

另一种方法是使用unpack(),您可以在其对应文档的文档中找到其格式信息pack()

  • A3Field X - 将3个字节作为字符串解压缩到"字段X"
  • A10Field Y - 将10个字节作为字符串解压缩到"字段Y"
  • A11Field Z - 将11个字节作为字符串解压缩到"字段Z"

示例3:

$fields = unpack('A3Field X/A10Field Y/A11Field Z', $record);
var_dump($fields);

结果:

array(3) {
  ["Field X"]=>
  string(3) "GCA"
  ["Field Y"]=>
  string(10) "0000000188"
  ["Field Z"]=>
  string(11) "T0544291021"
}

是否使用sscanfunpack取决于您的数据的性质以及您需要如何处理它:sscanf可以很好地解释字符串中的字符{{1}很好地解释构成它的字节(它对二进制数据更有用。)

例如,给定带有解包的字符串unpack,您可以获得它所包含的字节的值(即其ASCII value):

"1"

$fields = unpack('c', "1"); var_dump($fields[1]); //int(49) 功能强大但很复杂,您可以在http://perldoc.perl.org/perlpacktut.html找到更多相关信息

答案 1 :(得分:0)

如果您要使用哪些列,最简单的解决方案可能就是使用substr

<script src="https://cdnjs.cloudflare.com/ajax/libs/modernizr/2.8.3/modernizr.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="what">Well... I'm not sure.</div>