【问题标题】:VBA : save a file with UTF-8 without BOMVBA:使用 UTF-8 保存文件,没有 BOM
【发布时间】:2015-07-15 16:10:19
【问题描述】:

这可能很简单,这是我尝试过的:

 Set objStream = CreateObject("ADODB.Stream")
 Set objStreamNoBOM = CreateObject("ADODB.Stream")

 With objStream
        .Open
        .Charset = "UTF-8"
        .WriteText "aaaaaa"
        .Position = 0
    End With

    With objStreamNoBOM
      '.Charset = "Windows-1252"   ' WORK
       .Charset = "UTF-8"          ' DOESN'T WORK!!
       .Open
       .Type = 2
       .WriteText objStream.ReadText
       .SaveToFile "toto.php", 2
       .Close
    End With
    objStream.Close

如果字符集是 UTF-8,则文件开头有 ï»。

知道如何用 UTF-8 和不带 BOM 的方式保存文件吗?

【问题讨论】:

    标签: vba excel utf-8 vbscript vb6


    【解决方案1】:

    在所有可能的情况下,相关列表将包含对 this question 的引用,我发现它是“vbscript adodb.stream bom vbscript site:stackoverflow.com”的第一个命中。

    基于boost's answer的第二个策略:

    Option Explicit
    
    Const adSaveCreateNotExist = 1
    Const adSaveCreateOverWrite = 2
    Const adTypeBinary = 1
    Const adTypeText   = 2
    
    Dim objStreamUTF8      : Set objStreamUTF8      = CreateObject("ADODB.Stream")
    Dim objStreamUTF8NoBOM : Set objStreamUTF8NoBOM = CreateObject("ADODB.Stream")
    
    With objStreamUTF8
      .Charset = "UTF-8"
      .Open
      .WriteText "aÄö"
      .Position = 0
      .SaveToFile "toto.php", adSaveCreateOverWrite
      .Type     = adTypeText
      .Position = 3
    End With
    
    With objStreamUTF8NoBOM
      .Type    = adTypeBinary
      .Open
      objStreamUTF8.CopyTo objStreamUTF8NoBOM
      .SaveToFile "toto-nobom.php", adSaveCreateOverWrite
    End With
    
    objStreamUTF8.Close
    objStreamUTF8NoBOM.Close
    

    证据:

    chcp
    Active code page: 65001
    
    dir
     ...
    15.07.2015  18:48                 5 toto-nobom.php
    15.07.2015  18:48                 8 toto.php
    
    type toto-nobom.php
    aÄö
    

    【讨论】:

    • adSaveCreateNotExist 是一个未使用的常量
    • 太棒了!不需要第一个 SaveToFile,一个 .Flush 就可以完成这项工作。测试代码,在记事本中保存为UTF16-LE,否则测试字符串在读取源代码时不会被vbs乱码..
    【解决方案2】:

    我知道脚本文件系统对象的流插入了字节顺序标记,但我还没有看到 ADODB 流。

    或者至少现在还没有:我很少使用 ADODB 流对象...

    但我确实记得几年前将这句话写进了一些代码:

    '   ****   WHY THIS IS COMMENTED OUT   **** **** **** **** **** **** **** ****
    '
    '   Microsoft ODBC and OLEDB database drivers cannot read the field names from
    '   the header when a unicode byte order mark (&HFF & &HFE) is inserted at the
    '   start of the text by Scripting.FileSystemObject 'Write' methods. Trying to
    '   work around this by writing byte arrays will fail; FSO 'Write' detects the
    '   string encoding automatically, and won't let you hack around it by writing
    '   the header as UTF-8 (or 'Narrow' string) and appending the rest as unicode
    '
    '   (Yes, I tried some revolting hacks to get around it: don't *ever* do that)
    '
    '   **** **** **** **** **** **** **** **** **** **** **** **** **** **** ****
    '
    '    With FSO.OpenTextFile(FilePath, ForWriting, True, TristateTrue)
    '        .Write Join(arrTemp1, EOROW)
    '        .Close
    '    End With ' textstream object from objFSO.OpenTextFile
    '
    '   **** **** **** **** **** **** **** **** **** **** **** **** **** **** ****
    

    你可以看出我今天过得很糟糕。

    接下来,使用来自原始 C 的文件处理出现之前的史前 PUT 命令:

    '   **** WHY WE 'PUT' A BYTE ARRAY INSTEAD OF A VBA STRING VARIABLE  **** ****
    '
    '       Put #hndFile, , StrConv(Join(arrTemp1, EOROW), vbUnicode)
    '       Put #hndFile, , Join(arrTemp1, EOROW)
    '
    '   If you pass unicode, Wide or UTF-16 string variables to PUT, it prepends a
    '   Unicode Byte Order Mark to the data which, when written to your file, will
    '   render the field names illegible to Microsoft's JET ODBC and ACE-OLEDB SQL
    '   drivers (which can actually read unicode field names, if the helpful label
    '   isn't in the way). However, the 'PUT' statements writes a Byte array as-is
    '
    '   **** **** **** **** **** **** **** **** **** **** **** **** **** **** ****
    

    所以实际上有代码:

    Dim arrByte() As Byte
    Dim strText   As String
    Dim hndFile   As String
    
    
        strText = "Y'all knew that strings are actually byte arrays?"
        arrByte = strText 
    
        hndFile = FreeFile
        Open FilePath For Binary As #hndFile
    
        Put #hndFile, , arrByte
        Close #hndFile
    
        Erase arrByte
    

    我假设 strText 实际上是 UTF-8。我的意思是,我们在 VBA 中,在 Microsoft Office 中,我们绝对知道这将始终是 UTF-8,即使我们在国外使用它...

    ...对吗?

    【讨论】:

    • 无论如何感谢您的回答尼罗河,它最终与 Ekkehard.Horner 的解决方案一起工作
    • AFAIK 这会导致 UTF-16 编码(所有当前版本的 Windows 都支持)。
    • @T.M - 最好检查一下:分别在 VBA IDE 的导出文本中,以及在工作表本身显示的文本中。
    • @NigelHeffernan,感谢您对可能的版本问题(?)的反馈;实际上,我新安装的 Office 2019 64 位中的记事本编辑器将 UTF-16LE 显示为导出文本的当前保存选项,所以我猜它 UTF-16 编码的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-28
    • 1970-01-01
    • 2020-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-10
    相关资源
    最近更新 更多