Problemi lettura file csv

SolidSnake4

Utente Attivo
23 Ott 2007
505
0
0
Buongiorno a tutti. Sto avendo dei problemi con la lettura di dati da file csv. Vi spiego qual'è il problema. Quando vado a leggere il file con una classe in php, in alcuni casi i valori non corrispondono con quelli del file csv. Da cosa può dipendere ? Non faccio nessuna conversione ai dati.
 
Ciao,

al fine di offirti un avlido supporto quando postate la richieste che sono relative a codice postate i riferimenti o il codice stesso altrimenti è un pò arduo darvi un aiuto.

Ciao, Ciro

p.s. potrebbe essere un problema di codifica, posta il codice o la classe
 
questa è la classe:

questo problema non ce l'ho sututti i file csv solo su alcuni.

PHP:
<?
class CSV
{
	var $CSVFile;
	var $CSVData;
	var $CSVError;
	var $FieldNames;      //beinhaltet die Feldnamen der Felder. FieldNames[field_id] = Feldname
	var $Fields;         //beinhaltet ein array mit den ganzen zeilen und feldern Fields[line][field_id] = value
	var $FieldTypes;    //enthält die Typ-Definitionen für die Felder FieldTypes[field_id] = type
	var $fetchCursor;  //Interner Zähler der von den Fetch-Funktionen benutzt wird

	var $Filter;

	function CSV()
	{
		$this->CSVError = array();
		$this->CSVData = "";
		$this->Filter = array();
	}


	function setFile($file)
	{
		/*
			Bestimmt die CSV-Datei und setzt den Inhalt der Datei
			in die CSVData in einem String
		*/

		$this->CSVFile = $file;

		if(file_exists($this->CSVFile) && ($this->CSVFile != "none") && !empty($this->CSVFile))
		{
			$this->setData(join("",file($this->CSVFile)));
		}
		else
		{
			$this->CSVError[] = "Datei " . $file . " existiert nicht oder keine Lese-Rechte";
			return FALSE;
		}
	}


	function setData($string)
	{
		/*
			Sollte zum Import von CSV-Daten keine Datei benutzt werden, so
			kann hier der String übergeben werden.
		*/

		$this->CSVData = $string;


		//Löschung von gefüllten Arrays
		$this->Fields = array();
		$this->FieldTypes = array();
		$this->FieldNames = array();
	}

	function CSVFetchRow()
	{

		if($this->fetchCursor <= $this->CSVNumRows())
		{
			$r = $this->Fields[$this->fetchCursor];
			$this->fetchCursor++;
			return $r;
		}
		else
		{
			$this->CSVError[] = "Es existieren keine weiteren Datensätze";
			return FALSE;
		}
	}


	function CSVFetchArray($resultTyp = "BOTH")
	{

		if($this->fetchCursor <= $this->CSVNumRows())
		{

			if( ($resultTyp == "NUM") || ($resultTyp == "BOTH") )
			{
				$r = $this->CSVFetchRow();

				if($resultTyp == "NUM") return $r;

				$this->fetchCursor--; //Weil diese var von der Funktion CSVFetchRow inkrementiert und im nächsten Fall "ASSOC" dann scheisse liefert
			}

			if( ($resultTyp == "ASSOC") || ($resultTyp == "BOTH") )
			{
				if(is_array($this->Fields[$this->fetchCursor]))
				{
					reset($this->Fields[$this->fetchCursor]);
					while(list($field_id, $field) = each($this->Fields[$this->fetchCursor]))
					{
						$r[$this->FieldNames[$field_id]] = $field;
					}
				}
			}

			$this->fetchCursor++;
			return $r;
		}
		else
		{
			$this->CSVError[] = "Es existieren keine weiteren Datensätze";
			return FALSE;
		}
	}

	function CSVFetchFieldNames()
	{
		return $this->FieldNames;
	}


	function CSVFieldName($field_id)
	{
		return $this->FieldNames[$field_id];
	}


	function CSVNumRows()
	{
		return count($this->Fields);
	}


	function CSVNumFields()
	{
		return count($this->FieldNames);
	}


