Парсинг текстового файла с SD карты
- Войдите на сайт для отправки комментариев
Вс, 01/07/2018 - 16:34
Добрый день товарищи.
Стоит задача разобрать текстовый файл на переменные. Файл лежит на SD карте.
Удалось считать файл с карты в строку и вывести содержимое строки в монитор для теста.
теперь некоторый затык с разбором.
вот содержимое файла:
F:\MUZON.mp3 № Модуля;№ Канала;Начало;Задержка 1;1;00:09.207;00:10.207;00:01.000;01.000;;; 1;2;00:12.207;00:15.207;00:01.000;03.000;;; 1;3;00:19.142;00:20.142;00:01.000;01.000;;; 1;4;00:25.108;00:25.108;00:01.000;00.000;;; 1;5;00:30.000;00:30.000;00:01.000;00.000;;; 1;6;00:35.000;00:35.000;00:01.000;00.000;;; 1;7;00:40.000;00:40.000;00:01.000;00.000;;; 1;8;00:45.000;00:45.000;00:00.000;00.000;;; 1;9;00:50.000;00:50.000;00:00.000;00.000;;; 1;10;00:55.000;00:55.000;00:00.000;00.000;;; 1;11;01:00.000;01:00.000;00:00.000;00.000;;; 1;12;01:05.000;01:05.000;00:00.000;00.000;;; 1;13;01:10.000;01:10.000;00:00.000;00.000;;; 1;14;01:15.000;01:15.000;00:00.000;00.000;;; 1;15;01:20.000;01:20.000;00:00.000;00.000;;; 1;16;01:25.000;01:25.000;00:00.000;00.000;;; 1;17;01:30.000;01:30.000;00:00.000;00.000;;; 1;18;01:35.000;01:35.000;00:00.000;00.000;;; 1;19;01:40.000;01:40.000;00:00.000;00.000;;; 1;20;01:45.000;01:45.000;00:00.000;00.000;;; 1;21;01:50.000;01:50.000;00:00.000;00.000;;; 1;22;01:55.000;01:55.000;00:00.000;00.000;;; 1;23;02:00.000;02:00.000;00:00.000;00.000;;; 1;24;02:05.000;02:05.000;00:00.000;00.000;;; 1;25;02:10.000;02:10.000;00:00.000;00.000;;; 1;26;02:15.000;02:15.000;00:00.000;00.000;;; 1;27;02:20.000;02:20.000;00:00.000;00.000;;; 1;28;02:25.000;02:25.000;00:00.000;00.000;;; 1;29;02:30.000;02:30.000;00:00.000;00.000;;; 1;30;02:35.000;02:35.000;00:00.000;00.000;;; 1;31;02:40.000;02:40.000;00:00.000;00.000;;; 1;32;02:45.000;02:45.000;00:00.000;00.000;;;
Строки под номерами 1 и 3 нужно пропустить и начать брать данные начиная с 5й строки файла.
переменные разделеные символом ";" группа параметров оканчивается символами ";;;" и переходом на следующую строку.
вот код что я уже написал
//----------------------------------------------------------------------------------------
#include <SD.h>
#include <SPI.h>
//----------------------------------------------------------------------------------------
const int chipSelect = 53; // Номер пина для CD карты для MEGA CS
File dataFile;
String buffer;//тут хранится прочитанный из карты текст
boolean SDfound;
//----------------------------------------------------------------------------------------
void setup()
{
Serial.begin(9600); // Инициализируем UART.
Serial.println("Initializing SD card..."); // Инициализация SD-карты...
pinMode(chipSelect, OUTPUT);// Настроим выход выбора микросхемы на вывод.
if (SDfound == 0)
{
if (!SD.begin(chipSelect))
{
Serial.print("The SD card cannot be found");
while(1);
}
}
SDfound = 1;
dataFile = SD.open("TEST.zpl");//Откроем файл
Serial.println("SD card ok.");
if (!dataFile)
{
Serial.print("text fail eror"); // Текстовый файл не открывается
while(1);
}
while (dataFile.available()) //Читаем содержимое файла
{
buffer = dataFile.readStringUntil('\n');//Считываем с карты весь дотекст в строку до символа окончания.
Serial.println(buffer); // для отладки отправляем по UART все что прочитали с карты.
}
dataFile.close(); //закроем файл
}
//----------------------------------------------------------------------------------------
void loop()
{
}
//----------------------------------------------------------------------------------------Осталось разобратся как разобрать текст который лежит в строке на группы а их на отдельные парасетры.
А никак нельзя вместо ;;; использовать тот же перевод строки? Или хотя бы люой одиночный символ? Или протокол не Вами задаётся?
Добрый день евгений неполучится файл создаёт программа для PC а ардуинка его использует с флешки
Но по идее символ перевода строки там всеравно должен быть если судить по структуре файла
Тогда Ваша тема - функция strtok
Пример раздербанивания строки на параметры по разделителю я двавал вот здесь - http://arduino.ru/forum/programmirovanie/eshche-raz-pro-strtok#comment-279523
Вот был ещё пример, на этот раз с признаком начала и признаком конца, там по точкам разбивается - http://arduino.ru/forum/programmirovanie/parsing#comment-312218
Это формат - CSV. Гугл по этому поводу выдаем гору вариантов для всех мыслимых языков, и для Си тоже. Но честно говоря эта задача настолько тривиальная, что если Вам в голову не пришло ни одной идеи - програмирование не для Вас. Да, ;;; - это не конец группы, это три опциональных параметра. Конец группы - символ перевода строки.
вот что получается
//---------------------------------------------------------------------------------------- #include <SD.h> #include <SPI.h> #include <string.h> template <typename T> inline Print & operator << (Print &s, T n) { s.print(n); return s; } //---------------------------------------------------------------------------------------- const int chipSelect = 53; // Номер пина для CD карты для MEGA CS File dataFile; String buffer;//тут хранится прочитанный из карты текст boolean SDfound; //char charBuf[64]; //---------------------------------------------------------------------------------------- void setup() { Serial.begin(9600); // Инициализируем UART. Serial.println("Initializing SD card..."); // Инициализация SD-карты... pinMode(chipSelect, OUTPUT);// Настроим выход выбора микросхемы на вывод. if (SDfound == 0) { if (!SD.begin(chipSelect)) { Serial.print("The SD card cannot be found"); while(1); } } SDfound = 1; dataFile = SD.open("TEST.zpl");//Откроем файл Serial.println("SD card ok."); if (!dataFile) { Serial.print("text fail eror"); // Текстовый файл не открывается while(1); } while (dataFile.available()) //Читаем содержимое файла { buffer = dataFile.readStringUntil('\n');//Считываем с карты весь дотекст в строку до символа окончания. Serial.println(buffer); // для отладки отправляем по UART все что прочитали с карты. } dataFile.close(); //закроем файл Serial.println("Test"); char charBuf[buffer.length()+1]; buffer.toCharArray(charBuf, buffer.length()); // Serial.println (charBuf); char * pch; pch = strtok (charBuf,";"); while (pch != NULL) { Serial.println (pch); pch = strtok (NULL, ";"); } } //---------------------------------------------------------------------------------------- void loop() { } //----------------------------------------------------------------------------------------на выходе имеем
разобралась последняя строка остальные не видит почему то
Вы бы убрали чтение с карты, а текст забили бы просто в константу char * - сразу код бы стал короче и суть виднее. Да и ошибки чтения исключили бы - так сказать решали бы проблему в чистом виде.
Евгений суть в том что читать нужно именно скарты потому что значения настроек в этом тексте будут менятся с помощью программы редактора на ПК. Убрать чтение с карты и вынести содержание текста в константы допускается разве что для тестирования.
Для тестирования вам и предлагают вынести...
разве что для тестирования.
А я что говорю? Чтобы при отладке strtok ничто другое внимание не отвлекало.
Вот запустите такой код
void setup(void) { Serial.begin(57600); char *s = (char *) "1;2;00:12.207;00:15.207;00:01.000;03.000;;;\n" "1;3;00:19.142;00:20.142;00:01.000;01.000;;;\n" "1;4;00:25.108;00:25.108;00:01.000;00.000;;;\n" "1;5;00:30.000;00:30.000;00:01.000;00.000;;;\n" "1;6;00:35.000;00:35.000;00:01.000;00.000;;;\n" "1;7;00:40.000;00:40.000;00:01.000;00.000;;;\n" "1;8;00:45.000;00:45.000;00:00.000;00.000;;;\n"; for (char *p = strtok(s, ";"); p; p = strtok(NULL, ";\n")) { Serial.println(p); } } void loop (void) {}У меня получился вот такой результат
Это то, что нужно? Если "то", то, как видите, делов-то - всего одна строчка. И суть дела намного виднее, чем если код перегружен посторонними операциями.
да это то что нужно только нужно вместо тестового вывода в порт засунуть результат в массив чтобы было можно дальше раскидать по переменным и еще там две текстовых строки сверху которые не используются но присуствуют в файле
F:\MUZON.mp3
№ Модуля;№ Канала;Начало;Задержка
да это то что нужно только нужно вместо тестового вывода в порт засунуть результат в массив чтобы было можно дальше раскидать по переменным и еще там две текстовых строки сверху которые не используются но присуствуют в файле
F:\MUZON.mp3
№ Модуля;№ Канала;Начало;Задержка
Ну, нужно - делайте. Как пользоваться strtok я Вам показал. А проигнорировать первые две строки - как-нибудь сообразите. Ну, и пихайте куда Вам надо. Парсинг-то работает, а с результатом делайте что хотите.
Евгений вот что получилось
Вот так всё работает
//---------------------------------------------------------------------------------------- struct kv { char *value; char *Slat; char *Cue; char *Time; }; //---------------------------------------------------------------------------------------- void setup() { Serial.begin(9600); while (!Serial); char S[] = "1;1;00:09.207;00:10.207;00:01.000;01.000;;;\n" "1;2;00:12.207;00:15.207;00:01.000;03.000;;;\n" "1;3;00:19.142;00:20.142;00:01.000;01.000;;;\n" "1;4;00:25.108;00:25.108;00:01.000;00.000;;;\n" "1;5;00:30.000;00:30.000;00:01.000;00.000;;;\n" "1;6;00:35.000;00:35.000;00:01.000;00.000;;;\n" "1;7;00:40.000;00:40.000;00:01.000;00.000;;;\n" "1;8;00:45.000;00:45.000;00:00.000;00.000;;;\n" "1;9;00:50.000;00:50.000;00:00.000;00.000;;;\n" "1;10;00:55.000;00:55.000;00:00.000;00.000;;;\n" "1;11;01:00.000;01:00.000;00:00.000;00.000;;;\n" "1;12;01:05.000;01:05.000;00:00.000;00.000;;;\n" "1;13;01:10.000;01:10.000;00:00.000;00.000;;;\n" "1;14;01:15.000;01:15.000;00:00.000;00.000;;;\n" "1;15;01:20.000;01:20.000;00:00.000;00.000;;;\n" "1;16;01:25.000;01:25.000;00:00.000;00.000;;;\n" "1;17;01:30.000;01:30.000;00:00.000;00.000;;;\n" "1;18;01:35.000;01:35.000;00:00.000;00.000;;;\n" "1;19;01:40.000;01:40.000;00:00.000;00.000;;;\n" "1;20;01:45.000;01:45.000;00:00.000;00.000;;;\n" "1;21;01:50.000;01:50.000;00:00.000;00.000;;;\n" "1;22;01:55.000;01:55.000;00:00.000;00.000;;;\n" "1;23;02:00.000;02:00.000;00:00.000;00.000;;;\n" "1;24;02:05.000;02:05.000;00:00.000;00.000;;;\n" "1;25;02:10.000;02:10.000;00:00.000;00.000;;;\n" "1;26;02:15.000;02:15.000;00:00.000;00.000;;;\n" "1;27;02:20.000;02:20.000;00:00.000;00.000;;;\n" "1;28;02:25.000;02:25.000;00:00.000;00.000;;;\n" "1;29;02:30.000;02:30.000;00:00.000;00.000;;;\n" "1;30;02:35.000;02:35.000;00:00.000;00.000;;;\n" "1;31;02:40.000;02:40.000;00:00.000;00.000;;;\n" "1;32;02:45.000;02:45.000;00:00.000;00.000;;;\n"; Serial.println("test data: "); for(int i = 0; i < sizeof(S); i++) { if(S[i]) { Serial.print(S[i]); } } Serial.println(); struct kv parsed[192]; // 192 место для ввода для 32 каналов по 6 параметров int nparsed = 0; for (char *p = strtok(S, ";"); p; p = strtok(NULL, ";\n")) { parsed[nparsed].value = p; nparsed++; } Serial.print("Pole "); Serial.println(nparsed); Serial.println("value"); for (int i = 0; i < nparsed; i++) { Serial.print(parsed[i].value); Serial.println(); } Serial.println(); Serial.println("test2 "); Serial.print("Slat: "); Serial.println(parsed[186].value); Serial.print("Cue: "); Serial.println(parsed[187].value); Serial.print("None: "); Serial.println(parsed[188].value); Serial.print("Time: "); Serial.println(parsed[189].value); Serial.print("None: "); Serial.println(parsed[190].value); Serial.print("None: "); Serial.println(parsed[191].value); } //---------------------------------------------------------------------------------------- void loop() { } //----------------------------------------------------------------------------------------а вот с картой пока неполучается
По самому первому скетчу: В строках №№ 50-56 что написано? Для чего это?
По второму скетчу: там вообще что-то непонятное. Что Вы читаете в строке 51? Первую строчку файла? зачем?
Я Вам уже об этом говорил, не мешайте всё вместе. Отлаживайте по частям. Не умеете читать с карты - выбросьте из программы всё, кроме чтения с карты и добейтесь чтобы это работало. Вы же опять всвалил всё в кучу.
По самому первому скетчу: В строках №№ 50-56 что написано? Для чего это?
Это для теста выводит в порт содержание строки без изменений
for(int i = 0; i < sizeof(S); i++) { if(S[i]) { Serial.print(S[i]); } }По поводу второго скетча это которого?
Это для теста выводит в порт содержание строки без изменений
for(int i = 0; i < sizeof(S); i++) { if(S[i]) { Serial.print(S[i]); } }Фига-се! А чем не угодил вариант:
"Не наш метод"?
По поводу второго скетча это которого?
Ну, там был скетч с картой, Вы сейчас его зачем-то удалили.
ну по поводу не нашего метода то да он не наш обрезок от чужого кода
а по поводу скетча с картой то вот он тут читает и парсит нормально
//---------------------------------------------------------------------------------------- #include <SD.h> #include <SPI.h> #include <string.h> //---------------------------------------------------------------------------------------- struct kv { char *value; char *Slat; char *Cue; char *Time; }; //---------------------------------------------------------------------------------------- const int chipSelect = 53; // Номер пина для CD карты для MEGA CS File dataFile; String buffer;//тут хранится прочитанный из карты текст boolean SDfound; //---------------------------------------------------------------------------------------- void setup() { Serial.begin(9600); // Инициализируем UART. while (!Serial); char S[] = " "; struct kv parsed[192]; // 192 место для ввода для 32 каналов по 6 параметров int nparsed = 0; Serial.println("Initializing SD card..."); // Инициализация SD-карты... pinMode(chipSelect, OUTPUT);// Настроим выход выбора микросхемы на вывод. if (SDfound == 0) { if (!SD.begin(chipSelect)) { Serial.print("The SD card cannot be found"); while(1); } } SDfound = 1; dataFile = SD.open("TEST.zpl");//Откроем файл Serial.println("SD card ok."); if (!dataFile) { Serial.print("text fail eror"); // Текстовый файл не открывается while(1); } Serial.println("Test-1"); while (dataFile.available()) //Читаем содержимое файла { buffer = dataFile.readStringUntil('\n');//Считываем с карты весь текст в строку до символа окончания. Serial.println(buffer); // для отладки отправляем по UART все что прочитали с карты. char charBuf[buffer.length()+1]; buffer.toCharArray(charBuf, buffer.length()); char *pch; pch = strtok (charBuf,";"); while (pch != NULL) { parsed[nparsed].value = pch; nparsed++; Serial.println (pch); pch = strtok (NULL, ";"); } } dataFile.close(); //закроем файл } //---------------------------------------------------------------------------------------- void loop() { } //----------------------------------------------------------------------------------------проблемы возникают при попытке добавить сохранение в массив
//---------------------------------------------------------------------------------------- #include <SD.h> #include <SPI.h> #include <string.h> //---------------------------------------------------------------------------------------- struct kv { char *value; char *Slat; char *Cue; char *Time; }; //---------------------------------------------------------------------------------------- const int chipSelect = 53; // Номер пина для CD карты для MEGA CS File dataFile; String buffer;//тут хранится прочитанный из карты текст boolean SDfound; //---------------------------------------------------------------------------------------- void setup() { Serial.begin(9600); // Инициализируем UART. while (!Serial); char S[] = " "; struct kv parsed[192]; // 192 место для ввода для 32 каналов по 6 параметров int nparsed = 0; Serial.println("Initializing SD card..."); // Инициализация SD-карты... pinMode(chipSelect, OUTPUT);// Настроим выход выбора микросхемы на вывод. if (SDfound == 0) { if (!SD.begin(chipSelect)) { Serial.print("The SD card cannot be found"); while(1); } } SDfound = 1; dataFile = SD.open("TEST.zpl");//Откроем файл Serial.println("SD card ok."); if (!dataFile) { Serial.print("text fail eror"); // Текстовый файл не открывается while(1); } Serial.println("Test-1"); while (dataFile.available()) //Читаем содержимое файла { buffer = dataFile.readStringUntil('\n');//Считываем с карты весь дотекст в строку до символа окончания. char charBuf[buffer.length() + 1]; buffer.toCharArray(charBuf, buffer.length()); for (char *p = strtok(charBuf, ";"); p; p = strtok(NULL, ";\n")) { parsed[nparsed].value = p; nparsed++; } Serial.print("Pole "); Serial.println(nparsed); Serial.println("value"); for (int i = 0; i < nparsed; i++) { Serial.print(parsed[i].value); Serial.println(); } } dataFile.close(); //закроем файл Serial.println(); Serial.println("test2 "); Serial.print("Slat: "); Serial.println(parsed[186].value); Serial.print("Cue: "); Serial.println(parsed[187].value); Serial.print("None: "); Serial.println(parsed[188].value); Serial.print("Time: "); Serial.println(parsed[189].value); Serial.print("None: "); Serial.println(parsed[190].value); Serial.print("None: "); Serial.println(parsed[191].value); } //---------------------------------------------------------------------------------------- void loop() { } //----------------------------------------------------------------------------------------если вы имели в виду для чего это
buffer = dataFile.readStringUntil('\n');//Считываем с карты весь дотекст в строку до символа окончания. Serial.println(buffer); // для отладки отправляем по UART все что прочитали с карты. char charBuf[buffer.length()+1]; buffer.toCharArray(charBuf, buffer.length());то это читаем файл в строку и преобразовуем строку в массив char ну по крайней мере я думаю что это делаю но могут быть глупые ошибки
Вы не поняли.
У Вас так много скетчей, давайте так: сейчас мы говорим про тот, что идёст сразу после фразы "читает и парсит нормально".
Ни фига не нормально.
В строке №52 Вы не читаете весь файл как думаете, а читаете только первую строку (до '\n').
Затем Вы эту одну строку парсите и печатаете. Но при парсинге Вы не сохраняете значение, которое распарсили, а только запоминаете указатель на него.
Однако, уже при следующем проходе цикла в Вас это указатель устаревает, т.к. Вы заново размещаете массив charbuf.
В результате у Вас в памяти мешанина.
Для того, чтобы убедиться, что там чушь, просто вставьте в строку 68 печато Вашего массива parsed и посмотрите какая в нём красота сидит.
Согласен косяк, но как это исправить?
Ну, не знаю. Там миллион способов. Тем более, что не понимаю задачи.
Начать можно с того, что массив charBuf, не нужен, т.к. он тупо дублирует текст в строке buffer, жрёт память не привнося ничего нового.
Можно полученные значения просто копировать в структу prased, только описать их надо правильно (как массивы, а не как указатели).
Ну, и самое главное. Сейчас Вы дважды держите в памяти весь прочитанный файл (вернее, пытаетесь). Оно Вам точно надо? Точно нужно именно весь файл одновременно иметь в памяти? Или достаточно "прочита строку, обработал, выбросил, прочитал следующую".
Откуда мне всё это знать?
Задача такая прочитали файл из карты памяти разобрали его на переменные и сохранили их в массив для дальнейшей обработки
так как обработка будет тоже объёмная то прямо налету скорее всего неполучится и потому данные прийдется хранить в массиве разве что переввести их сразу в числовой вид.
По сути устройсво будет считывать переменные с карты и отдавать их некоторому количесву таймеров.
типа многоканального реле времени которое берет настройки с карты.
вот чтото такое наверно нужно сделать как пример
int h=0; // считываем массив входящего конфигурвционного файла char buffer[5]; //так как в кажде данное не больше 4 цифр int num,i=0; configFile = SD.open("config.txt"); if (configFile) { Serial.println("configFile.txt open OK"); char array[ConfigFile.size()]; // массив выходящих значений конфигурационного файла while (configFile.available()) { // считываем байт входящего файла symbol = configFile.read(); array[h]=symbol; h++; } array[h]='\0'; configFile.close(); do { buffer=strtok(array,","); num =atoi(buffer); outputArray[i]=num; //тут особо не обращайте внимание,остюда уже идут операции размещения считанных данных куда вам надо по массивам i++; } while(buffer!=NULL);alexval2007 - думаю, вам надо внимательно изучить. что такое переменные, а что - указатели. А так же разобрать, как устроены символы и строки в Си. Без этого у вас ничего не выйдет. И не надейтесь решить эту проблему в пару дней.
А то, чем вы занимаетесь сейчас - берете советы с одного форума и тащите на другой, там выдавая за свое творчество, а потом ответы со второго форума на первый - это читерство.
я просто ищу варианты решения не выдавая за свое просто одно подсмотрел там другое здесь