据我所知/可以找到,有两种方法可以做到这一点。
explode("\n", $data)
鉴于您有基于记录(每个记录一行)的文本文件,其中包含特定规则。字符1到2为您提供yy格式的年份,字符3到4为您提供mm格式的月份。字符70到72为您提供一些x参数。
对于CSV,我们有str_getcsv()
,但我认为没有任何文本文件可用。
我个人的偏好是简单的换行选项。想法?
文本文件如下所示:
14 5 12466 3202313 710101010 31 7 9 5 3 4 4 4 4 50.21
14 5 22466 41317 7 7 7 3 3 7 19 5 6 3 3 3 2 2 3 30.10
14 5 32466 5 7 7 3 7 3172727 29 3 3 2 3 2 6 12 12 50.21
14 5 42466 62337332330231713 60 9 22 18 9 15 9 6 5 120.73
14 5 52466 71327202020202320 49 5 12 7 7 7 7 9 7 80.42
14 5 62466 8 3 7 7 7 3 3 3 3 11 2 3 3 3 2 2 2 2 20.00
14 5 72466 9 0 0 0 310 3 720 13 0 0 0 2 4 2 3 7 20.00
14 5 82466102333334320333037 76 9 18 18 32 7 18 15 22 170.94
14 5 924661130172017 7 3 010 31 15 6 7 6 3 2 0 4 50.21
14 51024661220301310 7 32327 40 7 15 5 4 3 2 9 12 70.42
14 5112466134330172713172027 58 32 15 6 12 5 6 7 12 120.73
14 5122466142320202320101717 45 9 7 7 9 7 4 6 6 70.31
14 51324661510131310 7 7 720 26 4 5 5 4 3 3 3 7 40.10
14 5142466161710 3 72317 717 30 6 4 2 3 9 6 3 6 50.21
14 51524661710101313 7101313 27 4 4 5 5 3 4 5 5 40.21
14 5162466181713101020201710 35 6 5 4 4 7 7 6 4 50.21
14 51724661913 7 3 7 3 3 3 3 13 5 3 2 3 2 2 2 2 30.00
14 518246620171310 717201013 32 6 5 4 3 6 7 4 5 50.21
14 5192466211013101013131020 30 4 5 4 4 5 5 4 7 50.21
14 520246622 7 7101010 7 3 3 17 3 3 4 4 4 3 2 2 30.10
14 521246623 7 3 3 3 0 3 3 7 9 3 2 2 2 0 2 2 3 20.00
14 5222466241010109999999999 4 4 4
每条记录/行的一些规则:
1- 2 i2 yy, last two digits of year
3- 4 i2 mm, month (1-12)
5- 6 i2 dd, day of month (1-31)
7-10 i4 Bartels solar rotation number - a sequence of 27-day
intervals counted continuously from February 8, 1832
11-12 i2 Number of day within the Bartels 27-day cycle
13-28 8i2 3-hourly Kp indices (0-3, 3-6, 6-9, 9-12, 12-15,
15-18, 18-21, 21-24 UT)
29-31 i3 Daily Kp sum, expressed to the nearest third of a unit
(supplied only for tradition, use Ap scientific
purposes!)
32-55 8i3 3-hourly ap indices (0-3, 3-6, 6-9, 9-12, 12-15,
15-18, 18-21, 21-24 UT)
56-58 i3 Ap equivalent daily amplitude -
答案 0 :(得分:0)
由于这种文本格式似乎没有任何分隔符,除了换行符之外,我会逐行读取它并使用substr
从中获取字段。正则表达式或CSV读取器不会起作用,因为没有分隔符。好吧,正则表达式在技术上是可行的,因为您还可以指定通配符和特定数量的重复,但最终它不会增加太多值。
所以只需在$line
中读一行,然后通过获取一些字符来解析它:
$year = trim(substr($line, 0, 2));
$month = trim(substr($line, 2, 2));
// etc.
这可能看起来很麻烦,但你可以把它包装成一个整洁的功能,如:
function getIntField($line, $start, $length);
{
return (int)trim(substr($line, $start, $length));
}
如果更进一步,可以在数组中进行字段定义以帮助您阅读文件:
$fields = array(
'year' => array(0, 2, 'int'),
'month' => array(2, 2, 'int'),
'day' => array(4, 2, 'int'),
'hour' => array(6, 2, 'int'),
'amount' => array(8, 5, 'float')
);
然后,您可以阅读如下字段:
function getField($line, $field)
{
$fields = .... field def goes here (or use global or class variable).
// Get the proper field definition for the field. (You can add some
// checking to see whether it exists.
$def = fields[$field];
// Read the specified part (start, length are in the field definition).
$value = trim(substr($line, $def[0], $def[1]));
// In my example, the third parameter of the definition is the type.
switch ($def[2])
{
case 'int': return (int)$value;
case 'float': return (float)$value;
}
// Not returned as a specific type? Then, just return the string.
return $value;
}
如果在类中包含这样的函数,那么应该很容易拥有一个处理文件访问的类,并在内部跟踪当前行。然后你可以写一段这样的代码:
$amount = 0;
$file = new FixedLengthRecordFile($filePath);
while ($file->readLine())
{
$amount += $file->getField('amount');
}
echo 'Total amount in file: ' . $amount;
如果您愿意,您甚至可以使用魔术__get
方法来包装吸气剂。这样,你可以写:
$amount += $file->amount;
而不是
$amount += $file->getField('amount');
无论如何,如果我找不到已经为我做的开箱即用的课程,我可能会这样做。但我认为没有。