.NET 可以很容易地从剪贴板内读取文本、图片、文件等数据,但若是剪贴板内拥有HTML内容,则读取出来的是 HtmlFragment 格式,需要自己进行格式转换和读取。

其实这种 HtmlFragment 格式非常简单,只是将一些描述信息放在头部,包括版本、HTML内容位置、Fragment内容位置、源文件地址等……
然而当我尝试读取此格式时,发现读取出来的HTML内容乱码严重,即便对文本内容进行转码,依然无法解决缺字和部分乱码。
后来我又搜索了很久,才发现原来.NET的剪贴板类本身就有BUG,内部的文本需要自己通过读取剪贴板的内存流,再进行文本的数据转换,才能正确读取出数据。

一个编写好的函数如下:

Imports System.Text
Imports System.Text.RegularExpressions
Imports System.IO


Shared Function ParserClipboardHTML() As String

    If Not Clipboard.ContainsText(TextDataFormat.Html) Then
        Return Nothing
    End If

    ' 获取剪贴板HTML原始数据
    Dim ms As MemoryStream = Clipboard.GetData("Html Format")
    ms.Position = 0
    Dim bs(ms.Length - 1) As Byte
    ms.Read(bs, 0, bs.Length)

    Dim html As String = Encoding.UTF8.GetString(bs)
    If html = Nothing Then Return Nothing

    ' 找到内容边界
    Dim startF As Integer = -1, endF As Integer = -1
    Using reader As New StreamReader(ms)
        ms.Position = 0
        Dim m As Match
        Do
            If reader.EndOfStream Then Exit Do

            m = Regex.Match(reader.ReadLine, "^(\w+)\s*\:\s*(.+)$", RegexOptions.IgnoreCase Or RegexOptions.Multiline)
            If m.Success Then
                Select Case m.Groups(1).Value
                    Case "StartFragment"
                        startF = CInt(m.Groups(2).Value)
                    Case "EndFragment"
                        endF = CInt(m.Groups(2).Value)
                End Select
            Else
                Exit Do
            End If
        Loop
    End Using
    ms.Close()

    If startF < 0 OrElse endF < 0 Then
        'Throw New Exception("无法找到剪贴内容的边界")
        Return Nothing
    End If

    ' 取出相应数据
    Dim bsnew(endF - startF - 1) As Byte
    Buffer.BlockCopy(bs, startF, bsnew, 0, bsnew.Length)

    Dim ret As String = Encoding.UTF8.GetString(bsnew)
    Return ret
End Function
浪费了好多时间,.NET真特么蛋疼!