如何確定csv文件字段是製表符分隔還是用逗號分隔。我需要PHP驗證。任何人都可以幫助。提前致謝。如何查找csv文件字段是製表符分隔還是逗號分隔
回答
有沒有100%可靠的方法來確定這一點。你可以做的是
- 如果你有一個方法來驗證你讀的字段,嘗試閱讀幾個字段使用任何分隔符和驗證您的方法。如果中斷,請使用另一個。
- 計算文件中製表符或逗號的出現次數。通常,其中一個明顯高於另一個
- 最後但並非最不重要的是:詢問用戶,並允許他覆蓋您的猜測。
除了從小事回答Ç SV文件始終用逗號分隔的 - 它在這個名字,我不認爲你可以拿出任何硬性規則。 TSV和CSV文件都有足夠寬鬆的規定,您可以創建可接受的文件。
A\tB,C
1,2\t3
(假設\ t == TAB)
你如何將決定這是否是TSV或CSV?
c可以代表'字符',這使得,;或\ t所有有效的選項。 – julesj 2012-07-02 15:52:53
@julesj快速搜索建議很少使用c來表示字符,最具意義的逗號。雖然即使這樣,分隔符並不總是一個逗號,只是爲了使事情複雜化。 – 2012-07-02 19:41:17
當我輸出一個TSV文件I使用\ t時的方法相同的方法人會創作像\ n中的換行符創作選項卡,使得被所述我想的方法可以如下:
<?php
$mysource = YOUR SOURCE HERE, file_get_contents() OR HOWEVER YOU WISH TO GET THE SOURCE;
if(strpos($mysource, "\t") > 0){
//We have a tab separator
}else{
// it might be CSV
}
?>
我猜猜這可能不是正確的方式,因爲在實際內容中也可以有製表符和逗號。這只是一個想法。使用正則表達式可能會更好,儘管我對此不太瞭解。
在我的情況下,用戶提供的csv文件被輸入到SQL數據庫中。他們可以將Excel電子表格保存爲逗號或製表符分隔的文件。將電子表格轉換爲SQL的程序需要自動識別字段是製表符分隔還是逗號
許多Excel csv導出都將字段標題作爲第一行。標題測試不可能包含逗號,除非作爲分隔符。對於我的情況,我計算了第一行的逗號和製表符,並用較大的數字來確定它是csv還是製表符
這就是我所做的。
- 解析所述第一5線CSV文件
- 計數中的每一行
- 比較每行分隔符的數量的分隔符[逗號,製表符,分號和冒號]的數量。如果你有一個格式正確的CSV,那麼每一行的分隔符數量都會匹配。
這不會100%的時間,但它是一個體面的起點。至少它會減少可能的分隔符的數量(使用戶更容易選擇正確的分隔符)。
/* Rearrange this array to change the search priority of delimiters */
$delimiters = array('tab' => "\t",
'comma' => ",",
'semicolon' => ";"
);
$handle = file($file); # Grabs the CSV file, loads into array
$line = array(); # Stores the count of delimiters in each row
$valid_delimiter = array(); # Stores Valid Delimiters
# Count the number of Delimiters in Each Row
for ($i = 1; $i < 6; $i++){
foreach ($delimiters as $key => $value){
$line[$key][$i] = count(explode($value, $handle[$i])) - 1;
}
}
# Compare the Count of Delimiters in Each line
foreach ($line as $delimiter => $count){
# Check that the first two values are not 0
if ($count[1] > 0 and $count[2] > 0){
$match = true;
$prev_value = '';
foreach ($count as $value){
if ($prev_value != '')
$match = ($prev_value == $value and $match == true) ? true : false;
$prev_value = $value;
}
} else {
$match = false;
}
if ($match == true) $valid_delimiter[] = $delimiter;
}//foreach
# Set Default delimiter to comma
$delimiter = ($valid_delimiter[0] != '') ? $valid_delimiter[0] : "comma";
/* !!!! This is good enough for my needs since I have the priority set to "tab"
!!!! but you will want to have to user select from the delimiters in $valid_delimiter
!!!! if multiple dilimiter counts match
*/
# The Delimiter for the CSV
echo $delimiters[$delimiter];
很好地工作。在解析我的文件之前,我將它用作函數。它的返回值,** $ delimiters [$ delimiter] **我在** str_getcsv($ value,$ delimeter)中使用它; ** – MJoraid 2015-01-05 06:58:41
您還可以使用fgetcsv(http://php.net/manual/en/function.fgetcsv.php)傳遞一個分隔符參數。如果該函數返回false,則意味着$ delimiter參數不是正確的一個樣本,用於檢查分隔符是否爲';',而不是正確的
樣本。
if (($data = fgetcsv($your_csv_handler, 1000, ';')) !== false) { $csv_delimiter = ';'; }
$ csv_delimiter =';';而不是$ csv_delimiter =';' – 2014-03-28 17:40:08
我的不好!只是編輯它 – Rommy 2014-04-03 07:37:42
不幸的是,這並沒有爲我工作 – antongorodezkiy 2015-08-03 23:57:28
我只是計數的CSV文件中的不同分隔符的情況出現時,一個最可能應該是正確的分隔符:
//The delimiters array to look through
$delimiters = array(
'semicolon' => ";",
'tab' => "\t",
'comma' => ",",
);
//Load the csv file into a string
$csv = file_get_contents($file);
foreach ($delimiters as $key => $delim) {
$res[$key] = substr_count($csv, $delim);
}
//reverse sort the values, so the [0] element has the most occured delimiter
arsort($res);
reset($res);
$first_key = key($res);
return $delimiters[$first_key];
太晚來回答這個問題,但希望它能幫助別人。
這是一個簡單的函數,它將返回文件的分隔符。
function getFileDelimiter($file, $checkLines = 2){
$file = new SplFileObject($file);
$delimiters = array(
',',
'\t',
';',
'|',
':'
);
$results = array();
$i = 0;
while($file->valid() && $i <= $checkLines){
$line = $file->fgets();
foreach ($delimiters as $delimiter){
$regExp = '/['.$delimiter.']/';
$fields = preg_split($regExp, $line);
if(count($fields) > 1){
if(!empty($results[$delimiter])){
$results[$delimiter]++;
} else {
$results[$delimiter] = 1;
}
}
}
$i++;
}
$results = array_keys($results, max($results));
return $results[0];
}
使用如下這樣的功能:
$delimiter = getFileDelimiter('abc.csv'); //Check 2 lines to determine the delimiter
$delimiter = getFileDelimiter('abc.csv', 5); //Check 5 lines to determine the delimiter
PS我已經使用使preg_split()而不是爆炸(),因爲爆炸( '\ t',$值)將不給予適當的結果。
更新:感謝@RichardEB指出代碼中的錯誤。我現在更新了這個。
$ line = ....應替換爲:if(!$ line = $ file-> fgets()){break;} 如果$ checkLines超過csv文件的行數,那麼會出現錯誤。 – 2015-12-08 10:27:27
沒問題,除非您的修補程序在$ checkLines超過csv行數時仍會引發'無法讀取文件'異常。如果你想在while循環中構建檢查,它應該是:while($ file-> valid()&& $ i <$ checkLines) – 2015-12-09 12:32:35
'Works for me'不適用於錯誤的布爾邏輯(例如,你的錯誤處理配置可能不同)。你的while表達式使用OR不是AND,因此當$ i低於$ checkLines時,'文件結束'將被忽略。例如,在1行的CSV文件中,無論是否到達EOF,$ i都將被允許計數到三行,僅僅因爲(2 <= 2)= TRUE – 2015-12-10 10:07:39
這是我的解決方案。 它的作品,如果你知道你期望多少列。 最後,分隔符是$ actual_separation_character
$separator_1=",";
$separator_2=";";
$separator_3="\t";
$separator_4=":";
$separator_5="|";
$separator_1_number=0;
$separator_2_number=0;
$separator_3_number=0;
$separator_4_number=0;
$separator_5_number=0;
/* YOU NEED TO CHANGE THIS VARIABLE */
// Expected number of separation character (3 colums ==> 2 sepearation caharacter/row)
$expected_separation_character_number=2;
$file = fopen("upload/filename.csv","r");
while(! feof($file)) //read file rows
{
$row= fgets($file);
$row_1_replace=str_replace($separator_1,"",$row);
$row_1_length=strlen($row)-strlen($row_1_replace);
if(($row_1_length==$expected_separation_character_number)or($expected_separation_character_number==0)){
$separator_1_number=$separator_1_number+$row_1_length;
}
$row_2_replace=str_replace($separator_2,"",$row);
$row_2_length=strlen($row)-strlen($row_2_replace);
if(($row_2_length==$expected_separation_character_number)or($expected_separation_character_number==0)){
$separator_2_number=$separator_2_number+$row_2_length;
}
$row_3_replace=str_replace($separator_3,"",$row);
$row_3_length=strlen($row)-strlen($row_3_replace);
if(($row_3_length==$expected_separation_character_number)or($expected_separation_character_number==0)){
$separator_3_number=$separator_3_number+$row_3_length;
}
$row_4_replace=str_replace($separator_4,"",$row);
$row_4_length=strlen($row)-strlen($row_4_replace);
if(($row_4_length==$expected_separation_character_number)or($expected_separation_character_number==0)){
$separator_4_number=$separator_4_number+$row_4_length;
}
$row_5_replace=str_replace($separator_5,"",$row);
$row_5_length=strlen($row)-strlen($row_5_replace);
if(($row_5_length==$expected_separation_character_number)or($expected_separation_character_number==0)){
$separator_5_number=$separator_5_number+$row_5_length;
}
} // while(! feof($file)) END
fclose($file);
/* THE FILE ACTUAL SEPARATOR (delimiter) CHARACTER */
/* $actual_separation_character */
if ($separator_1_number==max($separator_1_number,$separator_2_number,$separator_3_number,$separator_4_number,$separator_5_number)){$actual_separation_character=$separator_1;}
else if ($separator_2_number==max($separator_1_number,$separator_2_number,$separator_3_number,$separator_4_number,$separator_5_number)){$actual_separation_character=$separator_2;}
else if ($separator_3_number==max($separator_1_number,$separator_2_number,$separator_3_number,$separator_4_number,$separator_5_number)){$actual_separation_character=$separator_3;}
else if ($separator_4_number==max($separator_1_number,$separator_2_number,$separator_3_number,$separator_4_number,$separator_5_number)){$actual_separation_character=$separator_4;}
else if ($separator_5_number==max($separator_1_number,$separator_2_number,$separator_3_number,$separator_4_number,$separator_5_number)){$actual_separation_character=$separator_5;}
else {$actual_separation_character=";";}
/*
if the number of columns more than what you expect, do something ...
*/
if ($expected_separation_character_number>0){
if ($separator_1_number==0 and $separator_2_number==0 and $separator_3_number==0 and $separator_4_number==0 and $separator_5_number==0){/* do something ! more columns than expected ! */}
}
感謝您的投入,我做了我的使用技巧:使preg_split,fgetcsv,循環等
但我實現了東西,是令人驚訝的不是在這裏,使用fgets而不是讀取整個文件,如果文件很重的話更好!
下面的代碼:
ini_set("auto_detect_line_endings", true);
function guessCsvDelimiter($filePath, $limitLines = 5) {
if (!is_readable($filePath) || !is_file($filePath)) {
return false;
}
$delimiters = array(
'tab' => "\t",
'comma' => ",",
'semicolon' => ";"
);
$fp = fopen($filePath, 'r', false);
$lineResults = array(
'tab' => array(),
'comma' => array(),
'semicolon' => array()
);
$lineIndex = 0;
while (!feof($fp)) {
$line = fgets($fp);
foreach ($delimiters as $key=>$delimiter) {
$lineResults[$key][$lineIndex] = count (fgetcsv($fp, 1024, $delimiter)) - 1;
}
$lineIndex++;
if ($lineIndex > $limitLines) break;
}
fclose($fp);
// Calculating average
foreach ($lineResults as $key=>$entry) {
$lineResults[$key] = array_sum($entry)/count($entry);
}
arsort($lineResults);
reset($lineResults);
return ($lineResults[0] !== $lineResults[1]) ? $delimiters[key($lineResults)] : $delimiters['comma'];
}
怎麼樣簡單的東西?
function findDelimiter($filePath, $limitLines = 5){
$file = new SplFileObject($filePath);
$delims = $file->getCsvControl();
return $delims[0];
}
這不起作用,因爲getCsvControl()只返回使用setCsvControl()函數手動設置的內容。它沒有做任何神奇的猜測。 – ethan 2015-05-05 18:29:14
如果在GB中有一個非常大的文件示例,請將頭幾行放在一個臨時文件中。在vi打開臨時文件
head test.txt > te1
vi te1
這不是OP要求的! – CinCout 2015-03-06 07:06:38
我用@Jay布哈特的解決方案,找出一個CSV文件的分隔符,但它並沒有爲我工作,所以我申請了幾個修復和徵求意見過程中要更多可以理解的。
見我的版本@Jay布哈特的功能:
function decide_csv_delimiter($file, $checkLines = 10) {
// use php's built in file parser class for validating the csv or txt file
$file = new SplFileObject($file);
// array of predefined delimiters. Add any more delimiters if you wish
$delimiters = array(',', '\t', ';', '|', ':');
// store all the occurences of each delimiter in an associative array
$number_of_delimiter_occurences = array();
$results = array();
$i = 0; // using 'i' for counting the number of actual row parsed
while ($file->valid() && $i <= $checkLines) {
$line = $file->fgets();
foreach ($delimiters as $idx => $delimiter){
$regExp = '/['.$delimiter.']/';
$fields = preg_split($regExp, $line);
// construct the array with all the keys as the delimiters
// and the values as the number of delimiter occurences
$number_of_delimiter_occurences[$delimiter] = count($fields);
}
$i++;
}
// get key of the largest value from the array (comapring only the array values)
// in our case, the array keys are the delimiters
$results = array_keys($number_of_delimiter_occurences, max($number_of_delimiter_occurences));
// in case the delimiter happens to be a 'tab' character ('\t'), return it in double quotes
// otherwise when using as delimiter it will give an error,
// because it is not recognised as a special character for 'tab' key,
// it shows up like a simple string composed of '\' and 't' characters, which is not accepted when parsing csv files
return $results[0] == '\t' ? "\t" : $results[0];
}
我個人使用此功能幫助自動解析文件與PHPExcel,它精美的作品,快捷。
我推薦解析至少10行,以使結果更準確。我個人使用它100行,它運行速度快,沒有延遲或滯後。您解析的線越多,結果得到的結果就越精確。
注意:這只是@Jay Bhatt對該問題的解決方案的修改版本。所有學分都歸於@Jay Bhatt。
- 1. 用內聯逗號分隔逗號分隔的csv文件
- 2. 在python中用逗號分隔逗號分隔的csv文件
- 3. 用逗號分隔多個逗號分隔的csv文件
- 4. MVC中的逗號分隔和分隔符文本字段4
- 5. 如何更改分隔在逗號分隔的製表符
- 6. 如何檢查.csv-File是否有逗號或分號作爲分隔符?
- 7. csv文件的分隔符,而不是逗號在php中
- 8. 製表符分隔符到逗號分隔符傳輸問題
- 9. 如何檢查逗號分隔字段中是否存在值?
- 10. 比較逗號分隔的字符串,其中柱是也逗號分隔
- 11. VB6逗號分隔CSV文件
- 12. 轉換被逗號分隔值,以逗號分隔字符串
- 13. 以逗號分隔的列表中的分隔符和自由文本字段
- 14. 逗號分隔值分隔
- 15. 使用Python在字段中分隔逗號分隔的文本
- 16. 檢查逗號分隔的字符串是否包含另一個以逗號分隔的字符串
- 17. 拆分字段的逗號分隔值
- 18. SQL:如何分隔由逗號分隔的字符串值?
- 19. 製表符分隔或逗號分隔輸出中的新行
- 20. 以逗號分隔,製表符分隔格式組合數據
- 21. 如何使用引號分隔C中分隔字段的CSV?
- 22. 如何使用逗號分隔CSV行?
- 23. 尋找逗號分隔值用冒號分隔符
- 24. 如何從csv文件分開逗號分隔的數據?
- 25. PHP將逗號分隔的字符串轉換爲CSV文件
- 26. mysql - 在逗號分隔的文本字段中查找匹配
- 27. String.split() - 如何區分製表符分隔值和逗號分隔值?
- 28. XSLT如何用逗號分隔的字符串查找值?
- 29. 如何避免使用XSLT以逗號分隔的逗號分隔的CSV
- 30. 逗號分隔字符串表
看看當然的擴展:)製表符分隔應該是'.tsv' – 2010-08-03 09:47:10