检测csv文件
我需要检测什么样的行结尾的是在一个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文件做一些假设:
- 该文件不以空行开始;
- 第一行至少5个字节长;
- 第二行不是空的,也至少有5个字节长;
- 第一行的最后一列和最后一行的第一列不包含任何换行符;
- 你没有处理混合行尾的文件。
如果不能满足这些条件的算,你就必须添加一些验证步骤,如检查如果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