<bgdev />free

Вход Регистрация

Някой да знае добър алгоритъм за четене на ред от текстов файл, но без използване на допълнителен буфер?
0

0 1
#16754 (ツ) johnfound
Създадено на 24.10.2020, видяно: 899 пъти.

Идеята е – имаме манипулатор на отворен файл. Функцията чете от текущото място във файла, до края на реда и връща прочетения ред. Файла остава позициониран на началото на следващия ред.

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

Аз това и правя в момента, но по неизвестни причини това връщане назад в някои случаи е много по-бавно от четенето напред. Тоест, когато файла е голям, четенето на целият файл става много бавно.

Библиотечни варианти на "readln" не е алтернатива - желателно да се използват само функции от ниско ниво. (независимо от операционната система). Тях ги знам как работят – с допълнителен буфер, в който държат каквото са прочели, а файла не го местят назад. Но буфера трябва да се предава при всяко следващо викане.

Някаква идея как всичко това може да се забърза?

#16757 (ツ) |
Създадено на 24.10.2020, видяно: 891 пъти.
johnfound

Идеята е – имаме манипулатор на отворен файл. Функцията чете от текущото място във файла, до края на реда и връща прочетения ред. Файла остава позициониран на началото на следващия ред.

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

Аз това и правя в момента, но по неизвестни причини това връщане назад в някои случаи е много по-бавно от четенето напред. Тоест, когато файла е голям, четенето на целият файл става много бавно.

Библиотечни варианти на "readln" не е алтернатива - желателно да се използват само функции от ниско ниво. (независимо от операционната система). Тях ги знам как работят – с допълнителен буфер, в който държат каквото са прочели, а файла не го местят назад. Но буфера трябва да се предава при всяко следващо викане.

Някаква идея как всичко това може да се забърза?

Какво е това "връщане назад"? lseek? Каква е скоростта ако използваш pread, например?

#16758 (ツ) slow_user
Създадено на 24.10.2020, видяно: 887 пъти.

Можеш да мапнеш файла в паметта, и да четеш докато стигнеш до \n символ - стринга ще ти е началото на указателя, до броя символи които си прочел, после местиш указателя след \n символа и повтаряш горната операция. Но вероятно определянето на code-page ако са ANSI файловете ще е мъка.

#16759 (ツ) |
Създадено на 24.10.2020, видяно: 879 пъти.
slow_user

Можеш да мапнеш файла в паметта, и да четеш докато стигнеш до \n символ - стринга ще ти е началото на указателя, до броя символи които си прочел, после местиш указателя след \n символа и повтаряш горната операция. Но вероятно определянето на code-page ако са ANSI файловете ще е мъка.

Това при всички случаи влиза в дефиницията "използване на допълнителен буфер".

#16762 (ツ) johnfound
Създадено на 24.10.2020, видяно: 873 пъти.
|

Какво е това "връщане назад"? lseek? Каква е скоростта ако използваш pread, например?

Примерно да, lseek със SEEK_CUR и отрицателен офсет.

Скоростта е в пъти по-бавна, отколкото ако банално чета целият файл при същият размер на буфера.

#16763 (ツ) |
Създадено на 24.10.2020, видяно: 871 пъти.
johnfound
|

Какво е това "връщане назад"? lseek? Каква е скоростта ако използваш pread, например?

Примерно да, lseek със SEEK_CUR и отрицателен офсет.

Скоростта е в пъти по-бавна, отколкото ако банално чета целият файл при същият размер на буфера.

Пробва ли с pread?

#16764 (ツ) slow_user
Последно редактирано на 24.10.2020 от johnfound, видяно: 867 пъти.
|
slow_user

Можеш да мапнеш файла в паметта, и да четеш докато стигнеш до \n символ - стринга ще ти е началото на указателя, до броя символи които си прочел, после местиш указателя след \n символа и повтаряш горната операция. Но вероятно определянето на code-page ако са ANSI файловете ще е мъка.