	function setCursor($pos)
	{
		$this->fetchCursor = $pos;
	}


	function getCursor()
	{

		return $this->fetchCursor;
	}


	function resetCursor()
	{
		$this->setCursor(0);
	}


	function getFieldID($search_field)
	{

		if(!is_array($this->FieldNames)) return FALSE;

		foreach($this->FieldNames AS $field_id => $field_name)
		{
			//echo $search_field . " " . $field_name . " hallo<br>";
			if(trim($search_field) == trim($field_name))
			{
				return $field_id;
			}
		}

		return FALSE;
	}

	function addFilter($field, $operator, $match_value)
	{

		if(!$fieldID = $this->getFieldID($field)) $fieldID = $field;
		$field = $fieldID . "||" . count($this->Filter);

		$this->Filter[$field]["operator"] = $operator;
		$this->Filter[$field]["match_value"] = $match_value;


	}


	function applyFilter()
	{

		if(!count($this->Filter)) return FALSE;

		$results = array();
		$cc = 0;

		foreach($this->Filter AS $match_field => $match_values)
		{
			$match_field = substr($match_field, 0, strpos($match_field, "||"));

			//Bei Trennzeichen-CSV-Dateien steht im key anstatt der id der name des Feldes. Hier wird die id des feldes ermittelt
			if(!is_numeric($match_field) && (($fieldID = $this->getFieldID($match_field)) !== FALSE) ) $match_field = $fieldID;


			$operator = $match_values["operator"];
			$match_value = $match_values["match_value"];

			$results[$cc] = $this->Fields;

			foreach($this->Fields AS $line => $fields)
			{
				$filterResult = FALSE;

				switch($operator)
				{
					case "==": case "=":
						if($fields[$match_field] == $match_value) $filterResult = TRUE;

						break;

					case "!=" : case "!":
						if($fields[$match_field] != $match_value) $filterResult = TRUE;

						break;

					case "<": case "lt":
						if($fields[$match_field] < $match_value) $filterResult = TRUE;

						break;

					case ">": case "gt":
						if($fields[$match_field] > $match_value) $filterResult = TRUE;

						break;
				}


				if(!$filterResult)
				{

					unset($results[$cc][$line]);
				}

			}

			$cc++;
		}


		//Die einzelnen Ergebnisse jedes Filters werden jetzt zusammengefasst
		$this->Fields = array();
		foreach($results AS $fields) $this->Fields = $this->array_merge_better($this->Fields, $fields);

		//Lückenlose (d.h. durchgehend nummeriert) Arrayzusammensetzung
		$r = "";
		foreach($this->Fields AS $fields) $r[] = $fields;
		$this->Fields = $r;

		return TRUE;

	}

	function setFieldType($field, $type="")
	{
		$this->FieldTypes[$field] = $type;
	}


	function _prepareFieldTypes()
	{
		foreach($this->FieldTypes AS $field => $value)
		{
			if(is_string($field))
			{
				unset($this->FieldTypes[$field]);
				if(($fieldID = $this->getFieldID($field)) !== FALSE) $this->FieldTypes[$fieldID] = $value;
			}
		}
	}



