Версия для печати
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум на Исходниках.RU > C/C++: Общие вопросы > Чтение и поиск в больших файлов на Си


Автор: ejikbeznojek 16.06.14, 11:19
ОС: любая
компилятор: Dev C++
Задача состоит в следующем:

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

1. Я формирую в 1С файл выгрузки(формат может быть разным, xml или dbf на каком смогу работать в Си), допустим в формате DBF. Файл будет отсортирован по штрих-коду. В первой строчке файла, я думаю указать количество строк.
Содержащий колонки - Штрих-код, Наименование. Файл достаточно большой, чтобы не грузить его в оперативную память (может достигать 500 тысяч строк).

2. Далее в приложении которое я хочу написать, вводится путь к файлу.
3. Последовательно начинают вводиться штрих-коды.
4. Приложение ищет по штрих-коду - Наименование. И если наименование найдено, то добавляет в массив строку с найденным товаром.

Я только начал программировать на Си, и у меня не получается разобраться с чтениями из DBF. Если кто-то подскажет, буду очень благодарен ☺.
Получается я хочу считать из 1й строчки, что у меня 500 тысяч строк в файле. Потом сравнить штрих-код 250000й строчки с введённым. Если введённый штрих-код меньше, то сравнить со 125000й строчкой и т.д.

Как считать энную строчку из файла DBF?
Или хотя бы где можно прочитать про это. Попытки поиска меня приводили либо к кускам кода на С++(а мне нужен именно С). Либо к работе с текстовым файлом.

Автор: shm 16.06.14, 11:29
Цитата ejikbeznojek @
компилятор: Dev C++

это не компилятор.
По всему остальному. Я так понял, что записи в файле отсортированы, иначе без индексного файла поиск будет ну очень долгий. Второе условие - все записи должны иметь фиксированный размер. Тогда функция fseek тебе в помощь.

Автор: ejikbeznojek 16.06.14, 11:36
Да, записи сортированы по штрих-коду
Штрих-код имеет фиксированный размер - 13 символов. Наименование - переменной длинны.

Получается строчку я выбираю смещением? И смещение идёт всегда горизонтально? (т.е. если есть 2 строчки по 10 байт, а я сместился на 15 байт от начала, то я примерно в середине 2й строчки?)

Автор: shm 16.06.14, 11:40
Цитата ejikbeznojek @
Наименование - переменной длинны

Так не получится. Вычислять вычисления смещения каждой новой строки надо считать предыдущую, а это жутко долго. Для начала конвертируй в файл с фиксированной длиной (остаток строки можно заполнить нулями, пробелами, etc...)

Добавлено
Кстати оригинальный DBF (dBase, Paradox) имеет поля фиксированного размера. А у тебя просто какой-то txt получается.

Автор: Step 16.06.14, 13:18
Зависит от требуемой производительности. Можно и в csv выгрузить (если можно, с 1С никогда не работал), читать его построчно и каким-нибудь регулярным выражением парсить. Если хочешь побыстрее то нужен индексный файл, лучше даже в виде хэш-таблицы.

Автор: Kray74 16.06.14, 15:45
Цитата ejikbeznojek @
Файл достаточно большой, чтобы не грузить его в оперативную память (может достигать 500 тысяч строк).

Если предположить среднюю длину строки равной 50 символов, то Вам понадобится:
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    500000 * 50 = 25000000 ≈ 24 Мегабайта

Не так уж и много.

Автор: korvin 16.06.14, 16:53
Цитата shm @
Кстати оригинальный DBF (dBase, Paradox) имеет поля фиксированного размера. А у тебя просто какой-то txt получается.

Насколько я помню, данные произвольно длины хранятся в отдельном MEMO-файле или как-то так, а не в самой DBF-ке. Хотя, что там намутили в 1С — хз. =)

Автор: ejikbeznojek 17.06.14, 10:52
Вроде бы какой то результат получился.
Я могу вывести все штрих-кода из файла.

<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    char str[50],mystr[50];
    int i;
     
    printf ("Opening file\n");
    mf=fopen ("myfile/boxes.DBF","r+");
     
    for(i=0;i<15;i++)
    {
    ////////////// ШК1
       if (fseek (mf,209+i*111,SEEK_SET)==0)
          printf ("Search text complete\n");
       else
          printf ("Error search\n");
     
       printf ("Reading: ");
       if (fgets (str, 14, mf)==NULL)
          printf ("Read error\n");
       else
          printf ("%s\n",str);
    ////////////// ШК 1


Но почему то не получается сравнить их с введённым мною через сканф штрих-кодом. Всегда разные, даже если я ввожу штрих-код из тех, что выводит.
<{CODE_COLLAPSE_OFF}><{CODE_WRAP_OFF}>
    scanf("%s",&str1);
    ....
    if (str==str1)

Автор: shm 17.06.14, 10:55
Цитата ejikbeznojek @
if (str==str1)

Интересно, а что ты хочешь получить, сравнивая 2 указателя?

Автор: ejikbeznojek 17.06.14, 11:13
Получается лучше сравнивать посимвольно?
(str[0]==str1[0])&&(str[1]==str1[1])....&&(str[12]=str1[12])


Так вроде заработало. Но наверное есть какой-то способ по рациональнее?)

Автор: Kray74 17.06.14, 11:35
Есть такая функция strcmp :whistle:

Автор: Qraizer 17.06.14, 11:56
M
Используем тег [code] для добавления текста программы в пост! Устное предупреждение! Читаем правила!

Автор: ejikbeznojek 17.06.14, 13:31
Всем спасибо, вроде всё заработало как надо)

Автор: Artemonchik 28.01.16, 22:00
Да, нужно было считать и сравнить строки
M
Бессмысленный некропост на форуме не приветствуется.
Предупреждение выдано.

Powered by Invision Power Board (https://www.invisionboard.com)
© Invision Power Services (https://www.invisionpower.com)