Просмотр полной версии : CSV памагити
Raikkonen
06.12.2021, 12:38
Добрый день!
мне не дано пользоваться поиском по форуму, подскажите наверняка есть нормальные примеры конвертации в CSV (юникод) обычных real word и других данных
с переводами строк и символом окончания
я пока пользуюсь
REAL_TO_WSTRING и StrConcatW
И все бы ничего, только не знаю как закончить файл, в конце какая-то фигня все время.
Ну и может есть более изящные примеры.
Евгений Кислов
06.12.2021, 12:40
Добрый день.
И все бы ничего, только не знаю как закончить файл, в конце какая-то фигня все время.
Опишите, пожалуйста, проблему так, чтобы я и другие пользователи смогли ее понять.
Выложите ваш проект, с которым можно воспроизвести проблему.
Raikkonen
06.12.2021, 12:53
Опишите, пожалуйста, проблему так, чтобы я и другие пользователи смогли ее понять.
Выложите ваш проект, с которым можно воспроизвести проблему.
Проект слишком большой чтобы его выкладывать, в нем еще капаться придется.
Могу выложить функцию преобразования и результат.
FUNCTION_BLOCK create_csv_file
VAR_INPUT
made: BOOL;
file_data: POINTER TO struct_bin_file_record;
END_VAR
VAR_OUTPUT
done: BOOL;
csv_result: WSTRING(10000);
END_VAR
VAR
t_state: INT;
run: R_TRIG;
i: INT;
t_wstring: WSTRING;
END_VAR
VAR CONSTANT
devider: WSTRING := ",";
new_liner: WSTRING := "$N";
ender: WSTRING := "$P";
END_VAR
run(CLK:=made);
CASE t_state OF
0: //======================================= wait for execute =====
IF run.Q THEN
t_state := 1;
done := FALSE;
csv_result := STRING_TO_WSTRING('Перемещение,Давление,Усилие$N') ;
END_IF
1: //======================================= create file =====
FOR i:=0 TO file_data^.table_point DO
t_wstring := REAL_TO_WSTRING(file_data^.table[i].len);
StrConcatW ( ADR(t_wstring) , ADR(csv_result) , SIZEOF(csv_result) );
StrConcatW ( ADR(devider) , ADR(csv_result) , SIZEOF(csv_result) );
t_wstring := REAL_TO_WSTRING(file_data^.table[i].pres);
StrConcatW ( ADR(t_wstring) , ADR(csv_result) , SIZEOF(csv_result) );
StrConcatW ( ADR(devider) , ADR(csv_result) , SIZEOF(csv_result) );
t_wstring := REAL_TO_WSTRING(file_data^.table[i].force);
StrConcatW ( ADR(t_wstring) , ADR(csv_result) , SIZEOF(csv_result) );
StrConcatW ( ADR(devider) , ADR(csv_result) , SIZEOF(csv_result) );
StrConcatW ( ADR(new_liner) , ADR(csv_result) , SIZEOF(csv_result) );
END_FOR
t_state := 2;
2: //======================================= write to buffer =====
t_wstring := " , , ,$N";
StrConcatW ( ADR(t_wstring) , ADR(csv_result) , SIZEOF(csv_result) );
t_wstring := REAL_TO_WSTRING(file_data^.result_Lenght);
StrConcatW ( ADR(t_wstring) , ADR(csv_result) , SIZEOF(csv_result) );
StrConcatW ( ADR(devider) , ADR(csv_result) , SIZEOF(csv_result) );
t_wstring := REAL_TO_WSTRING(file_data^.result_Preasure);
StrConcatW ( ADR(t_wstring) , ADR(csv_result) , SIZEOF(csv_result) );
StrConcatW ( ADR(devider) , ADR(csv_result) , SIZEOF(csv_result) );
t_wstring := REAL_TO_WSTRING(file_data^.result_Force);
StrConcatW ( ADR(t_wstring) , ADR(csv_result) , SIZEOF(csv_result) );
StrConcatW ( ADR(devider) , ADR(csv_result) , SIZEOF(csv_result) );
StrConcatW ( ADR(ender) , ADR(csv_result) , SIZEOF(csv_result) );
done := TRUE;
t_state := 0;
END_CASE
результат всего этого в переменной в кодесисе вот такой:
58230
а в экселе вот такой
58229
Проблема в том что он что-то лишнее в конце добавляет.
Гипотетически это конечно может делать функция записи в файл, но другие файлы она ок записывает......
И еще проблема в том, что полученный фал открывает эксель, а ворд, блокнот и другие не открывают.
Вот может подскажете нужное преобразование, а не стринг_встринг.
Евгений Кислов
06.12.2021, 13:20
1. STRING_TO_WSTRING в данном случае не подойдет.
http://www.owen.ru/forum/showthread.php?t=28167&p=270862&viewfull=1#post270862
2. Вам какой нужен формат Юникода - UTF-8, UTF-16 или какой-то другой?
Если UTF-16 подходит - посмотрите этот пример:
https://owen.ru/forum/showthread.php?t=27332&p=262454&viewfull=1#post262454
Raikkonen
06.12.2021, 13:35
Спасибо! А нет идей почему в конце какая-то гадость приклеивается?
Евгений Кислов
06.12.2021, 13:44
Спасибо! А нет идей почему в конце какая-то гадость приклеивается?
Этот файл сформирован одним вызовом вашего блока или несколькими?
Raikkonen
06.12.2021, 13:49
вот тот блок формирует wstring(10000)
а потом вот таким кодом она записывается за один раз
fbFileWrite(xExecute:=TRUE, hFile:=hBinFile, pBuffer:=file_data, szSize:=SIZEOF(file_data^));
это экземпляр FILE.Write
после этого делаю Flush
пишу на USB-флешку
обработчик вроде нормально написал. жду когда у него будет Done
Raikkonen
06.12.2021, 13:57
Благодаря предыдущим двум ссылкам файлик открывается теперь хоть вордом хоть блокнотом хоть экселем, спасибо большое!
и real стали контролируемыми
Осталось победить кракозябру в конце
Евгений Кислов
06.12.2021, 13:59
А зачем записывать в файл все 20002 байта буфера?
Фактически же ваш набор строк занимает гораздо меньше.
Возможно, вы при создании вашей строки перезатираете терминирующей ноль - посмотрите файл HEX-редактором, чтобы получить больше информации о происходящем.
Raikkonen
06.12.2021, 14:00
а я б с радостью.
руками считать количество символов?
а нет возможности этому csv_result: WSTRING(10000); задать каким-то чудесным символом конец строки?
ВОВОВО а как приклеить терминирующий ноль?
это все равно руками считать количество символов и после них приклеить 16#0000 ?
руками сложновато считать количество символов из-за того что у меня есть числа, их длинна варьируется.
Это перед каждой проверкой еще смотреть длинну..... может существуют более изящные решения?
Евгений Кислов
06.12.2021, 14:08
После того, как сформируете csv_result - скопируйте его в ARRAY [0...10000] OF WORD и посмотрите содержимое.
Это должно прояснить ситуацию - отследите, что находится после символов вашей строки в буфере в этот момент.
Raikkonen
06.12.2021, 14:16
После того, как сформируете csv_result - скоруйте его в ARRAY [0...10000] OF WORD и посмотрите содержимое.
Это должно прояснить ситуацию - отследите, что находится после символов вашей строки в буфере в этот момент.
Сейчас сделаю
А вот эта конструукция csv_result := OSU.CP1251_TO_UNICODE(' Перемещение,Давление,Усилие$N');
будет нормально работать? меня немного смущает $N
Евгений Кислов
06.12.2021, 14:26
Сейчас сделаю
А вот эта конструукция csv_result := OSU.CP1251_TO_UNICODE(' Перемещение,Давление,Усилие$N');
будет нормально работать? меня немного смущает $N
Да, нормально.
Raikkonen
06.12.2021, 14:27
58231
Вот такой вот текст.
Первый NUL является 60 символом, и в массиве WORD там реально 0
Второй NUL является 80 символом и массиве WORD там тоже 0
НО после 80 символа еще есть значения, которые неизвестно откуда берутся, но уже не отображаются.
Похоже сейчас буду считать длину........
ЛЮБОПЫТНЫЙ ФАКТ!!! после 80 символа 0 идут 17 19 0
Пошел писать прогу с подсчетом длины
Raikkonen
06.12.2021, 14:48
Сейчас ФБ выглядит вот так
FUNCTION_BLOCK create_csv_file
VAR_INPUT
made: BOOL;
file_data: POINTER TO struct_bin_file_record;
END_VAR
VAR_OUTPUT
done: BOOL;
csv_result: WSTRING(10000);
csv_lenght: DINT;
END_VAR
VAR
t_state: INT;
run: R_TRIG;
i: INT;
t_wstring: WSTRING;
END_VAR
VAR CONSTANT
devider: WSTRING := ",";
new_liner: WSTRING := "$N";
END_VAR
run(CLK:=made);
CASE t_state OF
0: //======================================= wait for execute =====
IF run.Q THEN
t_state := 1;
done := FALSE;
csv_result := OSU.CP1251_TO_UNICODE(' Перемещение,Давление,Усилие$N');
csv_result[0] := 16#FEFF;
csv_lenght := StrLenW(ADR(csv_result));
END_IF
1: //======================================= create file =====
FOR i:=0 TO file_data^.table_point DO
t_wstring := OSU.CP1251_TO_UNICODE( OSU.REAL_TO_STRING_FORMAT(file_data^.table[i].len, 3, OSU.DOT) );
StrConcatW ( ADR(t_wstring) , ADR(csv_result) , SIZEOF(csv_result) );
StrConcatW ( ADR(devider) , ADR(csv_result) , SIZEOF(csv_result) );
csv_lenght := csv_lenght + StrLenW(ADR(t_wstring)) + 1;
t_wstring := OSU.CP1251_TO_UNICODE( OSU.REAL_TO_STRING_FORMAT(file_data^.table[i].pres, 1, OSU.DOT) );
StrConcatW ( ADR(t_wstring) , ADR(csv_result) , SIZEOF(csv_result) );
StrConcatW ( ADR(devider) , ADR(csv_result) , SIZEOF(csv_result) );
csv_lenght := csv_lenght + StrLenW(ADR(t_wstring)) + 1;
t_wstring := OSU.CP1251_TO_UNICODE( OSU.REAL_TO_STRING_FORMAT(file_data^.table[i].force, 0, OSU.DOT) );
StrConcatW ( ADR(t_wstring) , ADR(csv_result) , SIZEOF(csv_result) );
csv_lenght := csv_lenght + StrLenW(ADR(t_wstring));
StrConcatW ( ADR(new_liner) , ADR(csv_result) , SIZEOF(csv_result) );
csv_lenght := csv_lenght + 1;
END_FOR
t_state := 2;
2: //======================================= write to buffer =====
t_wstring := " , , ,$N";
StrConcatW ( ADR(t_wstring) , ADR(csv_result) , SIZEOF(csv_result) );
csv_lenght := csv_lenght + StrLenW(ADR(t_wstring));
t_wstring := OSU.CP1251_TO_UNICODE( OSU.REAL_TO_STRING_FORMAT(file_data^.result_Lenght , 3, OSU.DOT) );
StrConcatW ( ADR(t_wstring) , ADR(csv_result) , SIZEOF(csv_result) );
StrConcatW ( ADR(devider) , ADR(csv_result) , SIZEOF(csv_result) );
csv_lenght := csv_lenght + StrLenW(ADR(t_wstring)) + 1;
t_wstring := OSU.CP1251_TO_UNICODE( OSU.REAL_TO_STRING_FORMAT(file_data^.result_Preasu re, 1, OSU.DOT) );
StrConcatW ( ADR(t_wstring) , ADR(csv_result) , SIZEOF(csv_result) );
StrConcatW ( ADR(devider) , ADR(csv_result) , SIZEOF(csv_result) );
csv_lenght := csv_lenght + StrLenW(ADR(t_wstring)) + 1;
t_wstring := OSU.CP1251_TO_UNICODE( OSU.REAL_TO_STRING_FORMAT(file_data^.result_Force, 0, OSU.DOT) );
StrConcatW ( ADR(t_wstring) , ADR(csv_result) , SIZEOF(csv_result) );
csv_lenght := csv_lenght + StrLenW(ADR(t_wstring));
csv_result[csv_lenght] := 16#0000;
csv_lenght := csv_lenght + 1;
done := TRUE;
t_state := 0;
END_CASE
и работает на 6+ !!!
спасибо большое!!!
глядишь еще и эффективнее работает, потому что теперь в файл записывается известный размер
Powered by vBulletin® Version 4.2.3 Copyright © 2025 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot