mIRC Homepage

$readini issue

Posted By: CapitanMarte

$readini issue - 28/12/18 01:33 PM

Hi, mIRC no longer crashes in v7.53 due to the issue with $readini but it does not work either. It won't load any data. It always return $null
The code (my code) that handles this routine works with older version (6.16) so I know for a fact it works.
I hope it can be fixed soon. Thanks
Posted By: Wims

Re: $readini issue - 28/12/18 01:37 PM

Can you provide a simple code which reproduces the $readini issue?
Posted By: CapitanMarte

Re: $readini issue - 28/12/18 01:50 PM

I tried both methods of setting the variable. Both gave the same result.
The file I'm reading from is about 14,000 KB

on *:TEXT:*:# {
if (.def isin $1) {
;.set -u5 %fword $readini dicc\fout.ini $2 R
var %fword = $readini(dicc\fout.ini, $2, R)

if (%fword == $null) {
%fword = 4 No data found
/msg $chan $2: %fword

Posted By: Khaled

Re: $readini issue - 28/12/18 03:10 PM

Thanks for your bug report. I am not aware of any recent reports of $readini causing mIRC to crash. Can you provide a link to the bug report that you are referring to? I have tested $readini and it is returning data from ini files as expected. For example:

test {
  var %fn = test.ini

  writeini %fn a a2 a3
  writeini %fn b b2 b3
  writeini %fn c c2 c3

  var %item = $readini(%fn,a,a2)
  echo item: %item
  var %item = $readini(%fn,b,b2)
  echo item: %item
  var %item = $readini(%fn,c,c2)
  echo item: %item
Posted By: Wims

Re: $readini issue - 28/12/18 03:12 PM

Without having the data in the file it's impossible to help you.

When you test it, what is the value of $2, and can you please provide the relevant section?

For example if $2 is "word", you must have a section named "word" in the INI file, with an item called "R", which has an associated value.

And you didn't say why this isn't working, are you getting $null for the $readini when it should have a value?
Posted By: klez

Re: $readini issue - 28/12/18 11:12 PM

CapitanMarte, I'm sure you are in confuse or you don't know how to work with an ini file and how $readini reads the data from it. I'm using very often $read and $readini and I see no bugs here, even in 7.53 and older versions.

In your case, on an incoming message in a chan, if the first word is .def, then using $readini(dicc\fout.ini, $2, R), your fout.ini file must have this topic inside:


In this case, $readini(dicc\fout.ini,$2,R) will return text. Pay attention, that if $2 is $null, i.e. someone will write only .def, then $readini(dicc\fout.ini,$2,R) will return $null and if there're no section $2 or item R, also the identifier will return $null. Put the condition if ($2 != $null) to avoid the mismatch.

Also you can use $readini(dicc\fout.ini,n,$2,R) if you want the read line to not be evaluated and be treated as plain text, in case it contains identifiers.
Posted By: CapitanMarte

Re: $readini issue - 30/12/18 10:23 PM

There is no chance that I'm doing something wrong. As I stated on my original post, the code runs on a previous version of mirc.
Actually I use this code on a stand alone dictionary definitions retrieval application and on 3 or 4 online games which also retrieve words from the same dictionary file on ini format and presents them to the players in different ways.
I've been running those games for almost a year with no problems.
I needed to upgrade mirc because I wanted to run code not compatible with the version of mirc I have.
On the 7.x versions of mirc $readini does not work on any of my games and mirc crashes, even on the latest release of mirc.
Since you guys say it looks like I'm the only one person having these issues, I'll do some more experimenting on the following days and report here if something changes and if it does what was the problem I found.
Before I posted here the other day I debugged the code and at $readini mirc crashed. Every single time.

Thanks for your support and attention. I'll keep you all posted.

If you want to see the games working let me know and I'll write a post with instructions for the games (so you know what is going on when you see it working) and the address to the irc server.
Posted By: maroon

Re: $readini issue - 30/12/18 11:37 PM

are you saying it crashes at the first call to readini, or only some of them.

i see you have the line like:

var %fword = $readini(dicc\fout.ini, $2, R)

As was suggested above, you should probably use the 'n' switch like:

var %fword = $readini(dicc\fout.ini,n, $2, R)

because that prevents any $word or %word or even #$word from being evaluated.

If you can find something that can trigger this crash due to using $readini in an editbox, that would help. If it triggers only for certain things, it helps to know what's different about the crash items. i.e. whether they're deep into a big 'section', or part of the 'big number' of a large number of sections.

If having trouble finding which things trigger the problem, you might need to use $ini() to sequentially find all [sections] of the .ini and access everything via $readini sequentially. If $ini also crashes, you might need to use $read() to find and parse lines of the file to determine what are the itemnames causing the problem.
Posted By: Khaled

Re: $readini issue - 31/12/18 12:45 PM

If you are experiencing an issue with how $readini() works in the latest version of mIRC, please provide us with an example script that reproduces the issue. For example:

test {
  var %fn = test.ini
  writeini %fn section item value
  var %value = $readini(%fn,section,item)
  echo value: %value

Also note that mIRC v6.16 was released in 2004, over fourteen years ago. If you must use an older version of mIRC, you should not under any circumstances use any version of mIRC older than mIRC v6.35. mIRC v6.35 includes security updates that fix remote exploits existing in older versions of mIRC. You can download mIRC v6.35 through the download page on the mIRC website.

While new versions of mIRC are updated in a way that tries to maintain backwards compatibility, sometimes that is not possible and if a script is very old, be aware that you may need to udpate it to work with newer versions of mIRC.
Posted By: CapitanMarte

Re: $readini issue - 31/12/18 05:11 PM


This is an update to my previous post. Today I started testing on another more powerful computer which at this times only was running one copy of mIRC 7.54 and the web browser.
This computer uses a SSD for the system files including mIRC's data paths. It's a 8 core cpu on Windows 7 64 bit and 16 GB of ram.

My original copy of mIRC 7.54 is installed on a non system disk. So for the seek of fairness of my tests I also ran it from the system disk at C:\mIRC and from my ram disk at B:\mIRC

I copied dicc/fout.ini to the data path and made sure the word I was going to search for existed in the file and was in the proper format for mIRC to find.

dicc/fout.ini is 13,170 KB

I ran this test a few times and every time after a second or so mIRC showed (Not Responding) on the window's title bar and a few seconds later it crashed.

I edited and manually shortened dicc/fout.ini and got ride of half of it content data and made sure the word I was using to test still remained in the kept portion of the file.
I ran the test and once again with the same result as before.

I edited the file once more and got rid of another half of the data and tried again. The file was renamed to: dicc/small.ini and has 3,574 KB

This time, it also showed the Not Responding message on the window's title bar but after exactly 13.5 seconds it disappeared and the definition for the word being seek "casa" showed up.

I ran the same test with mirc 6.x on this computer and it ran as fast as it does on my small older laptop which also runs on windows 7 64 2GB of memory.
I'm sure you already know this but when I run this code on mIRC 6.x it runs incredible quick even on a computer with mechanical hard drive and also considering the lag for data processing is minimal and data retrieval happens in a nick of time regardless of file size.

Below you will find the code I'm using for these testings.
For this test I'm using this code:
/define {
  echo -s $1
  var %file = dicc\small.ini
  if $isfile(%file) {
    echo -s File %file found: $isfile(%file)
    echo -s Searching for: $1 in file: %file
    var %fword = $readini(%file, $1, R)
    if (%fword == $null) {
      %fword = 4 Lo siento, no encontre la definicion
    echo -s %fword
  else {
    echo -s file: %file not found

I may be willing to send you (Mr. Khaled) my data file if you want it for testing.

Find below the pictures that support my tests


Happy New Year!
Posted By: Khaled

Re: $readini issue - 31/12/18 06:07 PM

Thanks for testing it out. Based on the size of your files and looking at your script, it looks like there are thousands of sections in your INI files and each section has one item. Is that the case? Can you post the first ten lines of your INI file?

That said, it is very likely that the INI files will be faster in older versions. The reason for this is that the INI file routines were updated a long time ago due to users reporting issues with corrupted INI files. mIRC was changed to manage INI files itself, instead of relying on Windows to cache and update INI files in the background. This means that, at the cost of being more robust, larger INI files will indeed be slower. This cannot be changed and it cannot be sped up because mIRC has to literally load and parse an entire INI file before it can manage it.
Posted By: maroon

Re: $readini issue - 31/12/18 07:03 PM

I can reproduce some of your problem. $readini is behaving much slower in newer mirc than in 6.35, so what you're experiencing may not be mirc crashing, but just taking a really long time. You can do things like using $findfile() to display all the files on your hard drive, and this causes mirc to display that message as if it's crashed. However it will eventually finish. All tests in this post were using the same .ini file in the same folder, so there's nothing being affected by different folder locations on the disk behaving different due to AV.

I repeated this command 9 times to create random item names, varying in length from 4-12 characters.

//var %i 100000 | while (%i) { var %a $regsubex($str(x,$rand(4,12)),/x/g,$rand(a,z)) | writeini \path\dict.ini R %a %a | dec %i }

Due to duplicates not added, this reports I have 889390 items instead of 900000, and took over 16000ms to perform. The filesize is nearly 17mb. The disk writes were not slow, taking not much longer to write 100k items than to retrieve just the 1 item.

//var %ticks $ticks | echo -a $ini(\path\dict.ini,R,0) | echo -a $calc($ticks - %ticks) ms

mirc 6.35 accessing this same file took only 219ms to count the 889390 items.

I then looked for an item near the end of the file, and another near the middle of the file and another near the front. All 3 $readini commands took almost the exact same time as the above $ini command, exceeding 16000ms.

//var %ticks $ticks | echo -a $readini(\path\dict.ini,R,ItemName) | echo -a $calc($ticks - %ticks) ms

I did attempt to read the same near-the-front-of-file item using the above command in mirc 7.52, and it took 349 seconds to complete.

I excluded that path from antivirus monitoring, so the issue in this thread shouldn't affect it, which mainly affects only diskwrites and deletes https://forums.mirc.com/ubbthreads.php/topics/260688/Re:_Windows_8.1_/write_very_ve#Post260688

If $readini is encountering unicode symbols in your datafile, that could possibly slow it down too.

As a workaround, you can try loading the dictionary into a hashtable in memory. 890k items and 17mb is a lot, but once it's in memory it should be manageable by your OS.

//if (!$hget(fout)) hmake -s fout 10000
/hload -ims fout dicc/fout.ini

Warning. This did take an extremely long time, exceeding a minute, so you probably want to try saving your dictionary in the normal hashtable format instead of .ini. If you had multiple [sections] in the same .ini, you can't load them into the same hashtable while keeping them identifiable as being from different sections.

Once the dictionary is loaded in memory, access is much faster. $hget(fout,Itemname) reported it took 0 ticks to retrieve the same thing as $readini(dicc/fout.ini,R,itemname), and this was with the default 101 buckets. If you increase to 10k buckets as shown above, retrieval should be more efficient, Though counting total items isn't helped by having many buckets, it's still much faster than disk: //echo -a $hget(fout,0).item took 78ms

If comparing 6.35 speed against newest mirc, be aware that some things that work in new mirc aren't available in the old version, such as the syntax to use hload to define the number of buckets while creating the table.

More info about hashtables can be found at https://en.wikichip.org/wiki/mirc/hash_tables
Posted By: CapitanMarte

Re: $readini issue - 31/12/18 07:20 PM

To complement my report I wanted to add that:
I also am using $read() with the same data file for a different application and for that it works just fine on any version of mIRC that I have tested it in.

Yes, the file contains 85,165 sections (I just counted them) As per your request I pasted few entries below.

I understand your explanation. It is too bad then I will not be able to use the newer versions of mIRC then, neither will be able to use newer third party scripts on my games bots.

Firs n(th) entries from the fout.ini dictionary file
R= (1). 1. f. Primera letra del abecedario espaņol y del orden latino internacional, que representa un fonema vocalico abierto y central. 2. f. Fil. Signo de la proposicion universal afirmativa. ~ por ~ y b por b. 1. loc. adv. punto por punto.a (2). (Del lat. ad). 1. prep. Precede a determinados complementos verbales, como el complemento indirecto y el complemento directo cuando este es de persona determinada o esta de algun modo personificado. 
[a contrariis]
R= (Loc. lat.; literalmente, 'por contrarios'). V. argumento a contrariis
[a contrario sensu]
R= (Loc. lat.). 1. loc. adv. En sentido contrario.
[a divinis]
R= (Loc. lat.; literalmente, 'lejos de lo divino'). 1. loc. adj. Dicho de la suspension o cesacion canonica impuesta a un sacerdote: Que lo inhabilita para ejercer su ministerio. U. t. c. loc. adv.
[a fortiori]
R= (Loc. lat.; literalmente, 'por un motivo mas fuerte'). 1. loc. adv. Con mayor razon. 2. loc. adv. fest. Mex. Por la fuerza.
[a latere]
R= (Loc. lat.; literalmente, 'de costado', 'al lado'). 1. com. adlatere. 2. loc. adv. al lado. V. legado a latere
[a nativitate]
R= (Loc. lat.). 1. loc. adv. Dicho de un defecto de sentido o de un miembro: Que se padece porque se nacio con el y no por contingencia o enfermedad sobrevenida.
[a pari]
R= (Loc. lat.; literalmente, 'por igual'). V. argumento a pari
[a posteriori]
R= (Loc. lat.; literalmente, 'de lo posterior'). 1. loc. adv. Indica la demostracion que consiste en ascender del efecto a la causa, o de las propiedades de algo a su esencia. 2. loc. adv. Despues de examinar el asunto de que se trata.
Posted By: CapitanMarte

Re: $readini issue - 31/12/18 07:37 PM

Thanks maroon for your testings, comparing and ideas. I just expected newer versions to work the same or better. This isn't the case for me.
I rather keep using mirc 6.x . and move on to my next project without changing anything.
Posted By: Protopia

Re: $readini issue - 31/12/18 07:54 PM

For the future you might want to consider whether an ini file with 85,000 sections is a good way of storing this.

For example a flat file with lines like:
a= (1). 1. f. Primera letra del abecedario espaņol y del orden latino internacional, que representa un fonema vocalico abierto y central. 2. f. Fil. Signo de la proposicion universal afirmativa. ~ por ~ y b por b. 1. loc. adv. punto por punto.a (2). (Del lat. ad). 1. prep. Precede a determinados complementos verbales, como el complemento indirecto y el complemento directo cuando este es de persona determinada o esta de algun modo personificado. 
a contrariis= (Loc. lat.; literalmente, 'por contrarios'). V. argumento a contrariis

could be read by $read(%fn,ns,a contrariss=) instead of $readini.

However this will still be a sequential read by mIRC of on average 1/2 of the file, which is likely to be resource intensive.

If memory is not a problem, you might want to consider reading the file into a hash table, and then saving / reloading the hash table.

Our you could use a database extension like "sqllite for mirc" (or whatever it is called) to access it more efficiently.
Posted By: Khaled

Re: $readini issue - 31/12/18 09:21 PM

In this case, newer versions of mIRC are working better in that ever since INI file support was changed, the number of reports of corrupt INI files decreased dramatically.

However, better does not necessarily mean faster and can often mean slower because of the amount of extra work that new features need to do to improve behaviour, security, and robustness. That is why it is difficult to compare older versions of a technology with newer versions - the number of differences are far greater than one issue.

That said, in the case of INI files, newer versions of mIRC are actually much faster once the INI file is loaded. For example, try the following script that writes and reads 10000 items. If anti-virus software is disabled, mIRC v7.54 takes 2 seconds, while mIRC v6.x takes 50 seconds. If anti-virus software is enabled, mIRC v7.54 takes 2 seconds again, while mIRC v6.x takes 109 seconds.

test {
  var %ticks $ticks

  var %fn = test.ini
  remove %fn
  var %n = 0
  while (%n < 10000) {
    var %section = n $+ %n
    writeini -n %fn %section r value
    if ($calc(%n % 1000) == 0) { echo n: %n }
    inc %n

  var %n = 0
  while (%n < 10000) {
    var %section = n $+ %n
    var %fword = $readini(%fn, %section, R)
    if ($calc(%n % 1000) == 0) { echo n: %n }
    inc %n

  echo tc: $calc($ticks - %ticks)

So, while /writeini and $readini() are initially slower in newer versions of mIRC when loading large INI files, if a script continues to use them, eg. as in the on TEXT events you are using, they are far faster. In the end, which is better really depends on your use case.
© 2019 mIRC Discussion Forums