LINUX.ORG.RU

Индексный файл для текстовой БД


0

1

Есть База в текстовом варианте, например

NAME=name1
CNT=5
PRICE=6000
NAME=name2
.................... и т.д. и есть индексный файл
name1
1
name2
4
число означает номер строки. как мне из текстового файла зная номер строки (напр 100500) сделать как бы seek. Я функции не нашел для перемещения по строчно, и есть ли такая функция вообще? или придется каждую строку делать фиксированного размера?Но от этого размер файла увеличится...

★★★

Последнее исправление: pozitiffcat (всего исправлений: 1)

Так как не сказана какая СУБД, то давайте я наугад скажу что-нибудь.
Например sed, или, что уж там мелочиться - awk

zolden ★★★★★
()
Ответ на: комментарий от pozitiffcat

правльно составленный регексп может помошь скокнуть на нужную строку, и выбрать нужные данные

visual ★★★
()

а пишите в индекс не номер строки а позицию в файле. Тогда будет не как бы seek а просто seek

AIv ★★★★★
()

только последовательное чтение и подсчет \n

П.С. хреновый индексный файл

aho
()
Ответ на: комментарий от AIv

форпируется файл на паскале в UTF-8 с русскими и англ символами, командой WriteLn. Как мне узнать текущий байт, чтоб потом записать в индексный файл

pozitiffcat ★★★
() автор топика
Ответ на: комментарий от pozitiffcat

Больше 10 лет не писал на С под линупс, неужели всякие system() выпилили?
Это костыль, но при любви к извращеухищрениям, ничего не мешает вам либо вызвать скрипт из программы, либо целиком его запихать в программу

zolden ★★★★★
()
Ответ на: комментарий от zolden

а я придумал, я на c++ запущу костыль который проиндексирует мне мои строки и запишет номер байта в индексный файл

pozitiffcat ★★★
() автор топика
Ответ на: комментарий от pozitiffcat

Может кому пригодится, как я реализовал

vector<int> lines;

void split(const string& str, vector<string>& tokens, const string& delimiters = ".")
{
    string::size_type lastPos = str.find_first_not_of(delimiters, 0);
    string::size_type pos = str.find_first_of(delimiters, lastPos);
    while (string::npos != pos || string::npos != lastPos)
    {
        tokens.push_back(str.substr(lastPos, pos - lastPos));
        lastPos = str.find_first_not_of(delimiters, pos);
        pos = str.find_first_of(delimiters, lastPos);
    }
}

string itoa(int i)
{
	char* str = (char*)malloc(8);
	sprintf(str,"%i",i);
	return str;
}

string format2(string one, string two)
{
	string ret = one;
	ret+=";";
	ret+=two;
	ret+="\n";
	return ret;
}

void indexation()
{
	cout << "Indexation" << endl;
	FILE* fil = fopen("C:/revitovars.txt","r");
	FILE* fil2 = fopen("C:/revitovars.indx","w");

	fpos_t pos=0;
	int line=0;
	char buf[500];
	while(!feof(fil))
	{
		fgetpos(fil,&pos);
		fgets(buf,500,fil);
		fputs(format2(itoa(line),itoa(pos)).c_str(),fil2);
		line++;
	}

	fclose(fil2);
	fclose(fil);
}

string readline(int line)
{
	char buf[500];
	FILE* fil = fopen("C:/revitovars.txt","r");
	fseek(fil,lines[line],SEEK_SET);
	fgets(buf,500,fil);
	string str = buf;
	fclose(fil);
	return str;
}

void loadindex()
{
	char buf[500];
	FILE* fil = fopen("C:/revitovars.indx","r");
	while(!feof(fil))
	{
		fgets(buf,500,fil);
		vector<string> spl;
		split(buf,spl,";");
		lines.push_back(atoi(spl[1].c_str()));
	}
	fclose(fil);
}



int main()
{
	int ch;
	cout << "loading" << endl;
	loadindex();
	cout << "Ready! enter line" << endl;
	cin >> ch;
	cout << readline(ch).c_str() << endl;
	cin >> ch;

	return 0;
}

pozitiffcat ★★★
() автор топика
Ответ на: комментарий от AIv

Тогда будет не как бы seek а просто seek

не на всех платформах с java есть RandomAccessFile

например, в блэкберри нужно сначала mark на начало файла, потом skip до нужной позиции, потом read сколько надо и наконец reset в начало файла. И учитывая, что все файлы лежат внутри jar-файлов (это такие зипники), тот reset+skip выполняется жутко медленно

с другой стороны, кое-где есть нативные реализации loadString(int stringNumber)

т.е. выбор между seek'ом и loadString'ом в контексте скорости зависит от особенностей платформы

stevejobs ★★★★☆
()
Ответ на: комментарий от zolden

ничего не мешает вам либо вызвать скрипт из программы

ничего кроме головы ;) Ты представляешь, сколько стоит на каждое чтение вызывать внешний скрипт?

stevejobs ★★★★☆
()
Ответ на: комментарий от zolden

эээ, она же у него не plain, вот даже индекс имеется... Оракл ведь тоже бд в файлах хранит =) Или ты разочаровался в способности ТСа нафигачить быструю БД? =)

stevejobs ★★★★☆
()

я чет не понял почему нельзя строки зачитать в массив и обращаться к нему по индексу?

Rastafarra ★★★★
()
Ответ на: комментарий от Rastafarra

Типа предполагается что файл бааальшй? Если фалй маленький и все в память лезет так класть увсе в ассоциативный массив и не мучаться, индекс то нафига...

AIv ★★★★★
()

никак, надо не номер строки, а номер байта сохранять

Reset ★★★★★
()
Ответ на: комментарий от AIv

файл огромнейший. Поэтому нужда в индексе. На устройстве доступно 10 мб памяти. Ну вобщем я все реализовал,все работает, всем спасибо за участие

pozitiffcat ★★★
() автор топика
Ответ на: комментарий от anonymous

ТС пишет аналог

grep -bi -e '^NAME=' filename.ext | sed -r 's/([0-9]+):NAME=(.*)/\2\n\1/i'

IMHO более удобны индексные ключи в виде '№строки:смещение:имя', по одному ключу на строку. То есть то что получается при
grep -bni -e '^NAME=' filename.ext | sed 's/:NAME=/:/i'

такой файл просто обрабатывать стандартыми утилитами а-ля sort awk и так далее, к тому-же загрузка файла в память упрощается.

MKuznetsov ★★★★★
()
Ответ на: комментарий от pozitiffcat

> Ну вобщем я все реализовал,все работает, всем спасибо за участие

Ты бы хоть кратко сказал, что в конечном итоге сделал.

anonymous
()
Ответ на: комментарий от pozitiffcat

> устройстве доступно 10 мб памяти

А чем SQLite не угодил?

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.