	function convertFieldType()
	{
		if(!count($this->FieldTypes)) return FALSE;
		$this->_prepareFieldTypes();

		$valid_holder = array("m", "h", "D", "M", "Y"); //erlaubte Platzhalter in der Datum-Definition

		foreach($this->Fields AS $line_id => $line)
		{
			foreach($line AS $field_id => $value)
			{
				if(!isset($this->FieldTypes[$field_id]) || empty($this->FieldTypes[$field_id]) || empty($value)) continue;



				$convert_type = $this->FieldTypes[$field_id];
				$convert_arg  = substr($convert_type, strpos($convert_type, "(")+1, strlen($convert_type) - (strpos($convert_type, "(") + 2));

				if(strpos($convert_arg, ",")) //mehrere Argumente
				{
					$convert_arg = explode(",", $convert_arg);

					reset($convert_arg);

					while(list($key2, $value2) = each($convert_arg))
					{
						$value2 = trim($value2);
						if(substr($value2, 0, 1) == "'") $value2 = str_replace("'", "", $value2);

						$convert_arg[$key2] = $value2;
					}
				}

				$convert_value = "";

				switch(trim(strtolower(substr($convert_type, 0, strpos($convert_type, "(")))))
				{
					case "decimal": case "double":
						$convert_value = substr($value, 0, strlen($value) - $convert_arg) . "." . substr($value, $convert_arg * -1) ;
						$convert_value = doubleval($convert_value);
						break;

					case "number": case "int": case "integer":
						$convert_value = str_replace(",", ".", $value);
						$convert_value = doubleval($convert_value);
						break;

					case "date":
						$holder_define = $convert_arg[0]; //hier wurden die Platzhalter definiert
						if(isset($holder_values)) unset($holder_values);


						for($cc = 0; $cc < strlen($value); $cc++)
						{
							$sub_value = substr($value, $cc, 1);
							$holder = substr($holder_define, $cc, 1);

							if(in_array($holder, $valid_holder))
							{
								$holder_values[$holder] .= $sub_value;
							}
						}

						$holder_define = $convert_arg[1];

						for($cc = 0; $cc < strlen($holder_define); $cc++)
						{
							$holder = substr($holder_define, $cc, 1);

							if(in_array($holder, $valid_holder))
							{
								$convert_value .= substr($holder_values[$holder], 0, 1);
								$holder_values[$holder] = substr($holder_values[$holder], 1);
							}
							else
							{
								$convert_value .= $holder;
							}
						}

						break;
				}

				if($convert_value !== $value)  $this->Fields[$line_id][$field_id] = $convert_value;
			}
		}
	}

	function echoCSVError()
	{
		/*
			gibt alle Fehler aus
		*/

		foreach($this->CSVError AS $pos => $error_str)
		{
			echo "- " . ($pos+1) . ". " . $error_str . "<br>";
		}
	}

	function isOK($error_output = TRUE)
	{
		//Liefert TRUE or FALSE, ob alles ok ist. Der optionale Parameter gibt die fehler aus.

		if($error_output) $this->echoCSVError();
		return ((count($this->CSVError) > 0) ? FALSE : TRUE);
	}

	function array_merge_better($a1,$a2)
	{
		if(!is_array($a1)) $a1 = array();
		if(!is_array($a2)) $a2 = array();

		// if(!is_array($a1) || !is_array($a2)) return false;
		$newarray = $a1;

		while (list($key, $val) = each($a2))
		{
			if (is_array($val) && is_array($newarray[$key]))
			{
				$newarray[$key] = $this->array_merge_better($newarray[$key], $val);
			}
			else
			{
				$newarray[$key] = $val;
			}
		}

		return $newarray;
	}


	function dumpResult()
	{

		$prevFetchCursor = $this->getCursor();
		$this->resetCursor();

		$fields = $this->CSVFetchFieldNames();
		echo "<table border='1'><tr>";

		foreach($fields AS $feld)
		{
			echo "<td><b>" . $feld . "</b></td>";
		}

		echo "</tr>";

		while($row = $this->CSVFetchArray("ASSOC"))
		{
			echo "<tr>";

			foreach($row AS $k => $feld)
			{
				echo "<td>&nbsp;" . $feld . "</td>";
			}

			echo "</tr>";
		}

		echo "</table>";

		$this->setCursor($prevFetchCursor);
	}
}

class CSVImport extends CSV
{
	var $FieldDelim;


	function CSVImport()
	{
		parent::CSV();
		$this->FieldDelim = ";";

	}


	function setDelim($delimiter)
	{
		$this->FieldDelim = $delimiter;
	}



