#file #unicode #batch-file
#файл #Юникод #пакетный файл
Вопрос:
У меня есть пакетный скрипт, который выполняет вызов с помощью sqlcmd для извлечения результатов инструкции SELECT в файл с именем temp.txt . В данных присутствуют некоторые посторонние символы, которые требуют от нас использования Unicode, поэтому temp.txt используется Unicode (кодовая страница 65001).
Как только данные в temp.txt скрипт подсчитывает количество строк и добавляет некоторые заголовки. Чтобы сделать это, он должен создать новый файл (назовем его newfile.txt ), добавьте заголовки и количество строк, а затем скопируйте в каждую строку из temp.txt для newfile.txt .
Все это работает нормально, за исключением того, что первая строка скопирована из temp.txt содержит знак порядка байтов в Юникоде; это означает, что первая строка, вместо того, чтобы выглядеть так:
1, Custom Page
вместо этого выглядит так:
1, Custom Page
Я не могу понять, как наилучшим образом справиться с этим.
Если бы я мог сказать sqlcmd предоставить мне Unicode без спецификации, это было бы идеально — попробовал поискать в Google, не смог понять.
Если бы я мог понять, как написать пакетный файл для цикла, который удаляет первые три символа только первой строки при копировании в temp.txt Я бы попробовал это, но после некоторого поиска в Google и экспериментов я разочарован.
Для записи соответствующий код выглядит следующим образом:
::%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 )
Пожалуйста, помогите мне, я схожу с ума из-за этой нелепой маленькой проблемы.
Ответ №1:
Вы могли бы попробовать
chcp 65001
в вашем пакетном скрипте перед вызовом sqlcmd. Это было бы не совсем интуитивно, но, возможно, это играет роль.
Если все остальное не удается, создайте собственную версию bomstrip
, и вы должны быть в курсе.
HTH
Обновить
У меня есть «исправленная» версия для Windows, которая повторно откроет stdin / stdout в двоичном режиме, так что вы избежите автоматического преобразования концов строк (sic!):
#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
Комментарии:
1. О да, я использую chcp 65001 перед вставкой кода. Я попробую bomstrip, хотя не похоже, что его можно вызвать из командной строки.
2. Я скомпилировал один на случай, если вы застряли. Мне просто нужно было бы отправить его, чтобы разместить где-нибудь на веб-сайте
3. Я его скомпилировал, просто пытаюсь выяснить, как вызвать его из командной строки.
4.
bomstrip < input.txt > output.txt
это фильтр в стиле UNIX.5. Я только что узнал, что bomstrip по умолчанию будет преобразовывать строки, если вы использовали версию C, я включил исправленную версию этого в свой пост здесь