Jump to content

How to store & read multiline text parts into ini file?


LCF-AT

Recommended Posts

Hi guys,

I see some problem when using the normal GetPrivateProfileString & WritePrivateProfileString function to store lines into a file and read them.All works for normal lines without CRLF but the GetPrivateProfileString function dosen't read the stored multiline/s which was saved with WritePrivateProfileString function. :( Why do they differ?Write works & Read not?In this case I can not use GetPrivateProfileString function to read some entry from file.

I'am using a edit control with multilines & wantreturn style and wanna save / read whole text parts to file.How could I do that in best case?Just asking before whether they are any functions I could use already before I try to create some custom stuff etc you know.Thanks.

greetz

Link to comment

I have some another small question.How can I show multi lines in a Listview control?Like this..

1 | test1 | Got removed the block
          | No access anymore
          | Done
2 | test2 | Rules
3 | test3 | None

...first entry / subitem 2 I wanna set a text part which has multilines.So I found no listview flag I could set for that.How to do that?

greetz

Link to comment

method 1:

use GetPrivateProfileSection API.  you can get multiple lines of text , “\0” is the end of each line

[test]
str1= 123
123
123
str2= 456
str3=789

code:

	TCHAR strBuff[128] = { 0 };

	int returnLen = GetPrivateProfileSection(
		_T("test"),
		strBuff, sizeof(strBuff) / sizeof(TCHAR),
		_T("test.ini"));

method 2:

use the following configuration, and split

[test2]
str1=123|123|123

 

  • Like 1
Link to comment

INI files have no true specification defined. So it is up to the implementation to handle special edge-cases like multi-lines, comment types, if inline-comments are supported on values, etc. Windows' API is deprecated in favor of using the registry, so their implementation is fairly limited. You're better off using a third-party library instead or writing your own parser for the file type. (It's fairly basic and straight forward, so it's pretty easy to write one.)

There are a handful of example projects on GitHub you can look at for reference to roll your own.

  • Like 2
Link to comment

Can use your own escape chars, or \n \r, which should also work for ES_MULTILINE style edit and richedit controls

 

https://www.codeproject.com/Questions/442723/Inserting-text-with-new-lines-in-Win32-Edit-Contro

https://stackoverflow.com/questions/1761051/difference-between-n-and-r/1761086

https://stackoverflow.com/questions/1940766/win32-multiline-edit-control-loses-carriage-returns-on-setwindowtext

https://stackoverflow.com/questions/23545216/win32-edit-box-displaying-in-new-lines

 

You might need to do some validation before saving multiline text to ini, by replacing newline and carriage return character sequences with \n\r

Edited by fearless
add validation note
  • Like 1
Link to comment

Hi,

when I do use GetPrivateProfileSection then I get same results back in buffer...

00403108  73 74 72 31 3D 31 32 33 00 31 32 33 00 31 32 33  str1=123.123.123
00403118  00 73 74 72 32 3D 34 35 36 00 73 74 72 33 3D 37  .str2=456.str3=7
00403128  38 39 00 00 00 00 00 00 00 00 00 00 00 00 00 00  89..............

....you see the 00 bytes after each return in text.I also don't wanna use "|" as marker when I do use it later for commandlines who using this "|" as pipe command.

What third-party functions I could use?

The main problem is where what does start & end when using multilines to save & read them.I could all entry seperated into single files but I don't like that and would store just all into one file.Not sure how to make that possible so far.In my listview I wanna store 3 infos for a single line.Name, comments, text.The first 2 ones are shorts only but the last one can be very large.At the moment I can also not show multiline text in a LV and just can show a short line till the return happens.Only can put the entire text into extra buffer and put them into lparam.

greetz

Link to comment

ok ! I think you need the following implementation, but the length of INI file is limited to 0xFFFF. If it can't meet your needs, you should choose JSON or SQLite

	typedef struct _StoreInfo
	{
		TCHAR	info1[128];
		TCHAR	info2[128];
		TCHAR	info3[128];
	}STOREINFO, *PSTOREINFO;
	static_assert(sizeof(STOREINFO) < 0x7fff, "!ERROR,The maximum profile section size is 32,767 characters.");

	TCHAR		strBuff[128] = { 0 };
	BOOL		retVal = FALSE;
	PSTOREINFO	pWriteSInfo = (PSTOREINFO)calloc(1, sizeof(STOREINFO));

	wcscpy_s(pWriteSInfo->info1, _T("123123123123"));
	wcscpy_s(pWriteSInfo->info2, _T("456456456456"));
	wcscpy_s(pWriteSInfo->info3, _T("body\r\n123123123\r\n456456456"));

	retVal = WritePrivateProfileStruct(
		_T("TestSec"),
		_T("TestVal"),
		pWriteSInfo, sizeof(STOREINFO),
		_T("test.ini")
	);

	free(pWriteSInfo);

	_tprintf(_T("Save -> retVal:%d\n"), retVal);
	if (retVal)
	{
		PSTOREINFO	pReadSInfo = (PSTOREINFO)malloc(sizeof(STOREINFO));

		retVal = GetPrivateProfileStruct(
			_T("TestSec"),
			_T("TestVal"),
			pReadSInfo, sizeof(STOREINFO),
			_T("test.ini")
		);

		_tprintf(_T("Read -> retVal:%d\n"), retVal);
		_tprintf(_T("%s\n%s\n%s\n"),
			pReadSInfo->info1,
			pReadSInfo->info2,
			pReadSInfo->info3);

		free(pReadSInfo);
	}

	return 0;

 

  • Like 2
