如何使用Perl或Python向文件添加EOF?

0 投票
3 回答
3779 浏览
提问于 2025-04-15 19:57

我正在尝试将大量数据一次性插入到SQL Server Express数据库中。当我在Windows XP的命令提示符下使用bcp命令时,出现了以下错误:

C:\temp>bcp  in  -T -f  -S 

Starting copy...
SQLState = S1000, NativeError = 0
Error = [Microsoft][SQL Native Client]Unexpected EOF encountered in BCP data-file

0 rows copied.
Network packet size (bytes): 4096
Clock Time (ms.) Total     : 4391

所以,这里有一个关于EOF(文件结束符)的问题。请问如何用Perl或Python给这个文件添加一个正确的EOF字符呢?

3 个回答

1

这不是因为缺少文件结束符(EOF)的问题,而是因为文件结束符存在,但 bcp 工具没有预料到它。

我对 bcp 工具不是很精通,但看起来你的数据文件格式有一些问题。

3

“意外的EOF”意味着bcp读取器在期待更多数据时遇到了文件结束符(EOF)。这个EOF可能是:

(1) 实际的物理文件结束(没有更多字节可以读取)。这意味着你的数据格式有问题。检查一下文件末尾,看看是否有不完整的记录。

或者

(2) 在Windows系统中,程序在以文本模式读取文件时,会遵循一个古老的约定,这个约定是从MS-DOS时代继承下来的。它把Ctrl-Z(也叫^Z,或者\x1A,或者SUB,或者替代符)当作文件结束标记来处理,而不仅仅是在终端中。这包括Python,因为这种行为是由C标准库决定的。检查一下你的数据中是否有\x1A。

更新:为了更清晰地回应评论:

在Notepad++中,你可以通过点击“查看 / 显示符号 / 显示所有字符”来显示一些不寻常的字符。你可以按Ctrl-F,输入\x1a到“查找内容”框中,然后在搜索面板中选择“扩展”选项。

或者,你可以用一点Python代码找到第一个Ctrl-Z出现的行号:

bytes = open('bcp.dat', 'rb').read()
zpos = bytes.find('\x1a')
# if zpos is -1, no Ctrl-Z in file
print 1 + bytes[:zpos].count('\r\n')

你创建.dat文件的地方并不重要。意外的Ctrl-Z可以在任何操作系统创建的文件中的任何地方发生。重要的是在读取这个文件时是否是以文本文件的方式——如果是在Windows上,那就会出问题!

3

EOF是“文件结束”的意思。发生这种情况可能是因为文件没有完整;软件在等待数据,但已经没有数据可以获取了。

这种情况通常发生在:

  • 导出过程被中断(比如在导出时关闭了软件)
  • 在复制转储文件时中止了复制
  • 在导出过程中磁盘空间满了

就是这些情况。

顺便说一下,虽然EOF通常只是表示文件的结束,但确实存在一个EOF字符。这个字符的使用是因为终端(命令行)输入并不像文件那样有明确的结束,但有时需要向某些工具传递一个EOF。我觉得在真实的文件中并不常用这个字符,至少不是用来表示文件结束。文件系统自己非常清楚文件何时结束,不需要额外的标识来判断。

编辑 这段内容是从John Machin的评论中“无耻地”复制过来的

在真实文件中,这种情况也可能(无意中)发生。只需要(1)一个数据录入用户错误地按下Ctrl-Z,屏幕上什么也看不见,然后按下想要的Shift-Z,继续输入;(2)一些验证软件(比如由公司总裁的侄子编写的)乐于接受文本字段中的Ctrl+任意键,这样你的数据库里就藏着一个小炸弹,等着有人对一个平面文件发起查询。

撰写回答