我有一个批处理脚本,它调用sqlcmd将SELECT语句的结果拉到一个名为temp.txt的文件中。数据中有一些外部字符要求我们使用Unicode,所以temp.txt是Unicode (codepage 65001)。
一旦数据在temp.txt中,脚本将计算行数并附加一些标题。为此,它必须创建一个新文件(我们称之为newfile.txt),添加标题和行数,然后将每一行从temp.txt复制到newfile.txt中。
所有这些都工作得很好,除了从temp.txt复制进来的第一行有一个Unicode字节顺序标记;这意味着第一行,而不是像这样:
1, Custom Page
看起来像这样:
1, Custom Page
我想不出处理这件事的最好办法。如果我能告诉sqlcmd给我Unicode没有BOM,那将是完美的——试着谷歌一下,不能弄清楚。
如果我能弄清楚如何写一个批处理文件的FOR循环,删除的前三个字符,只有第一行时复制在temp.txt,我会尝试,但经过一些谷歌搜索和实验,我很沮丧在那里。
对于记录,相关代码看起来像这样:
::%1 = sql file to call; %2 = filename to be created; %3 = header for file; %4 = data type row for file
sqlcmd -I -f 65001 -W -k 1 -h -1 -s "," -S servername -d dbname -i %1 -o temp.txt
set counter=0
for /f %%a in (temp.txt) do set /a counter+=1
echo ^^!total rows=%counter% >> %2
echo !str1! >> %2
echo !str2! >> %2
for /F "delims=¶" %%i in (temp.txt) do ( echo %%i >> %2 )
请帮帮我,这个可笑的小问题快把我逼疯了
你可以试试
chcp 65001
在调用sqlcmd之前在批处理脚本中添加。这并不完全是直观的,但也许它起了作用。
如果这些都失败了,给你自己一个版本的 bomstrip
,你应该清楚。
HTH
更新我有一个windows的"固定"版本,它将在二进制模式下重新打开stdin/stdout,这样你就可以避免自动转换行结束符:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
void
usage(char *prog)
{
fprintf(stderr, "usage: %sn", prog);
exit(1);
}
int
main(int argc, char *argv[])
{
size_t nread;
char buf[65536];
char *utf8bom = "xefxbbxbf";
if (argc > 1)
usage(argv[0]);
/*
* On Windows, we need to use binary mode to read/write non-text archive
* formats. Force stdin/stdout into binary mode in case that is what
* we are using.
*/
#ifdef WIN32
if (fmt != archNull)
{
setmode(fileno(stdout), O_BINARY);
setmode(fileno(stdin), O_BINARY);
}
#endif
nread = fread(buf, 1, strlen(utf8bom), stdin);
if (nread == 0)
return 0;
if (strcmp(buf, utf8bom) != 0)
fwrite(buf, 1, nread, stdout);
for (;;) {
nread = fread(buf, 1, sizeof buf, stdin);
if (nread < 0)
exit(1);
if (nread == 0)
return 0;
fwrite(buf, 1, nread, stdout);
}
return 0;
}
现在你可以这样做:
> .bomstrip.exe < withoutbom > test
> md5sum.exe withoutbom test
f9f2e33bb16636f990180fa3fcbc93cb *withoutbom
f9f2e33bb16636f990180fa3fcbc93cb *test