Чтение определенной строки из файла

vitus73
Offline
Зарегистрирован: 30.03.2019

Уважаемые гуру ! Есть текстовый файл на cd карте состоящий из произвольного количества строк  кириллицы в кодировке UTF-8 примерно такого вида :

На позитиве быть всегда
Чтобы сбылась твоя мечта
И в золоте всегда купаться
Как можно чаще улыбаться

Если файл состоит из одной строки, я могу прочитать ee и перекодировав функцией в CP866 вывести на VFD дисплей. А вот как прочитать определенную строку из файла и вывести на дисплей тямы не хватает.  Окончание строк можно например по символу \n определить,а как начало? Может сможет кто подсказать.

myFile = SD.open("text.txt"); // файл в кодировке UTF-8
if (myFile)
{
  byte h = 0; char text[] = {};
  while (myFile.available())
  {
    text[h] = myFile.read();
    h++;
  }

  myFile.close();

  mySerial.println(RUS(text));      //вывод перекодированного текста

}
rkit
Offline
Зарегистрирован: 23.11.2016

vitus73 пишет:

 Окончание строк можно например по символу \n определить,а как начало?

Например, по символу \n

 

vitus73
Offline
Зарегистрирован: 30.03.2019

А можно по подробней с примером как прочитать только 3 строку например пожалуйста? Не могу уловить суть прочтения любой строки по одному \n. 

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

третья строка начнется после второго \n и продолжается до следующего \n или конца файла.

b707
Offline
Зарегистрирован: 26.05.2017

vitus73 пишет:

А можно по подробней с примером как прочитать только 3 строку например пожалуйста? Не могу уловить суть прочтения любой строки по одному \n. 

По одному \n - никак, придется прочитать все . Читаете первую строку, отбрасываете. Вторую - так же. Следующая - та. что вам нужна :)

Если все строки разной длины - нет способа найти третью строку, не прочитав все предыдущие.

vitus73
Offline
Зарегистрирован: 30.03.2019

Всё верно строки разной длины,символ кириллицы занимает 2 байта,а остальные один. Всё я могу прочитать, а как откинуть ненужные строки не хватает знаний, по этому и обратился за помощью. Вот так я могу первую строку вывести. А как сделать что бы любую другую  строку вывести на дисплей по наступлению какого-нибудь события не знаю как.

 

    while (myFile.available())
    {
      text[h] = myFile.read();
      if ( text[h] == '\n') counter ++; 
      if (counter == 1 ) break;
      h++;
    }

    myFile.close();
    mySerial.println(RUS(text));      //вывод перекодированного текста

  }

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Я не знаком с этой библиотекой, но если у неё есть метод readln (), то просто прочитать и отбросить две строки, а третью использовать для перекодирования и последующего вывода. По идеи должен быть такой метод, но это не точно. 

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

В #3 что не ясно ? Считываешь символы и сравниваешь с \n. Символы \n считаешь. Как число символов \n стало равно двум - значит дальше идёт третья строка ...

vitus73
Offline
Зарегистрирован: 30.03.2019

А в # 4 написано, что нельзя. И как быть ? Я прошу пример, а не теорию. По другому я не разберусь, особенно когда мнения расходятся. 

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

#3 и #4 об одном и том же !!!

b707
Offline
Зарегистрирован: 26.05.2017

vitus73 пишет:

А в # 4 написано, что нельзя. И как быть ? Я прошу пример, а не теорию. По другому я не разберусь, особенно когда мнения расходятся. 

да не выдумывайте, в #3 и #4 написано одно и тоже.

Алгоритм очень простой, отвлекитесь от строк вообще и работайте только с символами. Читаете символ, сравниваете с \n. Если символ равен \n - увеличиваем счетчик. Когда число \n будет равно 2 - все последующие символы начинаем сохранять в массив, пока не встретится еще один \n

Что тут не понятного? - остается написать код. Этого за вас делать, думаю, никто не станет. Я уж точно :) Весь смысл обучения в том, чтобы вы научились переводить алгоритмы в код самостоятельно

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Если строки при формировании файла начинать со знака '#', например, то легко можно определить их начало.

vitus73
Offline
Зарегистрирован: 30.03.2019

Да, извиняюсь, не вник в суть! Я принцып понял как это работает. А как это в коде прописать я не знаю. 

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

мы тут как чукчи - а чукча не писатель - чукча читатель

vitus73
Offline
Зарегистрирован: 30.03.2019

Если строки начинать с какого-нибудь символа, то они и на экране отобразятся. Если их только потом откидывать, но тогда для меня это вообще тёмный лес.

b707
Offline
Зарегистрирован: 26.05.2017

sadman41 пишет:
Если строки при формировании файла начинать со знака '#', например, то легко можно определить их начало.

а смысл ?:) разве '#' в начале чем-то лучше '\n' в конце?

vitus73
Offline
Зарегистрирован: 30.03.2019

Это здорово, и я такой же читатель. Вот и застрял на одном месте несколько дней уже. Хотя там пару, тройку строк кода наверное. 

sadman41
Offline
Зарегистрирован: 19.10.2016

Зачем их откидывать, если можно просто пропустить и не складывать со строкой?

Впрочем, способ проще посоветовать наврядли можно.

b707
Offline
Зарегистрирован: 26.05.2017

vitus73 пишет:

А как это в коде прописать я не знаю. 

и что вы от нас хотите? Если вы такую элементарщину не знаете как записать - мы вам должны весь учебник программирования здесь в лицах разыграть. что ли?

sadman41
Offline
Зарегистрирован: 19.10.2016

b707 пишет:

