PHP的fgetcsv()无法读取所有行

3
我有一个PHP脚本,它正在读取远程CSV文件,并根据CSV文件的内容将产品添加到数据库中。目前大约有2800行产品,但该脚本在第1388行时停止。
我使用的代码如下:
while(($data = fgetcsv($fopen, 0, ",")) !== false):
  //stuff is done here...
endwhile;

我已将PHP内存限制设置为64M,甚至尝试了128M。我还将max_execution_time设置为60分钟。我还尝试按照以下方式更改代码:

while(($data = fgetcsv($fopen, 1000, ",", '\r')) !== false):
  //stuff is done here...
endwhile;

那确实导致了更多的行被解析,但数据却是不正确的,即图像列变成了描述列等。我认为这与添加\r作为行结尾有关。我尝试了\n,但没有成功。最后,我也在ini中将auto_detect_line_endings设置为true。
有人能提出我的数据被截断的原因吗?
谢谢, 西蒙
编辑
我注意到了一些有趣的事情。我在上面的代码中循环遍历每一行都有一个MySQL插入。现在,我的数据库中的最后一条记录是CSV文件中的第一行,这是否意味着文件是从最后一行向上解析的?
这些似乎是在或接近断点的行:
W-3066,  I Love Love Cheap And Chic,     Moschino, 3.4 oz,EDT Spray,Women,,"Introduced by the design house of Moschino, I love love has a blend of grapefruit, orange, lemon, red currant, tea rose, cinnamon leaves, musk, cedar and tonka wood. It is recommended for daytime wear.",http://www.perfume-worldwide.com/products/Women/Final/W-3066large.jpg,0,0,0,8011003991457
W-3070,  Adidas Floral Dream,            Adidas,   1.7 oz,EDT Spray,Women,,"Introduced in 2008, the notes are bergamot, lily, rose, tonka bean and vanilla.",http://www.perfume-worldwide.com/products/Women/Final/W-3070large.jpg,0,0,0,3412244310024
W-3071,  Adidas Fruity Rhythm,           Adidas,   1.7 oz,EDT Spray,Women,,"Introduced in 2008, the notes are black currant, raspberry, cyclamen, freesia and musk.",http://www.perfume-worldwide.com/products/Women/Final/W-3071large.jpg,0,0,0,3412244510004

解决方案

事实证明,将文件复制到我的服务器上并从副本中进行操作效果更好。我遵循的步骤如下:

  • 使用file_get_contents()函数读取远程文件内容
  • 然后使用iconv()函数将数据重新编码为UTF-8格式
  • 使用fopen()fwrite()fclose()函数创建一个临时文件,文件内容是上面编码后的数据
  • 使用chmod()函数将该文件的权限设置为0750
  • 然后将fgetcsv()函数应用于我的临时文件
  • 完成所有需要完成的操作
  • 使用unlink()函数删除临时文件

这样就解决了问题。因此,我怀疑问题的一半实际上是远程服务器超时,另一半是编码问题。

感谢大家给予的正确指引。


似乎你的 CSV 文件可能包含原始二进制图像数据(在你所提到的“图像列”中),你能确认一下吗? - Maxime Pacary
@Frosty - 不是的,图片列只是一个代码,例如 w-12345。 - SimonDowdles
关于您的编辑,我们确实需要看到CSV文件的样本,如果我们不知道原因,就无法修复它。 - RobertPitt
源代码在 http://pastebin.com/fLngbWYu。 - SimonDowdles
如果答案被标记为正确,就不需要使用“[SOLVED]”前缀,因为它会以不同的颜色突出显示。 - RobertPitt
2个回答

2
文件格式正确吗?您是否尝试在一些可以指定分隔符和行结束符的CSV阅读器中打开文件?根据这个信息判断,虽然解析出了更多的行,但数据却不正确,例如图像列变成了描述列等。我会认为数据可能已经损坏(即某些描述中包含了逗号、行结束符等)。如果数据是动态生成的且格式不正确,则会发生这种情况。同时,在文本编辑器(如notepad++)中打开并查看文件。

谢谢,现在在Notepad++中检查。 - SimonDowdles

2

首先我有一些问题要问你:

  • 第1388行,第1388行和第1389行分别是什么
  • 是否输出了任何错误
  • 当您到达最后一行时,$data [0] === null是这样的吗?

关于内存限制的信息可能不是导致问题的原因,因为每次迭代fgetcsv只读取一行,内存中始终只有1行数据。

在循环中,如果您不断将数据放入数组中或将它们连接在一起,这可能会导致内存泄漏,但您必须展示更深入的代码。

CSV文件必须相当结构化,才能使 fgetcsv 正确解析它。使用 CSV 文件时请记住以下规则:

  • 第一行必须始终是列名
  • 所有其他行都是数据行:
    • 每个元素应该用,分隔
    • 如果一个元素包含空格或逗号、'\n''\r''\r\n',则应将其用双引号括起来

一个有效的 CSV 文件示例应如下所示:

id, firstname, lastname, age, profile_description
0,  Robert,    Pitt,     22,  "this string has spaces, and has a comma"

您应该验证结构是否正确,如果不正确,则应修复此问题,直到解析器能够正确读取数据,然后可以将数据清晰地放置在新的CSV文件中,同时注意所有小的不正确结构。


@Robert - 我会查看那一行,并输出最后一行的数据,以查看它是否为空。问题是我无法控制数据,CSV文件每晚都是动态生成的,并从数据库记录中填充。我现在会去查看并回复你。 - SimonDowdles
@Robert - 上面有三行代码,我正在等待 PHP 脚本运行完成,然后我会粘贴最后解析的行的输出。感谢您的所有帮助。 - SimonDowdles
看起来 CSV 文件对我来说没问题,它可以正常解析 2.6K 行,所以肯定是其他原因导致了问题,请尝试将错误更改为 On >> ini_set("display_errors", "On"); - RobertPitt
@robert - 有趣的是,当我在OpenOffice.org中打开CSV文件并将其另存为CSV时,它解析了所有行,但数据仍然不稳定。我想知道这是否是编码问题? - SimonDowdles
如果可能的话,您应该只在不应用任何格式或隐藏字符的编辑器中编辑生成的文件,例如“记事本”和“记事本++(UTF-8无BOM)”。 - RobertPitt
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接