Това при всички случаи влиза в дефиницията "използване на допълнителен буфер".

Не и самото четене, ако трябва да правиш някакви конвертирания може. Но примерно ако файла е UTF-16 LE четенето е без буфер.

        HANDLE hMapFile;     
        HANDLE hFile;        
	
	hFile = CreateFile(L"d:\\test.txt",
		GENERIC_READ | GENERIC_WRITE,
		0,
		NULL,
		OPEN_EXISTING,
		FILE_ATTRIBUTE_NORMAL,
		NULL);

	if (hFile == INVALID_HANDLE_VALUE)
	{
	
		return 0;
	}

	// Get the system allocation granularity.
	SYSTEM_INFO siInfo;
	GetSystemInfo(&siInfo);
	auto nGranularity = siInfo.dwAllocationGranularity;

	LARGE_INTEGER dwFileSize;
	if (!GetFileSizeEx(hFile, &dwFileSize))
	{
		CloseHandle(hFile);
		return 0;
	}
	hMapFile = CreateFileMapping(hFile,    
		NULL,           
		PAGE_READWRITE, 
		dwFileSize.HighPart,  
		dwFileSize.LowPart,  
		NULL);        

	if (hMapFile == NULL)
	{
		return 0;
	}

	// Map the view and test the results.

	wchar_t* lpMapAddress = (wchar_t*)MapViewOfFile(hMapFile, 
		FILE_MAP_ALL_ACCESS,
		0,          
		0,     
		dwFileSize.LowPart);     
	if (lpMapAddress == NULL)
	{
		return 0;
	}
	std::vector<std::wstring> oaItems;
	wchar_t* lpEndLinePtr = lpMapAddress;
	wchar_t* lpEndPtr = &lpMapAddress[dwFileSize.LowPart];
	while(lpEndLinePtr!=lpEndPtr)
	{
		if (*lpEndLinePtr++ == L'\n')
		{
			oaItems.push_back(std::wstring(lpMapAddress, lpEndLinePtr - lpMapAddress));
			lpMapAddress = lpEndLinePtr;
		}
	} 
	oaItems.push_back(std::wstring(lpMapAddress, lpEndLinePtr - lpMapAddress));
	UnmapViewOfFile(lpMapAddress);
	CloseHandle(hMapFile); 
	CloseHandle(hFile);   ` 

Абе, как да форматирам първия ред на кода, като го преместя на долния ред форматиран и тага за код не излиза

#16765 (ツ) |
Създадено на 24.10.2020, видяно: 864 пъти.
slow_user
|
slow_user

Можеш да мапнеш файла в паметта, и да четеш докато стигнеш до \n символ - стринга ще ти е началото на указателя, до броя символи които си прочел, после местиш указателя след \n символа и повтаряш горната операция. Но вероятно определянето на code-page ако са ANSI файловете ще е мъка.

Това при всички случаи влиза в дефиницията "използване на допълнителен буфер".

Това map-ване на файла не заема ли памет?

#16766 (ツ) johnfound
Последно редактирано на 24.10.2020 от johnfound, видяно: 857 пъти.
slow_user

Абе, как да форматирам първия ред на кода, като го преместя на долния ред форматиран и тага за код не излиза

Използвай правилните тагове за форматиране (пишат се от първата колона на текста):

 ;begin cpp
   // your code here.
 ;end

С мапване в паметта не искам и вероятно ще стане още по-бавно – защото трябва да мапвам и размапвам на всяко викане на функцията.

#16772 (ツ) |
Създадено на 24.10.2020, видяно: 842 пъти.

Според мен проблема е, че буфера ти е много по-голям от средната дължина на реда и изхвърляш повечето от прочетеното. Но трябва да ериш да провериш дали съм прав.

#16773 (ツ) johnfound
Създадено на 24.10.2020, видяно: 838 пъти.
|

Според мен проблема е, че буфера ти е много по-голям от средната дължина на реда и изхвърляш повечето от прочетеното. Но трябва да ериш да провериш дали съм прав.

Хм, това е възможно. И тогава излиза, че бавенето е заради повторното четене (и евентуално лошо буфериране при някои от операционните системи)...

Но тъй като не може да се знае предварително каква ще е дължината на стринга, излиза, че винаги ще е зле - буфера ще е или прекалено малък, или прекалено голям... :-(

#16775 (ツ) |
Създадено на 24.10.2020, видяно: 833 пъти.
johnfound
|

Според мен проблема е, че буфера ти е много по-голям от средната дължина на реда и изхвърляш повечето от прочетеното. Но трябва да ериш да провериш дали съм прав.

Хм, това е възможно. И тогава излиза, че бавенето е заради повторното четене (и евентуално лошо буфериране при някои от операционните системи)...

Но тъй като не може да се знае предварително каква ще е дължината на стринга, излиза, че винаги ще е зле - буфера ще е или прекалено малък, или прекалено голям... :-(

Ами има две решения. По-лесното е спекулативно да четеш по-малко (например 40 байта) и аконямаш късмет да дочиташ.

Другия вариант е да смениш api-a и да дадешсобственността на буфера на функцията, която чете реда, а тя да връща указател към началото му. Така няма да ср налга четене на същите данни, може ни само memcpy.

#16822 (ツ) bvbfan
Създадено на 25.10.2020, видяно: 814 пъти.
|

Това map-ване на файла не заема ли памет?

Не, това е mmap.

#16844 (ツ) |
Създадено на 25.10.2020, видяно: 795 пъти.
bvbfan
|

Това map-ване на файла не заема ли памет?

Не, това е mmap.

mmp не заема ли памет? :)

#16845 (ツ) bvbfan
Създадено на 25.10.2020, видяно: 791 пъти.

Виртуална, не реална.

#16846 (ツ) |
Създадено на 25.10.2020, видяно: 789 пъти.
bvbfan

Виртуална, не реална.

Ох, пак започват идиотщините... Като започнеш да четеш mmap-нат файл, каква памет заема той?

#16850 (ツ) bvbfan
Създадено на 25.10.2020, видяно: 778 пъти.

Файлът се мапва в паметта като виртуална такава, като swap. Нищо не се чете.

#16851 (ツ) |
Създадено на 25.10.2020, видяно: 776 пъти.
bvbfan

Файлът се мапва в паметта като виртуална такава, като swap. Нищо не се чете.

И как знаеш какви са данните от файла? Някаква магия? :)

Като се опиташ да прочетеш първия байт от мапнатия файл какво се случва? :)

#16852 (ツ) bvbfan
Създадено на 25.10.2020, видяно: 770 пъти.

Ти нямаш нищо общо с програмиране.

#16853 (ツ) |
Създадено на 25.10.2020, видяно: 768 пъти.
bvbfan

Ти нямаш нищо общо с програмиране.

Виж сега, смешник, разбирам че нямаш никаква идея как работи mmap. Но аз съм писал няколко файлови системи за Линукс и поназнайвам това, онова. Освен това, макар че не съм експерт по memory management-a на Линукс, се оправям сравнително добре в кода (това дето е в linux/mm).

Ta, избягвай бълнуванията с какво имам общо и с какво не. :)

Та, да се върнем на въпроса, mmap-нал си файла, получил си адрес. Четеш първия байт от този адрес. Какво се случва? :)

0 1

Някой да знае добър алгоритъм за четене на ред от текстов файл, но без използване на допълнителен буфер?
0

AsmBB v2.9 (check-in: 36c85c790bbb4625); SQLite v3.31.1 (check-in: 3bfa9cc97da10598);
©2016..2020 John Found; Licensed under EUPL. Powered by Assembly language Created with Fresh IDE