sadman41 пишет:
Если строки при формировании файла начинать со знака '#', например, то легко можно определить их начало.

а смысл ?:) разве '#' в начале чем-то лучше '\n' в конце?


Для мозга новичка это должно быть проще, как мне кажется. Искать начало по концу - это абстракция для человека, который уже поработал со строковыми массивами.

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

давайте теперь новый формат текстового файла изобретать ...

rkit
Offline
Зарегистрирован: 23.11.2016

Вот эта строчка пропустит строку. Вызвать два раза и дальше можно работать с третьей

while(file.read() != '\n') {}

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

не все чукчи оказывается - нашелся один слабохарактерный ...

вангую ошибку при компиляции

vitus73
Offline
Зарегистрирован: 30.03.2019

b707 пишет:

vitus73 пишет:

А как это в коде прописать я не знаю. 

и что вы от нас хотите? Если вы такую элементарщину не знаете как записать - мы вам должны весь учебник программирования здесь в лицах разыграть. что ли?

Да вы извините меня,просто для кого-то это элементарщина,а для меня нет. Я от Вас не требую, просто много искал примеров на просторах нета и похожего не нашел. Вот решил спросить на форуме у знающих людей. 

sadman41
Offline
Зарегистрирован: 19.10.2016

Опять ничего в интернете нет? Что ж такое-то... Какой у вас провайдер?

vitus73
Offline
Зарегистрирован: 30.03.2019

sadman41 пишет:
Опять ничего в интернете нет? Что ж такое-то... Какой у вас провайдер?
Шутейку оценил. 

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

в #21 даже код написали (чуть поправить надо правда) и все равно не понятно ??? тогда в вашем случае медицина уже не поможет ... 

vitus73
Offline
Зарегистрирован: 30.03.2019

Komandir пишет:

в #21 даже код написали (чуть поправить надо правда) и все равно не понятно ??? тогда в вашем случае медицина уже не поможет ... 

Если быть честным , то не до конца. Но буду пробывать. А на счет медицины я уверен, есть вещи где я разбираюсь гораздо лучше Вас. Не возможно быть спецом во всем. 

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

в #1 я так понимаю то же код из интернета ?

vitus73
Offline
Зарегистрирован: 30.03.2019

Komandir пишет:

в #1 я так понимаю то же код из интернета ?

Функция перекодировки из просторов, так как перекодировать из utf8 в cp866 основная масса и понятия не имеет. Остальное брал из других скетчей и переделывал под себя. Я не думаю что все тут с нуля пишут. Смотрю чужие примеры и разбираюсь по маленьку что делает определенный кусок кода. Может это и не правильный подход, но  мне  так гораздо понятней чем в теории. 

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

что по вашему делает код из #21 ?

vitus73
Offline
Зарегистрирован: 30.03.2019

Читает файл пока не встретит символ \ n. Точнее выполняет какие то действия в цикле пока не встретит \n

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

иными словами считывает строку ... (цикл там пустой)

а если два раза подряд ?

vitus73
Offline
Зарегистрирован: 30.03.2019

Считает вторую строку

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

не два раза, а две строки (пробежит все символы из двух строк и проигнорирует их) - следующая третья, а именно она вам и нужна ...

vitus73
Offline
Зарегистрирован: 30.03.2019

Это я понял, но мне нужно вывести одну строку например в 8.00,а другую в 10.00. На каждое событие писать эту функцию разное колличество раз?

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Можно в цикле выполнять нужное количество раз.

b707
Offline
Зарегистрирован: 26.05.2017

vitus73 пишет:

Это я понял, но мне нужно вывести одну строку например в 8.00,а другую в 10.00. На каждое событие писать эту функцию разное колличество раз?


ну вот видите, как только разобрались с тем как строку получить - сразу новый вопрос как это делать для разных строк. И так будет бесконечно, по пять вопрлсов на каждую строчку - пока вы не научитесь находить ответы самостоятельно. Поэтому мы и не пишем код за новичков , потому что стоит начать - придется делать так постоянно

vitus73
Offline
Зарегистрирован: 30.03.2019

 Вопрос изначально стоял как это делать для разных строк.  Вывести одну строку я тупо мог просто записав её одну в файл.

Komandir
Komandir аватар
Offline
Зарегистрирован: 18.08.2018

Я правильно понимаю - всё ещё вопрос не решен ????????????????????????????????????????????????????????

vitus73
Offline
Зарегистрирован: 30.03.2019

Нет,не решен. 

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Надо срочно кэпа звать, без него не разобраться. 

vitus73
Offline
Зарегистрирован: 30.03.2019

Всем спасибо, вопрос решен. while(file.read() != '\n') {} не понадобился пропуск строк. Подправить всего одну строчку нужно было из #5 поста. А сколько шума было. 

p-a-h-a
Offline
Зарегистрирован: 17.01.2019

Вдруг кому пригодиться.

#include <FS.h>
#include <LittleFS.h>

void setup() {
  Serial.begin(115200);
  LittleFS.begin();
  Serial.println (readFile("/text.txt", 15)); // 15я строка файла в корне text.txt
}

void loop() {}

String readFile(const char * path, uint16_t line) {
  File file = LittleFS.open(path, "r");
  if (!file)  return F("Failed to open file for reading");

  while (file.available() && line > 1) {//Пропускаем лишние строки в количестве line-1.
    line -= file.read() == '\n';
  }; 
  
  String read_text;
  char last_simbol;
  while (file.available() && (last_simbol != '\n')) {//Читаем строку
    last_simbol = file.read();
    read_text += last_simbol;
  };
  file.close();
  return read_text;
}