【问题标题】:Using Visual Basic to read a Unicode INI file使用 Visual Basic 读取 Unicode INI 文件
【发布时间】:2018-04-09 21:36:43
【问题描述】:

使用 Visual Basic 从 Unicode INI 文档中读取 INI 值。

我认为这是正确的:

Private Class NativeMethods
    ' AJT 2014.11.28 Use the unicode function !!!
    <DllImport("kernel32", CharSet:=CharSet.Unicode)>
    Public Shared Function WritePrivateProfileString(section As String, key As String, val As String, filePath As String) As Boolean
    End Function

    ' AJT 2014.11.28 Use the unicode function !!!
    <DllImport("kernel32", CharSet:=CharSet.Unicode)>
    Public Shared Function GetPrivateProfileString(section As String, key As String, def As String, retVal As StringBuilder, size As Integer, filePath As String) As Integer
    End Function
End Class

但是当我从 INI 文件中读取俄语数据时,我得到了问号。

然后我偶然发现了this,它定义了:

Private Declare Function GetPrivateProfileString _
   Lib "kernel32" Alias "GetPrivateProfileStringA" _
  (ByVal lpSectionName As String, _
   ByVal lpKeyName As Any, _
   ByVal lpDefault As String, _
   ByVal lpbuffurnedString As String, _
   ByVal nBuffSize As Long, _
   ByVal lpFileName As String) As Long

我注意到他们使用了GetPrivateProfileStringA,这让我觉得我可能需要使用GetPrivateProfileStringW,但现在我很困惑,因为我正在使用:

<DllImport("kernel32", CharSet:=CharSet.Unicode)>

请帮忙。

【问题讨论】:

  • 这是一个严格的遗留 API,保留用于重现 Windows v3 行为。它不知道有关文本编码的 bean,它始终假定文件中的文本使用默认的系统代码页。几乎不是唯一的问题,读取单个设置时吹出 50 毫秒也很难隐藏。不要使用它。
  • 作为GetPrivateProfileString() 方法的替代方案,我编写了一个纯.NET 解决方案,该解决方案利用Regex 来解析INI。您可以从文件或字符串中加载它,从而为您提供指定编码的选项:stackoverflow.com/a/44096742(目前它仅支持读取 INI,但将其调整为写入也不是很复杂)
  • @VisualVincent 谢谢。我刚刚在您的答案中添加了一个查询。

标签: vb.net


【解决方案1】:

您提供的链接早于 .NET。您正在查看的内容(Lib "kernel32" Alias "GetPrivateProfileStringA" 语法)实际上是在 VB6 等中导入非托管类型等的旧方法。此语法在 VB.NET 中仍然有效,但已被 @ 取代987654325@ 功能。如果使用这种较旧的处理方式,您是正确的,因为您需要指定 "GetPrivateProfileStringW" 而不是 "GetPrivateProfileStringA"

关于您遇到的问题,俄语字符可能不是问题的实际原因;可能是您只是在取回垃圾数据。如果您的 DllImport 方法的参数未使用一个或多个参数的正确类型定义,则可能会发生这种情况。

尝试查看以下链接。 PInvoke 网站通常包含有关如何正确定义方法签名的有用信息: https://www.pinvoke.net/default.aspx/kernel32.getprivateprofilestring https://www.pinvoke.net/default.aspx/kernel32.writeprivateprofilestring

为了完整起见,我在下面添加了这些定义(直接从上面的链接复制,尽管我承认我自己没有测试过它们)。 如果您对此仍有疑问,可能值得用您尝试阅读的 INI 文件内容示例更新您的答案。

GetPrivateProfileString():

DllImport("kernel32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)> _
Private Shared Function GetPrivateProfileString(ByVal lpAppName As String, _
                        ByVal lpKeyName As String, _
                        ByVal lpDefault As String, _
                        ByVal lpReturnedString As StringBuilder, _
                        ByVal nSize As Integer, _
                        ByVal lpFileName As String) As Integer
End Function

WritePrivateProfileString():

<DllImport("kernel32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)> _
Private Shared Function GetPrivateProfileString(ByVal lpAppName As String, _
                        ByVal lpKeyName As String, _
                        ByVal lpDefault As String, _
                        ByVal lpReturnedString As StringBuilder, _
                        ByVal nSize As Integer, _
                        ByVal lpFileName As String) As Integer
End Function

【讨论】:

  • 谢谢。那么看看那个网页,究竟是如何告诉它使用 Unicode 版本的呢?
  • 在您的问题中,在 DllImport 属性中设置 CharSet:=CharSet.Unicode 会告诉它使用函数的 unicode 版本。我的回答旨在引起人们对函数参数本身的注意,因为我怀疑这就是问题所在,基于您问题中当前可用的信息。但是,为了避免混淆,我更新了我的答案,在从 PInvoke 网站复制的示例中的 DllImport 属性中包含了 CharSet 字段的设置。
猜你喜欢
  • 2017-10-20
  • 2016-10-02
  • 1970-01-01
  • 2014-06-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-24
  • 1970-01-01
相关资源
最近更新 更多