Utilizando PHP para tomar a primeira linha de um arquivo CSV e criar uma tabela MySQL com os dados
Pergunta
Eu estou tentando ter um pouco grande arquivo CSV e inseri-lo em um banco de dados MySQL para referência em um projeto. Gostaria de usar a primeira linha do arquivo para criar a tabela usando tipos de dados adequados e não varchar para cada coluna. O objetivo final é para automatizar esse processo como eu tenho vários arquivos semelhantes, mas a cada um tem diferentes dados e uma quantidade diferente de "colunas" em arquivos CSV. O problema que estou tendo é gettype () está retornando 'string' para cada coluna em vez de int, float e string como eu gostaria que fosse.
Platform é PHP 5, OS é o Ubuntu 8.04
aqui é o meu código até agora:
<?php
// GENERATE TABLE FROM FIRST LINE OF CSV FILE
$inputFile = 'file.csv';
$tableName = 'file_csv';
$fh = fopen($inputFile, 'r');
$contents = fread($fh, 5120); // 5KB
fclose($fh);
$fileLines = explode("\n", $contents); // explode to make sure we are only using the first line.
$fieldList = explode(',', $fileLines[0]); // separate columns, put into array
echo 'CREATE TABLE IF NOT EXISTS `'.$tableName.'` ('."<br/>\n";
for($i = 0; $i <= count($fieldList); $i++)
{
switch(gettype($fieldList[$i])) {
case 'integer':
$typeInfo = 'int(11)';
break;
case 'float':
$typeInfo = 'float';
break;
case 'string':
$typeInfo = 'varchar(80)';
break;
default:
$typeInfo = 'varchar(80)';
break;
}
if(gettype($fieldList[$i]) != NULL) echo "\t".'`'.$i.'` '.$typeInfo.' NOT NULL, --'.gettype($fieldList[$i]).' '.$fieldList[$i]."<br/>\n";
}
echo ' PRIMARY KEY (`0`)'."<br/>\n";
echo ') ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;';
Exemplo Primeira linha: 1,0,0,0,0,0,0,0,0,0,0,0,0.000000,0.000000,0,0,0, 0,0,1,0,50, 'palavra de recordação ( OLD)',
Solução
Com base no Nouveau de código que você poderia fazer isso
for($i = 0; $i <= count($fieldList); $i++)
{
if (is_numeric($fieldList[$i]))
{
if (strpos($fieldList[$i],'.') !== false){
$fieldList[$i] = (int)$fieldList[$i];
}else{
$fieldList[$i] = (float)$fieldList[$i];
}
}
switch(gettype($fieldList[$i])) {
case 'integer':
$typeInfo = 'int(11)';
break;
case 'float':
case 'double':
$typeInfo = 'float';
break;
case 'string':
$typeInfo = 'varchar(80)';
break;
default:
$typeInfo = 'varchar(80)';
break;
}
if(gettype($fieldList[$i]) != NULL) echo "\t".'`'.$i.'` '.$typeInfo.' NOT NULL, --'.gettype($fieldList[$i]).' '.$fieldList[$i]."<br/>\n";
}
que funciona, observe a adição de "caso 'duplo':". Na chave, mas pode haver uma maneira melhor de fazer o check int / float como eles só iria trabalhar com uk padrão / Números
Outras dicas
Tente converter o valor e compará-lo com o original:
define('DECIMAL_SEPARATOR', '.');
switch ($fieldList[$i])
{
case (string)(int)$fieldList[$i]:
$typeInfo = (strpos($fieldList[$i], DECIMAL_SEPARATOR) === false) ? 'int(11)' : 'float';
break;
case (string)(float)$fieldList[$i]:
$typeInfo = 'float';
break;
default:
$typeInfo = 'varchar(80)';
break;
}
Adicionalmente, verificação da presença de separador decimal no primeiro caso para os números que estão ao redor, mas eles têm a parte de fração decimal.
<?php
// GENERATE TABLE FROM FIRST LINE OF CSV FILE
$inputFile = 'file.csv';
$tableName = 'file_csv';
$fh = fopen($inputFile, 'r');
$contents = fread($fh, 5120); // 5KB
fclose($fh);
$fileLines = explode("\n", $contents);
$fieldList = explode(',', $fileLines[0]);
echo 'CREATE TABLE IF NOT EXISTS `'.$tableName.'` ('."<br/>\n";
for($i = 0; $i <= count($fieldList); $i++)
{
if(strlen($fieldList[$i]) == 0) $typeInfo = 'varchar(80)';
if(preg_match('/[0-9]/', $fieldList[$i])) $typeInfo = 'int(11)';
if(preg_match('/[\.]/', $fieldList[$i])) $typeInfo = 'float';
if(preg_match('/[a-z\\\']/i', $fieldList[$i])) $typeInfo = 'varchar(80)';
echo "\t".'`'.$i.'` '.$typeInfo.' NOT NULL, -- '.gettype($fieldList[$i]).' '.$fieldList[$i]."<br/>\n";
}
echo ' PRIMARY KEY (`0`)'."<br/>\n";
echo ') ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;';
Usando expressões regulares vai lhe dar uma solução flexível. Se você precisa para detectar campos de data, então este é o caminho a percorrer.