在csv文件中,我有这种结构的行:
Name;timestamp;floatValue
Name;timestamp;floatValue
Name;timestamp;floatValue
...
在我的代码中,我检查行中的每个值,我过滤它们,然后我想通过调用函数floatval
来更正浮点值,因为我有错误的值有时像:.904或2,454和使用此函数返回正确格式化的函数。
<?php
if (($handle = fopen('file.csv', "r+")) !== false) {
while (($line = fgetcsv($handle, 1024, ";")) !== false) {
$headers = [
'name',
'timestamp',
'floatValue',
];
$line = array_combine($headers, $line);
$args = array('name' => array('filter' => FILTER_VALIDATE_REGEXP,
'options' => array('regexp' => '/^[a-zA-Z0-9_:.()\/]*$/'), ),
'timestamp' => array('filter' => FILTER_CALLBACK,
'options' => 'validateDate', ),
'floatValue' => array('filter' => FILTER_VALIDATE_FLOAT),);
$result = filter_var_array($line, $args);
$line = correctFloat($line);
print_r($line);
}
}
fclose($handle);
function validateDate($date)
{
if (!preg_match("/^\d{8}$/", substr($date, 0, 8))) {
return false;
}
if (!checkdate(substr($date, 4, 2), substr($date, 6, 2), substr($date, 0, 4))) {
return false;
}
if (substr($date, 8, 2) > 23 || substr($date, 10, 2) > 59 || substr($date, 12, 2) > 59) {
return false;
}
return true;
}
function correctFloat($line){
$float = $line['floatValue'];
$value = str_replace(",",".",$float);
return str_replace($float,floatval($value),$line);
}
?>
现在我被困在如何在正确的行中写入文件中的正确值?
我试过了:
fwrite($handle,implode(";",correctFloat($line)));
但它没有用。 如何使用正确的浮点将每一行重写到正确位置的文件中而不会丢失数据? 有什么想法吗?
::: EDIT :::
我还尝试使用临时文件:
$temp = tmpfile();
fputcsv($temp,correctFloat($line),';');
fwrite($handle,fread($temp, 1024));
但我没有得到好结果。文件里面什么也没发生。
示例
输入:
Name;timestamp;.23
Name;timestamp;2,4578
Name;timestamp;1.23
预期输出:
Name;timestamp;0.23
Name;timestamp;2.4578
Name;timestamp;1.23
在此示例中:2,4578应位于输出中:2.4578(我使用上面的function correctFloat($line)
将逗号替换为'。'
新尝试:
$newline = correctFloat(array_combine($headers, $line));
array_push($newline,chr(10));
$l = implode(";",$newline);
fwrite($handle,$l);
rewind($handle);
只有第一个值发生变化,然后文件才会刷新而不会退出循环。
答案 0 :(得分:2)
要求:给定CSV输入文件,然后创建一个输出文件,其中浮动字段格式正确。
如何:
fields
correctFloat
)注意:我使用过测试数据,因此未检查验证。此代码只是格式化输入的输出。
输入/输出文件名:
define('DATA_FILE', 'Q42208643.dat');
define('DATA_FILE_OUT', 'Q42208643.out.dat');
标题和验证:
// setup field names and validiation rules
$headers = ['name', 'timestamp', 'floatValue',];
$args = array(
'sensor_internal_id' => array('filter' => FILTER_VALIDATE_REGEXP,
'options' => array('regexp' => '/^[a-zA-Z0-9_:.()\/]*$/'), ),
'timestamp' => array('filter' => FILTER_CALLBACK,
'options' => 'validateDate', ),
'value' => array('filter' => FILTER_VALIDATE_FLOAT),
);
处理输入和输出文件:
if (($handle = fopen(DATA_FILE, "r+")) !== false) {
$fOut = fopen(DATA_FILE_OUT, "wb");
while (($fields = fgetcsv($handle, 1024, ";")) !== false) {
$fields[2] = str_replace(",", ".", $fields[2]); // ensure float sting is valid
$namedFields = array_combine($headers, $fields);
$result = filter_var_array($namedFields, $args);
$outLine = correctFloat($fields);
fwrite($fOut, $outLine . PHP_EOL);
}
fclose($handle);
fclose($fOut);
}
功能:
function validateDate($date)
{
if (!preg_match("/^\d{8}$/", substr($date, 0, 8))) {
return false;
}
if (!checkdate(substr($date, 4, 2), substr($date, 6, 2), substr($date, 0, 4))) {
return false;
}
if (substr($date, 8, 2) > 23 || substr($date, 10, 2) > 59 || substr($date, 12, 2) > 59) {
return false;
}
return true;
}
function correctFloat($fields) {
$fields[2] = floatval($fields[2]);
return implode(';', $fields);
}
示例输入:
122222;1487075470;.123
233333;1487075470;2,345
344444;1487075470;3.678
示例输出:
122222;1487075470;0.123
233333;1487075470;2.345
344444;1487075470;3.678
答案 1 :(得分:0)
试试这个rewind() 示例代码:
$handle = fopen('output.txt', 'r+');
fwrite($handle, 'Really long sentence.');
rewind($handle);
fwrite($handle, 'Foo');
rewind($handle);
echo fread($handle, filesize('output.txt'));
fclose($handle);
// 输出: 愚蠢的长句。
此处的回放功能会将您带到当前行的开头,然后您只需要替换该行中的所有字符 [注意:如果您当前的数据少于旧数据,那么您将在末尾看到附加的旧值,因此只需将所有剩余字符替换为''(空白)
如果有帮助,请告诉我,否则我会提供在您的代码中使用它的方法