【问题标题】:How to create UTF-16 file in VBScript?如何在 VBScript 中创建 UTF-16 文件?
【发布时间】:2018-09-14 21:32:15
【问题描述】:

我的系统是 Window 10 English-US。 我需要将一些不可打印的 ASCII 字符写入文本文件。因此,例如对于 28 的 ASCII 值,我想将 \u001Cw 写入文件。用 Java 编码时,我不需要做任何特别的事情。以下是我在 VBS 中的代码

Dim objStream
Set objStream = CreateObject("ADODB.Stream")
objStream.Open
objStream.Type = 2
objStream.Position = 0
objStream.CharSet = "utf-16"

objStream.WriteText ChrW(28)  'Need this to appear as \u001Cw in the output file

objStream.SaveToFile "C:\temp\test.txt", 2
objStream.Close

【问题讨论】:

  • 有什么问题?
  • 它将 28 的不可打印 ASCII 字符放在文件中,而不是 \u001Cw 如果我从 Java 做同样的事情,我会在文件中得到 \u001Cw。下面是我的 Java 代码,我没有做任何特殊的编码。 FileWriter log = new FileWriter(file); log.write(文本); log.close();

标签: vbscript


【解决方案1】:

您需要一个读写流,以便写入和保存到文件都可以工作。

Const adModeReadWrite = 3
Const adTypeText = 2
Const adSaveCreateOverWrite = 2

Sub SaveToFile(text, filename)
  With CreateObject("ADODB.Stream")
    .Mode = adModeReadWrite
    .Type = adTypeText
    .Charset = "UTF-16"
    .Open
    .WriteText text
    .SaveToFile filename, adSaveCreateOverWrite
    .Close
  End With
End Sub


text = Chr(28) & "Hello" & Chr(28)
SaveToFile text, "C:\temp\test.txt"

其他说明:

  • 我喜欢用Const 明确定义代码中的所有常量。让阅读变得如此轻松。
  • With 块可以节省大量输入。
  • 将流类型设置为adTypeText 并不是真正必要的,无论如何这是默认设置。但我猜,显式总比隐式好。
  • 在新流上将 Position 设置为 0 是多余的。
  • 对于 ASCII 范围的字符,没有必要使用 ChrW()。当您将流保存到文件时,流的Charset 决定了字节宽度。在 RAM 中,无论如何,一切都是 Unicode(是的,即使在 VBScript 中也是如此)。
  • ADODB.Stream 支持两种 UTF-16 编码:little-endian UTF-16LE(这是默认值,与 UTF-16 同义)和 big-endian UTF-16BE,字节顺序颠倒。李>

您可以使用 FileSystemObject 及其 CreateTextFile() method 获得相同的结果:

Set FSO = CreateObject("Scripting.FileSystemObject")

Sub SaveToFile(text, filename)
  ' CreateTextFile(filename [, Overwrite [, Unicode]])
  With FSO.CreateTextFile(filename, True, True)
    .Write text
    .Close
  End With
End Sub


text = Chr(28) & "Hello" & Chr(28)
SaveToFile text, "C:\temp\test.txt"

这有点简单,但它只提供了一个布尔值Unicode 参数,它在 UTF-16 和 ANSI 之间切换(不是 ASCII,因为文档错误地声称!)ADODB.Stream 的解决方案为您提供了细粒度的编码选择,例如 UTF-8,这对于 FileSystemObject 是不可能的。


作为记录,有两种方法可以创建 UTF-8 编码的文本文件:

  • Microsoft 喜欢这样做的方式,文件开头有一个 3 字节长的字节顺序标记 (BOM)。大多数(如果不是所有)Microsoft 工具在提供“UTF-8”选项时都会这样做,ADODB.Stream 也不例外。
  • 其他人的做法 - 没有 BOM。这对于大多数用途都是正确的。

要使用 BOM 创建 UTF-8 文件,可以使用上面的第一个代码示例。要创建 BOM 的 UTF-8 文件,我们可以使用两个流对象:

Const adModeReadWrite = 3
Const adTypeBinary = 1
Const adTypeText = 2
Const adSaveCreateOverWrite = 2

Sub SaveToFile(text, filename)
  Dim iStr: Set iStr = CreateObject("ADODB.Stream")
  Dim oStr: Set oStr = CreateObject("ADODB.Stream")

  ' one stream for converting the text to UTF-8 bytes
  iStr.Mode = adModeReadWrite
  iStr.Type = adTypeText
  iStr.Charset = "UTF-8"
  iStr.Open
  iStr.WriteText text

  ' one steam to write bytes to a file
  oStr.Mode = adModeReadWrite
  oStr.Type = adTypeBinary
  oStr.Open

  ' switch first stream to binary mode and skip UTF-8 BOM
  iStr.Position = 0
  iStr.Type = adTypeBinary
  iStr.Position = 3

  ' write remaining bytes to file and clean up
  oStr.Write iStr.Read
  oStr.SaveToFile filename, adSaveCreateOverWrite
  oStr.Close
  iStr.Close
End Sub

【讨论】:

  • 感谢您非常详细的回复和有用的说明。我非常感谢您为详细说明答案所做的努力。不幸的是,我得到了与原始代码相同的输出。我在 StackOverflow 上找到了一个解决方案,它在一定程度上解决了我的问题stackoverflow.com/questions/2241130/… 但是唯一的问题是我只需要将它用于不可打印的 ASCII 字符(ASCII 值 126)。对于不可打印的 ASCII 字符,我基本上只需要 HEX 值进入文件。这是 Java 默认做的。
  • 我承认我不知道你想要什么。我上面的代码示例输出带有“文件分隔符”字符 (28) 的 UTF-16 编码文本文件,编码为 Unicode 字符。我阅读您的问题的方式,这就是您所要求的。
  • 您想将实际字符串 "\u001C" 写入文本文件吗?
  • 我猜.Charset = "UTF-8" 如果你想写 UTF-8 会起作用并且做显而易见的事情,但我无法验证这一点。有这种环境的人可以确认(或反驳)吗?
猜你喜欢
  • 2023-03-16
  • 2016-01-01
  • 2012-11-06
  • 1970-01-01
  • 2011-10-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多