Link to comment
7 hours ago, LCF-AT said:

....you see the 00 bytes after each return in text.I also don't wanna use "|" as marker when I do use it later for commandlines who using this "|" as pipe command.

The Windows API will stop when a null char is hit. So you'd need to use a non-null char if you plan to replace newlines with another character.

7 hours ago, LCF-AT said:

What third-party functions I could use?

That would be up to you to decide which other library suites your needs. There's a lot of ini parsers available online. However, since you usually write stuff in ASM, you'd need to compile those options into a usable lib for your setup. The effort for that will vary depending on the lib you land up choosing.

7 hours ago, LCF-AT said:

The main problem is where what does start & end when using multilines to save & read them.I could all entry seperated into single files but I don't like that and would store just all into one file.Not sure how to make that possible so far.In my listview I wanna store 3 infos for a single line.Name, comments, text.The first 2 ones are shorts only but the last one can be very large.At the moment I can also not show multiline text in a LV and just can show a short line till the return happens.Only can put the entire text into extra buffer and put them into lparam.

Since there is no real specification for the file type, nothing really defines that behavior and instead it's just been mainly left to being per-line split on '=' characters for the key/value pairs. For libraries that support multiple lines, they usually do look-aheads where they'll look at the next line, check for = chars, and if none is found, its considered to be part of the previous field.

Windows' API has the intention of being used per-field as needed. Most other newer libraries that offer newer ini features (like multiline) will do a single-pass parse of the file and hold the data it found in memory for use to lower the overhead/cost of having to try and parse the file every time you want to look up or set a value. 

For example: https://github.com/benhoyt/inih

In their setup, they look for next-lines having leading whitespace to account for multiple lines if you enable the feature:

https://github.com/benhoyt/inih/blob/master/ini.c#L172

  • Like 1
Link to comment

Hi guys,

so I think I have to handle it by myself using some custom marker like this...

/*=\Here Some Text I want
and here too
and also here.../*=\

or

/*=\Name/*=\/*=\111111111111
222222222
333
444
5555555
6666/*=\

...and set them before & end of entire text.Maybe not very nice or handy but works.

LV1_2021-12-06_213733.png.d0ebd2b892d6065c28f8aed0024e0b25.png

Below a edit previewbox of the whole string of selected entry.I still don't know how make a listview  cell showing the string like in the edit box below.

greetz

Link to comment

Hi again,

one more question I have about using mulitline CLI commands and using them with CreateProcess function.I see somehow its not working yet to use CreateProcess function with such commandlines.

Example: The command below I did copy from Chrome devtools cURL cmd.

curl "https://www.youtube.com/getDatasyncIdsEndpoint" ^
  -H "accept: */*" ^
  -H "sec-gpc: 1" ^
  -H "sec-fetch-site: same-origin" ^
  -H "sec-fetch-mode: same-origin" ^
  -H "sec-fetch-dest: empty" ^
  -H "referer: https://www.youtube.com/" ^
  -H "accept-language: en-US,en;q=0.9" ^
  --compressed

This command I can also paste directly into cmd window and it works.Now I wanna do same using CreateProcess function.How to send it then?I tought so...

cmd.exe /k curl "https://www.youtube.com/getDatasyncIdsEndpoint" ^
  -H "accept: */*" ^
  -H "sec-gpc: 1" ^
  -H "sec-fetch-site: same-origin" ^
  -H "sec-fetch-mode: same-origin" ^
  -H "sec-fetch-dest: empty" ^
  -H "referer: https://www.youtube.com/" ^
  -H "accept-language: en-US,en;q=0.9" ^
  --compressed

...but not working only for first line = url.Is is possible to use this format too with CreateProcess function or do I have to format it new and remove all CR/LFs & ^ signs?

greetz

Link to comment
Quote

Below a edit previewbox of the whole string of selected entry.I still don't know how make a listview  cell showing the string like in the edit box below.

Refer to this link:
https://www.codeproject.com/Questions/60736/Multiline-text-in-CListCtrl-with-Report-Style 

 

Quote

but not working only for first line = url.Is is possible to use this format too with CreateProcess function or do I have to format it new and remove all CR/LFs & ^ signs?

It won't work. Use "curl" https://www.youtube.com/getDatasyncIdsEndpoint "" can get the same result

  • Like 1
Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...