Vb.net 使用PDFSharp将PDF转换为文本
我编写了以下函数来读取PDF文件中的文本。这是非常接近,但我只是不够熟悉所有的操作代码,以获得正确的行距。例如,当我看到“ET”时,我正在插入一个新行,但这似乎不太正确,因为它可能只是文本运行的结束,中间行。有人能帮我调整一下语法吗?我的目标类似于Adobe Reader的“另存为其他”-->“文本”Vb.net 使用PDFSharp将PDF转换为文本,vb.net,pdf,pdfsharp,Vb.net,Pdf,Pdfsharp,我编写了以下函数来读取PDF文件中的文本。这是非常接近,但我只是不够熟悉所有的操作代码,以获得正确的行距。例如,当我看到“ET”时,我正在插入一个新行,但这似乎不太正确,因为它可能只是文本运行的结束,中间行。有人能帮我调整一下语法吗?我的目标类似于Adobe Reader的“另存为其他”-->“文本” 您的代码忽略了几乎所有更改行的操作。你应该考虑 和 ,这通常意味着线的变化,但在野外很少使用。 因此,在文本对象(BT。ET)中,您还应该注意 tx tyTd移动到下一行的起点,与当前行的起点偏
您的代码忽略了几乎所有更改行的操作。你应该考虑<强> <强>和<强> <强>,这通常意味着线的变化,但在野外很少使用。 因此,在文本对象(BT。ET)中,您还应该注意
- tx tyTd移动到下一行的起点,与当前行的起点偏移(tx,ty)
- tx tyTD移动到下一行的开头,与当前行的开头偏移(tx,ty)。作为副作用,该操作员应在文本状态下设置前导参数
- a b c d e fTm设置文本矩阵Tm和文本行矩阵Tlm
- T*移动到下一行的开头
- 行距TL将文本行距TL设置为行距
- a b c d e fcm通过串联修改当前变换矩阵(CTM) 指定矩阵
- q保存当前图形状态
- Q恢复图形状态
您的代码正在忽略操作的所有数值参数。你不应该忽视它们,尤其是:
- 您应该检查上面列出的运算符的参数;e、 g.当
向下20个单位开始一个新行时,0-20 Td
保持在同一行上,仅在前一行开始的20个单位右侧开始绘制文本20 0 Td
- 您应该检查TJ数组参数的数字元素,因为它们可能(也可能不!)表示两个单词之间的空格
CString
实例的值
已包含Unicode编码的字符数据。这种假设通常是不正确的,在文本绘制操作中绘制的PDF字符串中使用的编码由字体决定。因此,你还应该注意
- font sizeTf将文本字体Tf设置为font,将文本字体大小Tfs设置为size。字体应为当前资源字典的font子字典中字体资源的名称
有关详细信息,您应该首先学习PDF规范,尤其是第8章图形中具有坚实背景的第9章文本。您的代码忽略了几乎所有更改行的操作。你应该考虑<强> <强>和<强> <强>,这通常意味着线的变化,但在野外很少使用。 因此,在文本对象(BT。ET)中,您还应该注意
- tx tyTd移动到下一行的起点,与当前行的起点偏移(tx,ty)
- tx tyTD移动到下一行的开头,与当前行的开头偏移(tx,ty)。作为副作用,该操作员应在文本状态下设置前导参数
- a b c d e fTm设置文本矩阵Tm和文本行矩阵Tlm
- T*移动到下一行的开头
- 行距TL将文本行距TL设置为行距
- a b c d e fcm通过串联修改当前变换矩阵(CTM) 指定矩阵
- q保存当前图形状态
- Q恢复图形状态
您的代码正在忽略操作的所有数值参数。你不应该忽视它们,尤其是:
- 您应该检查上面列出的运算符的参数;e、 g.当
向下20个单位开始一个新行时,0-20 Td
保持在同一行上,仅在前一行开始的20个单位右侧开始绘制文本20 0 Td
- 您应该检查TJ数组参数的数字元素,因为它们可能(也可能不!)表示两个单词之间的空格
CString
实例的值
已包含Unicode编码的字符数据。这种假设通常是不正确的,在文本绘制操作中绘制的PDF字符串中使用的编码由字体决定。因此,你还应该注意
- font sizeTf将文本字体Tf设置为font,将文本字体大小Tfs设置为size。字体应为当前资源字典的font子字典中字体资源的名称
Public Function ReadPDFFile(filePath As String,
Optional maxLength As Integer = 0) As String
Dim sbContents As New StringBuilder
Dim cArrayType As Type = GetType(CArray)
Dim cCommentType As Type = GetType(CComment)
Dim cIntegerType As Type = GetType(CInteger)
Dim cNameType As Type = GetType(CName)
Dim cNumberType As Type = GetType(CNumber)
Dim cOperatorType As Type = GetType(COperator)
Dim cRealType As Type = GetType(CReal)
Dim cSequenceType As Type = GetType(CSequence)
Dim cStringType As Type = GetType(CString)
Dim opCodeNameType As Type = GetType(OpCodeName)
Dim ReadObject As Action(Of CObject) = Sub(obj As CObject)
Dim objType As Type = obj.GetType
Select Case objType
Case cArrayType
Dim arrObj As CArray = DirectCast(obj, CArray)
For Each member As CObject In arrObj
ReadObject(member)
Next
Case cOperatorType
Dim opObj As COperator = DirectCast(obj, COperator)
Select Case System.Enum.GetName(opCodeNameType, opObj.OpCode.OpCodeName)
Case "ET", "Tx"
sbContents.Append(vbNewLine)
Case "Tj", "TJ"
For Each operand As CObject In opObj.Operands
ReadObject(operand)
Next
Case "QuoteSingle", "QuoteDbl"
sbContents.Append(vbNewLine)
For Each operand As CObject In opObj.Operands
ReadObject(operand)
Next
Case Else
'Do Nothing
End Select
Case cSequenceType
Dim seqObj As CSequence = DirectCast(obj, CSequence)
For Each member As CObject In seqObj
ReadObject(member)
Next
Case cStringType
sbContents.Append(DirectCast(obj, CString).Value)
Case cCommentType, cIntegerType, cNameType, cNumberType, cRealType
'Do Nothing
Case Else
Throw New NotImplementedException(obj.GetType().AssemblyQualifiedName)
End Select
End Sub
Using pd As PdfDocument = PdfReader.Open(filePath, PdfDocumentOpenMode.ReadOnly)
For Each page As PdfPage In pd.Pages
ReadObject(ContentReader.ReadContent(page))
If maxLength > 0 And sbContents.Length >= maxLength Then
If sbContents.Length > maxLength Then
sbContents.Remove(maxLength - 1, sbContents.Length - maxLength)
End If
Exit For
End If
sbContents.Append(vbNewLine)
Next
End Using
Return sbContents.ToString
End Function