	function parseCSV()
	{

		if($this->CSVData)
		{
			$akt_line  = 0;
			$akt_field = 0;
			$akt_field_value = "";
			$last_char = "";
			$quote = 0;
			$field_input = 0;
			$head_complete = 0;

			$end_cc = strlen($this->CSVData);

			for($cc = 0; $cc < $end_cc; $cc++)
			{
				$akt_char = substr($this->CSVData,$cc,1);

				if(($akt_char == "\"") && ($last_char != "\\")) //Abschliessung des eingeschlossenen Feldes. beschreibung siehe unten
				{
					$quote = !$quote;
					$akt_char = "";
				}

				if(!$quote)
				{
					if($akt_char == $this->FieldDelim) //Trennzeichen
					{
						$field_input = !$field_input;
						$akt_char = "";
						$akt_field++;
						$akt_field_value = "";
					}
					elseif(($akt_char == "\\") && $field_input) //Escape-Zeichen
					{
						$field_input++;
						$quote++;
					}
					elseif($akt_char == "\"") //Anführungszeichen kennzeichenen ein eingeschlossenes Feld, d.h. dieses Feld kann das Trennzeichen als Text enthalten und mehrzeilig sein.
					{
						$quote--;

						if($field_input)
							$field_input--;
						else
							$field_input++;
					}
					elseif($akt_char == "\n") //Neuer Datensatz
					{

						if($head_complete && (($akt_field+1) > $this->CSVNumFields()))
						{
							$this->CSVError[] = "Fehler in <b>Zeile " . ($akt_line + 2) . "</b>";
						}

						$akt_line++;
						$akt_field = 0;
						if(!$head_complete) $akt_line = 0;
						$head_complete = 1;
						$akt_char = "";
						$akt_field_value = "";
					}
				}


				$last_char = $akt_char;
				if($akt_char == "\\") $akt_char = "";
				$akt_field_value .= $akt_char;

				if($head_complete)
				{
					$this->Fields[$akt_line][$akt_field] = trim($akt_field_value); //Felder befüllung
				}
				else
				{
					$this->FieldNames[$akt_field] = trim($akt_field_value); //Feldernamen befüllung
				}

			}


			if(!$akt_field) //Leeren Abschluss-Datensatz entfernen
			{
				unset($this->Fields[$akt_line]);
			}

			parent::convertFieldType();
			parent::applyFilter();
			$this->fetchCursor = 0;
		}
		else
		{
			$this->CSVError[] = "Das CSV-Data ist nicht gefüllt";
			return FALSE;
		}
	}

}



class CSVFixImport extends CSV
{
	var $FieldLengths; //Array mit den Längen der Felder

	function CSVFixImport()
	{
		parent::CSV();  //Konstruktor der Eltern-Klasse aufrufen
		$this->FieldLengths = array();
	}


	function addCSVField($name, $length, $type = "")
	{

		$cursor = count($this->FieldNames);

		if(!$name) $name = "Feld " . ($cursor + 1);

		$this->FieldNames[$cursor] = $name;
		$this->FieldLengths[$cursor] = $length;
		$this->setFieldType($cursor, $type);
	}


	function setFile($file)
	{
		parent::setFile($file);
		$this->CSVData = explode("\n", trim($this->CSVData));
	}


	function parseCSV()
	{
		if($this->CSVData)
		{
			if(!count($this->FieldLengths))
			{
				$this->CSVError[] = "Die Felder wurden nicht definiert";
				return FALSE;
			}


			$currentLine = 0;

			foreach($this->CSVData AS $line)
			{
				$currentField = 0;
				$currentStringPos = 0;

				foreach($this->FieldLengths AS $FieldLength)
				{
					$value = trim(substr($line, $currentStringPos, $FieldLength));

					$this->Fields[$currentLine][$currentField] = $value;
					$currentStringPos += $FieldLength;
					$currentField++;
				}

				$currentLine++;
			}


			parent::convertFieldType();
			parent::applyFilter();
			$this->fetchCursor = 0;
		}
		else
		{
			$this->CSVError[] = "Keine zu importierende Daten gesetzt";
			return FALSE;
		}
	}
}

?>
 
Posta un esempio di come dovrebbero essere stampati i dati e di come invece vengono restituiti dalla classe.
 
Codice:
01.19.00	07.21.00	163.59.00	06.34.00
questi sono i dati presi dal file csv

questi invece sono come li restituisce la classe
Codice:
9.7500, 9.7850, 9.6550, 9.7500
 

Discussioni simili