проблема с открытием файлы с sd card
- Войдите на сайт для отправки комментариев
Ср, 24/06/2015 - 23:35
всем привет
подскажите пожалуйста
#include <SD.h> File myFile; String name[2]={"test.txt","test2.txt"}; void setup() { Serial.begin(9600); while (!Serial) { ; // wait for serial port to connect. Needed for Leonardo only } pinMode(10, OUTPUT); SD.begin(10)) myFile = SD.open(name[1]); if (myFile) { Serial.println("test.txt:"); while (myFile.available()) { Serial.write(myFile.read()); } myFile.close(); } } void loop() { }
как открыть файл с помощью массива String
Компилятор пишет:
ReadWrite:5: error: cannot convert 'const char*' to 'String*' in initialization ReadWrite:5: error: cannot convert 'const char*' to 'String*' in initialization ReadWrite.ino: In function 'void setup()': ReadWrite:22: error: no matching function for call to 'SDClass::open(String*&)' D:\Program Files\Arduino\libraries\SD/SD.h:74: note: candidates are: File SDClass::open(const char*, uint8_t)
можно ли что нибудь сделать?
Имена файлов объявите, как "char*".
И не забудьте, что счёт в массиве начинается с нуля...
спасибо maksim
я сделал как вы написали
но почему то
в имени теряется последняя буква
выдает не "test.txt" а "test.tx"
спасибо
Добрый день.Написал небольшой тестовый код.Не могу понять в чем ошибка.Попытался вывести список файлов и каталогов по индексу.
Выше вывод в Serial.Моя задача найти способ выводить имя файла или каталога по индексу.В библиотеке насколько я понял нет метода openPreviusFile(), есть только openNextFile().Основная проблема в том, что в данном тесте вывод приостанавливается на определенных значениях индекса, но если вручную установить последнее значение, то вывод продолжается .Так же не понятно откуда берутся дубликаты имен.
Добавил entry.close(), в цикл, убрал задержку.Ситуация стала лучше, распечатались все файлы и каталоги корневой директории, что мне на данном этапе нужно, но все же непонятно откуда дубликаты имен?
Выше вывод в Serial.Моя задача найти способ выводить имя файла или каталога по индексу.
что такое индекс в данном случае?
Имхо, ваша проблема именно в том и состоит, что вы приплели сюда какой-то индекс... который надо убрать из кода.
Метод openNextFile() сам переходит к следующему файлу, операция seek() тут совершенна лишняя и именно она приводит к повторению имен одних и тех же файлов.
Индекс в данном случае имеется ввиду порядковый номер каталога или файла в текущей директории.
Вариант вернуться к началу и пролистать N-1 мне не подходит, так как это очень медленно .Так же не подходит держать массив строк, так как памяти не хватит при большом количестве файлов и каталогов.
Выше вывод в Serial.Моя задача найти способ выводить имя файла или каталога по индексу.
что такое индекс в данном случае?
Имхо, ваша проблема именно в том и состоит, что вы приплели сюда какой-то индекс... который надо убрать из кода.
Метод openNextFile() сам переходит к следующему файлу, операция seek() тут совершенна лишняя и именно она приводит к повторению имен одних и тех же файлов.
Что делает openNextFile(), мне понятно.В конечном итоге мне нужно иметь возможность открывать предыдущий файл.Например, я вывожу на экран текущее имя файла, по нажатию выводится следующий файл, по нажатию другой кнопки, должен открыться предыдущий файл, имя его выводится на экран.
Понимаю,чужие мысли трудно понять и обьяснить.Но все же если не понятно, то попробую довавить.Нажимаешь на кнопку, индекс файла увеличивается i++, выводится соответствущее имя файла, жмешь другую индекс уменьшается i--, выводится имя согласно индексу.Я могу реагировать на повтор имени, но боюсь, что такой подход приведет к медленному интерфейсу пользователя, в случае, если их много.Поэтому хочется разобраться с этим.Полагаю, что повторы, это ранее удаленные файлы.
Думаю, что когда я пытался копировать файл, система Windows видела, что появился файл с одинаковым именем, создавала новый файл с именем "ИМЯ+копия файла1","ИМЯ+копия файла2" и т.д., а файл с повторным именем просто пометила как удаленный.Тоесть повторы это удаленные файлы при попытке копирования .В связи с этим возникает вопрос, как различить удаленный файл от не удаленного?
Догадка оказалась верной, если первый байт записи файла в файле директории равен 0xE5 или 0x05, согласно Википедия, то файл или директория являются свободными.
Переписал код выше, повторов нет кроме системной папки System.Впринцепи работа с этим каталогом не требуется.Не совсем понимаю, что в нем, полагаю, что это таблицы FAT и они дублируются.Есть какие мысли по данному вопросу?Если кто не понял, то данный код не делает, то , что я описал выше.Он лишь проверяет работоспособность концепции открытия файла по его порядковому номеру.
Так же интересно, есть ли еще подводные камни по данному вопросу?
"тихо сам с собою..." ?
Вкратце попробуйте резюмировать, что сделали и в чем осталась проблема.
Вариант вернуться к началу и пролистать N-1 мне не подходит, так как это очень медленно .
Тогда это тупик. Файловая система набор функций для работы с ней построены так, что перебор возможен лишь в одном направлении.
Так же не подходит держать массив строк, так как памяти не хватит при большом количестве файлов и каталогов.
Ну, если Вам нужно вернуться на одну позицию, то именно эту одну позицию и нужно хранить. А если таких "возвратов на 1" может быть несколько, то приходится как-то оптимизировать - либо по скорости, либо по памяти. Размер памяти Ардуино практически не оставляет выбора: если это Uno/Nano/Mini/Micro/Leonardo, то любая попытка оптимизировать по скорости не поместится в память. Следовательно осаеются только 2 варианта:
1. Читать каждый раз с начала.
2. Самостоятельно переписывать работу с ФС, опираясь на функции чтения и записи сектора. (но "вернуться на 1" все равно получится только до начала сектора, т.е. в среднем на несколько записей. при переходе на "предыдущий сектор" его уже нужно будет искать с самого начала.)
Переписал немного код.Он распечатывает имена файлов с любого индекса в обратном направлении.Установил индекс равный 455 и все распечаталось , с конца списка до нулевого файла.Вывод происходит шустро, в отличии от способа вернуться в начало и повторить перебор до N-1.Правда в коде есть ошибка, мне удалось исключить удаленные файлы из выводимого списка, но хоть и намного меньше все таки встречаются повторы, пока не понял почему.
Вариант вернуться к началу и пролистать N-1 мне не подходит, так как это очень медленно .
Тогда это тупик. Файловая система набор функций для работы с ней построены так, что перебор возможен лишь в одном направлении.
Так же не подходит держать массив строк, так как памяти не хватит при большом количестве файлов и каталогов.
Ну, если Вам нужно вернуться на одну позицию, то именно эту одну позицию и нужно хранить. А если таких "возвратов на 1" может быть несколько, то приходится как-то оптимизировать - либо по скорости, либо по памяти. Размер памяти Ардуино практически не оставляет выбора: если это Uno/Nano/Mini/Micro/Leonardo, то любая попытка оптимизировать по скорости не поместится в память. Следовательно осаеются только 2 варианта:
1. Читать каждый раз с начала.
2. Самостоятельно переписывать работу с ФС, опираясь на функции чтения и записи сектора. (но "вернуться на 1" все равно получится только до начала сектора, т.е. в среднем на несколько записей. при переходе на "предыдущий сектор" его уже нужно будет искать с самого начала.)
Код работает, каждый раз возвращаться к началу не требуется.Осталось понять по какой причине есть повторы.
Вывод происходит шустро, в отличии от способа вернуться в начало и повторить перебор до N-1.
Такое возможно только с нефрагментированным каталогом (в частном случае - корневым).
Спасибо за комментарии.Правильно ли я понимаю, что некоторые повторения одних и тех же имен файлов при выводе в Serial, это просто фрагменты одного файла или каталога? Иначе говоря фрагментированные файлы и каталоги?Если ввести вместо "/"(корневого каталога) , "/имя папки", то такой способ работает.Почему нельзя прочитать по очереди фрагменты каталога, ведь это всего лишь набор байтов?Раз это читается в прямом направлении, то и должно читаться в обратном, к тому же я могу устанавливать указатель в любое место файла.Могут ли фрагменты файла или каталога находится в разных частях диска? Насколько я понял запись располагается последовательно друг за другом.
1. Нет, фрагментация файла находит отражение только в FAT, в каталоге она никак не проявляется. А вот файлы с длинными именами занимают несколько "ячеек" в каталоге. Ну где-то же надо хранить символы этого самого длинного имени.
2. Дисковый накопитель принципиально невозможно читать "в любом месте", его можно читать исключительно посекторно, т.е. порциями по 512 байт. Соответственно "установить указатель в произвольном месте файла" - далеко не атомарная операция, которая может сопровождаться последовательным чтением нескольких секторов, расположенных как в текущем каталоге, так и в FAT. Файл не представляет собой непрерывную последовательность секторов, а потому сначала нужно узнать, каков номер сектора, содержащего следующий фрагмент файла. А это можно узнать лишь из FAT. А в FAT есть только ссылки "вперед" и нет ссылок "назад".
3. Да, фрагменты файла могут располагаться в разных частях диска. Именно это и называется фрагментацией файлов. А каталог - частный случай файла. И при банальном создании новых файлов каталог получается фрагментированным даже без удаления файлов. (в отличие от файлов, которые могут фрагментироваться лишь в случае, если на диске ранее удалялись файлы.)
4. Еще раз - нет, запись не обязана располагаться в секторах с последовательными номерами. Хотя и может. Это обстоятельство может существенно усложнить отладку: например, во всех тестовых примерах у Вас могут быть нефрагментированные файлы и неправильный алгоритм может работать с ними корректно, а как только появятся фрагментированные файлы, алгоритм "посыпется".
Звучит печатьно.Как правильно организовать возврат к началу и перебор до N-1?Меня терзают сомнения, что я делаю, что то не так?У меня данный код работает очень медленно уже на 50-м индексе.
Вы бы настоящую задачу озвучили, не "читать файлы по индексу", а зачем вам это надо, мож кто и посоветует.
по сути это и есть реальная задача, открыть предыдущий файл, вывести его имя на экран, вывести содержимое в Serial port.
Правильно ли я понимаю, что если избегать длинных имен, то мой код будет работать?Есть идея как можно смоделировать ситуацию с файлом, записи в катологе, которого находятся в разных местах, файла каталога?Просто мне еще не попадаются такие записи файлов в файле каталогов.В конце концов меня устраивает формат имени файла 8.3, у меня экран на 13 символов.
1. Честно говоря, у меня так и не сложилось целостного впечатления о библиотеке SD. На мой взгляд, она не слишком логично построена. Ну и работать мне с ней приходилось всего пару-тройку проектов: всего необходимого в этих проектах я добился, а углубляться дальше желания не было. Поэтому дать советы типа "нужно нажать мышкой на одну кнопку, а потом на другую" я не могу. Ну и, соответственно, не могу ответить на вопрос "будет ли работать данный код?", не запустив этот код и не посмотрев результат.
2. Я бы настоятельно порекомендовал почитать о самой файловой системе. Ну хотя бы для того, чего от нее можно добиться, а чего - нет. Я разбирался с этим давно (очень задолго до появления Ардуино), так что частично мог забыть, а частично с тех пор мог измениться и сам стандарт FAT либо появиться его более новые версии.
3. Не совсем понял, какую ситуацию Вы хотите смоделировать. Если фрагментированных файлов - то записать на карту много мелких файлов, после чего некоторые из них удалить в случайном порядке, а потом дописать на карту файлы покрупнее - они и будут фрагментированные. "Мелкие и "крупные", естественно, по отношению к размеру кластера. Если фрагментированный каталог, то достаточно просто последовательно писать в него много мелких (или крупных) файлов.
4. Корневой каталог всегда нефрагментирован, но у него ограниченный размер, и изменить его, в отличие от вложенного каталога, невозможно.
Спасибо за совет.Читал, читаю.К сожалению не сразу все понятно.Буду пробовать.
Хотелось найти способ фильтровать все дефрагментированные файлы, за исключением начального сегмента, каждого файла.Полагаю, что их можно отличить.Паралельно попробовал перебрать до N-1 при помощи другой библиотеки SDFat, работает шустро.Проблема решена.
Способ фильтрации, естественно, существует: фрагментированным является файл, у которого в цепочке последовательных кластеров хоть раз встречается ситуация, что номер следующего кластера не равен номеру предыдущего плюс единица.
Другими словами, нужно анализировать таблицу FAT.