我可以将流读入包含Unicode BOM的字符串中吗?

时间:2019-07-03 09:45:17

标签: .net string vb.net unicode stream

Content是包含Unicode字符的流。这些可以是UTF-8,UTF-16或UTF-32,并且两种字节序都可以。

这是一个具有UTF-16 Unicode字符的实例,其中包括一个表示Little Endian的BOM:FF FE

我在此文件中有一张职位表。这些位置以16位字符表示。 BOM位于位置0,即BOM位置之后的2个字节。

这样做的时候

Dim oContent = New StreamReader(Content, Text.Encoding.Unicode)
Dim sContent = oContent.ReadToEnd

物料清单被完全吞没:

?scontent
"AAaa" & vbCrLf & "BB111" & vbCrLf & "BB22222" & vbCrLf & "CCc" & vbCrLf & ...

detectEncodingFromByteOrderMarks设置为False时:

    Dim oContent = New StreamReader(Content, False)
    Dim sContent = oContent.ReadToEnd

每个字符代表一个字节(但包括BOM):

?scontent
"��A" & vbNullChar & "A" & vbNullChar & "a" & vbNullChar & "a" & vbNullChar & vbCr & vbNullChar & vbLf & ...

两者的结合

    Dim oContent = New StreamReader(Content, Text.Encoding.Unicode, False)
    Dim sContent = oContent.ReadToEnd

再次完全吞下BOM:

?scontent
"AAaa" & vbCrLf & "BB111" & vbCrLf & "BB22222" & vbCrLf & "CCc" & vbCrLf & "DDddd" & vbCrLf

问题:我可以以某种方式在字符串中获取以下内容,就像在流中一样吗?

Char    0     1     2     3
Byte    0  1  2  3  4  5  6  7
Content FF FE 41 00 41 00 61 00 ...

String.Substring(1,3)应该产生“ AAa”

如果不是::我能以某种方式检测到提供了什么BOM和多少字节吗? (输入文件之间有所不同。)

1 个答案:

答案 0 :(得分:1)

  

我能以某种方式检测到提供了什么BOM和多少字节吗?

如果您的文件(或流,无论如何)是UTF-16编码的,则BOM始终为2个字节:FE FFFF FE

因此,如果您确实需要了解BOM(如果文件是大端或小端),则只需读取文件(或流)的前两个字节即可:

Dim data as Byte()
Using fs = File.OpenRead("path/to/file/test.txt")
    Using binaryReader = new BinaryReader(fs)
        data = binaryReader.ReadBytes(2)
    End Using
End Using

如果您的文件包含BOM表,data现在将包含FE FFFF FE

但是您还说过,您已经知道您的文件是UTF-16 little-endian文件,因此对我来说您实际上想实现的目标还不清楚。

当您将文件/流读取为字符串时,该字符串将不包含BOM,因为这没有意义:BOM不是实际内容的一部分,它只是指示如何解释内容的标记。一堆字节。

还要注意,并非UTF-16字符串中的每个字符都由两个8位字节表示:字符也可以由4个字节表示。

如果要将内容作为字符串,只需使用StreamReader(Content, Text.Encoding.Unicode)

以您的示例

  

String.Substring(1, 3)应该产生"AAa"

要么从索引(1中减去String.Substring(0, 3),要么在字符串(Dim sContent = "x" + oContent.ReadToEnd)中添加一个虚拟的16位字符。


更新:要获取文件/流的编码,请让StreamReader为您完成工作:

 Dim encoding as Encoding
 using sr = new StreamReader(filename, true)
    sr.peek()
    encoding = sr.CurrentEncoding
 end using

encoding.BodyName现在是utf-16BE