{"id":109861,"date":"2024-06-06T07:00:00","date_gmt":"2024-06-06T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=109861"},"modified":"2024-06-06T10:09:39","modified_gmt":"2024-06-06T17:09:39","slug":"20240606-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20240606-00\/?p=109861","title":{"rendered":"Can INI files be Unicode? Yes, they can, but it has to be your idea"},"content":{"rendered":"<p>INI files were introduced by 16-bit Windows, and 16-bit Windows predates Unicode, so INI files naturally did not support Unicode at the time they were introduced. The relatively simple format of INI files means that many people parse (and sometimes even modify) them directly, without using the INI file manager. This in turn means that the format of INI files is pretty much locked and cannot be extended, since there is no mechanism for extending them in a way that won&#8217;t break those manual INI file parsers.<\/p>\n<p>This &#8220;locked in&#8221; nature of the INI file format means that even if you call the Unicode version, <code>Write\u00adPrivate\u00adProfile\u00adStringW<\/code>, the resulting INI file will not be Unicode. It will be a best approximation of your Unicode data in the ambient ANSI code page. The system doesn&#8217;t know whether the INI file is going to be processed by somebody&#8217;s homemade INI file parser, and writing it out in Unicode would break them.<\/p>\n<p>You might think, &#8220;Aw, c&#8217;mon. If you use the Unicode <code>Write\u00adPrivate\u00adProfile\u00adStringW<\/code> function, then clearly the resulting INI file can be Unicode. After all, this is a new function, so there&#8217;s no need to preserve legacy behavior.&#8221; However, <a title=\"Unicode INI function; Unicode INI file?\" href=\"http:\/\/archives.miloush.net\/michkap\/archive\/2006\/09\/15\/754992.html\"> Michael Kaplan noted<\/a> that this would mean that converting a program from ANSI to Unicode (which was a frequent occurrence back in the day) would invisibly modify file formats, and your program may not be ready for that.<\/p>\n<p>But that doesn&#8217;t mean that INI files could <i>never<\/i> support Unicode.<\/p>\n<p>Because if the INI file was <i>already<\/i> Unicode, then there would be no harm in <i>keeping<\/i> it in Unicode. The decision to create a Unicode INI file came from somewhere else, and we&#8217;re just following somebody else&#8217;s decision.<\/p>\n<p>So the rule is that the INI file functions will preserve Unicode-ness, but will never take it upon themselves to create a Unicode INI file. In particular, if you use a Write function to <i>create<\/i> an INI file, that INI file will be created as ANSI, for backward compatibility.<\/p>\n<p>This behavior is called out in the documentation:<\/p>\n<blockquote class=\"q\"><p>If the file was created using Unicode characters, the function writes Unicode characters to the file. Otherwise, the function writes ANSI characters.<\/p><\/blockquote>\n<p>Michael says, &#8220;I have almost no idea what this text is trying to say, but I am 100% sure it is wrong.&#8221;<\/p>\n<p>What it&#8217;s trying to say is what Michael inferred: The function writes Unicode characters to the file if the file is already Unicode.<\/p>\n<p>I think what confused Michael was the phrase &#8220;If the file was created&#8221;. This is not referring to the creation of the file by the <code>Write\u00adPrivate\u00adProfile\u00adStringW<\/code> function itself, but rather to whether the file had <i>already been created<\/i> as a Unicode file before <code>Write\u00adPrivate\u00adProfile\u00adStringW<\/code> was called.<\/p>\n<p>Arguably, the text could be made a little clearer:<\/p>\n<blockquote class=\"q\"><p>If the file <span style=\"border: solid 1px currentcolor;\">already exists and consists of<\/span> Unicode characters, the function writes Unicode characters to the file. Otherwise, the function writes ANSI characters.<\/p><\/blockquote>\n","protected":false},"excerpt":{"rendered":"<p>It&#8217;ll only be Unicode if it&#8217;s already Unicode.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-109861","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>It&#8217;ll only be Unicode if it&#8217;s already Unicode.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/109861","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=109861"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/109861\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=109861"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=109861"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=109861"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}