我需要檢測什麼樣的行結尾的是在一個CSV文件的行結束字符:檢測csv文件
\n
(UNIX默認)\r
(Mac的Excel中)\r\n
(視窗)- 或其他任何
要獲得分隔符,encosure &轉義字符,我使用SplFileObject::getCsvControl - 對於結束字符的行會有很大的幫助。
打開我還沒有試過這種文件
我需要檢測什麼樣的行結尾的是在一個CSV文件的行結束字符:檢測csv文件
\n
(UNIX默認)\r
(Mac的Excel中)\r\n
(視窗)要獲得分隔符,encosure &轉義字符,我使用SplFileObject::getCsvControl - 對於結束字符的行會有很大的幫助。
打開我還沒有試過這種文件
,但我認爲這是所以這裏一個有趣的問題是我在一個可能的解決方案裂縫:
// first, have PHP auto-detect the line endings, like @AbraCadaver suggested:
ini_set("auto_detect_line_endings", true);
// now open the file and read a single line from it
$file = fopen('/path/to/file.csv', 'r');
fgets($file);
// fgets() moves the pointer, so get the current position
$position = ftell($file);
// now get a couple bytes (here: 10) from around that position
fseek($file, $position - 5);
$data = fread($file, 10);
// we no longer need the file
fclose($file);
// now find out how many of each type EOL there are in those 10 bytes
// expected result is that two of these will be 0 and one will be 1
$eols = array(
"\r\n" => substr_count($data, "\r\n"),
"\r" => substr_count($data, "\r"),
"\n" => substr_count($data, "\n"),
);
// sort the EOL count in reverse order, so that the EOL with the highest
// count (expected: 1) will be the first item
arsort($eols);
// get the first item's key
$eol = key($eols);
// $eol will now be "\r\n", "\r" or "\n"
可能有這樣做的更好的方法,並注意我在這裏對你的CSV文件做一些假設:
如果不能滿足這些條件的算,你就必須添加一些驗證步驟,如檢查如果fgets()
結果竟是幾個字符的字符串。如果行可能少於5個字節,那麼您可能還必須考慮到結尾可能爲的行爲\r\n
的事實,但通過查找原始字節,我們碰巧遇到了像"abcde\r\nfg\r"
這樣的字符串,在那裏我們只是錯過了在第二個\n
,你會得到一個不正確的結果。
但是,如果你可以確定CSV文件的構造,這可能是一個(骯髒的,我承認)步驟正確的方向。
這是一個有趣的問題 - 沒有人能夠在這裏給你一個完整的解決方案。明顯的做法是:
1)繼續閱讀文件,直到\ r或\ n第一次出現爲止。在前者的情況下,再讀一個字符來檢查它是否跟着\ n。
這聽起來很簡單 - 但您需要實現報價處理以確定EOL是否嵌入在引用數據字段中 - 而且您不知道數據是如何引用的。除了檢測開頭和結尾的引號外,還需要能夠確定引號字符是否被轉義 - 並且至少有兩種不同的轉義字符轉義方式。
2)分析文件中字符的頻率。如果您可以忽略空格,alhpa字符和數字,那麼最常見的餘數應該是CSV元字符。但這些對於非常短的文件不起作用。
3)在文件中創建數據串的表示並查找記錄模式,例如,如果你發現數字,空間,阿爾法,空間,數字,標點符號,數字,spache,阿爾法,標點符號,阿爾法,空間,數字,標點符號,數字,空間,阿爾法,空間,數字,標點符號那麼你可能會認爲字段分隔符是一個空間,記錄由標點符號分隔,也可以顯示爲嵌入字符。
但是這需要一些非常複雜的代碼。
如果是我,我會問誰提供文件來提供文件格式的詳細信息。或者如果這些信息不可用,請用十六進制編輯器打開文件。
在一般情況下 - 你無法檢測到它,例如文件可能有混合行結束,你真正的問題是什麼? –
不確定所有函數都使用它,但是:'ini_set(「auto_detect_line_endings」,true);'至於'SplFileObject :: getCsvControl',注意這個函數不會奇怪地從給定的文件中猜測CSV控件,而是返回已被優先設置SplFileObject :: setCsvControl()._ – AbraCadaver
@IlyaBursov我需要導入一個csv到我的MySQL數據庫與LOAD數據INFILE,但該查詢必須明確定義行結束字符。 – PeterInvincible