На первый взгляд
I проверил файлы, предоставленные OP, используя текущую версию iTextSharp 5.5.7. Прежде всего, они не показывают точной проблемы, которую ОП описывает, потому что ни один из документов даже не содержит строку Путь местоположения. Они показывают сравнимое поведение, хотя, колонтитулы, как это:
Здесь экстрагирования с SimpleTextExtractionStrategy
действительно возвращает
M ethod Path: D:\Analyst Data\Projects\879...
Results Path: D:\Analyst Data\Projects\879...
Я уже объяснил некоторые фоны для этого в комментарии:
В «Пути методов» две буквы «M» и «e» не соответствуют друг другу, они фактически почти перекрываются! iText в таком случае хочет указать, что буквы неправильно следуют друг за другом, а поскольку строка не содержит небольшой задний шаг, iText выражает это с помощью символа пробела.
Но здесь ситуация отличается от ситуации OP описанной, поскольку экстракция с использованием LocationTextExtractionStrategy
возвращается:
Method Path: D:\Analyst Data\Projects\879...
Results Path: D:\Analyst Data\Projects\879...
Таким образом, я хотел бы предложить, что ОП проверяет версию iTextSharp он использует и переключается на LocationTextExtractionStrategy
текущей версии библиотеки.
Если даже после обновления до текущей версии проблема остается, пожалуйста, поделитесь PDF-файлом, с которым проблема может наблюдаться и с LocationTextExtractionStrategy
.
На второй взгляд
Как О.П. настаивал, что существуют пробелы, где никто не должен быть, даже в LocationTextExtractionStrategy
выходе, я действительно нашел некоторые после снова и снова искать (намек относительно местонахождение пространств будет иметь было приятно ...)
В разделе заголовка я нашел «Налист», «Оператор» и «W orkstation».
Причина для них, к сожалению, не имеет ничего общего с iText, указывающим на то, что текстовые фрагменты не соответствуют друг другу. Вместо этого причина в том, что - пробел. Например. в случае «Налиста» поток контента выглядит следующим образом:
q
1.0 1.0 1.0 rg
29.28 822.24 39.12 4.8 re
f
BT
/F2 4.515 Tf
0.0 0.0 0.0 rg
0.9998 0.0 0.0 1.0 29.28 823.2 Tm
[()] TJ
ET
Q
q
BT
/F2 4.515 Tf
0.0 0.0 0.0 rg
0.9998 0.0 0.0 1.0 29.28 823.2 Tm
[(A)30(n)21(a)18(l)65(y)21(s)-36(t)12()-15(V)137(e)71(r)14(s)-36(i)65(o)-31(n)21(:)65()-15(1)21(.)-15(6)21(.)-15(2)] TJ
ET
Q
I.e. после того, как рисунок белый прямоугольник (повторно, е), пробел обращается ([()] TJ) в точно то же самое положение (0,9998 0,0 0,0 1,0 29,28 823,2 Тт) как " A 'аналитика ([(A) ...] TJ).
После сортировки фрагментов текста пространство появляется сразу после «A» (порядок символов в том же положении после сортировки произвольный), поэтому вы получаете «A nalyst».
Можно было бы подумать об изменении стратегии извлечения текста, чтобы сохранить исходный порядок символов, напечатанных в одном месте, но в конце концов могут сломать другие документы. Тем не менее ...
Более верная стратегия извлечения
Мы попытаемся настроить LocationTextExtractionStrategy
сохранить порядок блоков текста которые закреплены на одной и той же позиции.
LocationTextExtractionStrategy
явно произвольно в связи с этим:
virtual public int CompareTo(TextChunk rhs) {
if (this == rhs) return 0; // not really needed, but just in case
int rslt;
rslt = CompareInts(orientationMagnitude, rhs.orientationMagnitude);
if (rslt != 0) return rslt;
rslt = CompareInts(distPerpendicular, rhs.distPerpendicular);
if (rslt != 0) return rslt;
// note: it's never safe to check floating point numbers for equality, and if two chunks
// are truly right on top of each other, which one comes first or second just doesn't matter
// so we arbitrarily choose this way.
rslt = distParallelStart < rhs.distParallelStart ? -1 : 1;
return rslt;
}
(LocationTextExtractionStrategy.TextChunk
)
Это произвольный выбор не только ненужным, но и нарушает договор, связанный с интерфейсом IComparable
который этот метод инвентарь:
Для объектов A, B и C следуют должно быть правдой:
A.CompareTo(A)
должен вернуть ноль.
Если A.CompareTo(B)
возвращает ноль, то B.CompareTo(A)
должен вернуть ноль.
Если A.CompareTo(B)
возвращает ноль и B.CompareTo(C)
возвращает ноль, то A.CompareTo(C)
должен вернуть ноль.
Если A.CompareTo(B)
возвращает значение, отличное от нуля, то B.CompareTo(A)
должно возвращать значение противоположного знака.
Если A.CompareTo(B)
возвращает значение x
не равное нулю, и B.CompareTo(C)
возвращает значение y
одного и того же знака, что и x
, то A.CompareTo(C)
должна возвращать значение одного и того же знака, что и x
y
.
(MSDN on IComparable.CompareTo)
Особенно жирным шрифтом условие не выполнено.
Следующая стратегия удаления текста здесь не является произвольной, но сохраняет порядок, в котором текстовые фрагменты поступают в качестве конечного элемента сравнения.
class FaithfulLocationTextExtractionStrategy : LocationTextExtractionStrategy
{
public class FaithfulTextChunk : TextChunk
{
public FaithfulTextChunk(String stringValue, Vector startLocation, Vector endLocation, float charSpaceWidth, int index)
: base(stringValue, startLocation, endLocation, charSpaceWidth)
{
this.index = index;
orientationMagnitudeField = typeof(TextChunk).GetField("orientationMagnitude", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
distPerpendicularField = typeof(TextChunk).GetField("distPerpendicular", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
distParallelStartField = typeof(TextChunk).GetField("distParallelStart", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
}
override public int CompareTo(TextChunk rhs)
{
if (this == rhs) return 0; // not really needed, but just in case
if (rhs is FaithfulTextChunk)
{
int rslt;
rslt = CompareInts((int)orientationMagnitudeField.GetValue(this), (int)orientationMagnitudeField.GetValue(rhs));
if (rslt != 0) return rslt;
rslt = CompareInts((int)distPerpendicularField.GetValue(this), (int)distPerpendicularField.GetValue(rhs));
if (rslt != 0) return rslt;
rslt = CompareFloats((float)distParallelStartField.GetValue(this), (float)distParallelStartField.GetValue(rhs));
if (rslt != 0) return rslt;
return CompareInts(index, ((FaithfulTextChunk)rhs).index);
}
else
return base.CompareTo(rhs);
}
private static int CompareInts(int int1, int int2)
{
return int1 == int2 ? 0 : int1 < int2 ? -1 : 1;
}
private static int CompareFloats(float float1, float float2)
{
return float1 == float2 ? 0 : float1 < float2 ? -1 : 1;
}
int index;
System.Reflection.FieldInfo orientationMagnitudeField, distPerpendicularField, distParallelStartField;
}
public override void RenderText(TextRenderInfo renderInfo)
{
LineSegment segment = renderInfo.GetBaseline();
if (renderInfo.GetRise() != 0){ // remove the rise from the baseline - we do this because the text from a super/subscript render operations should probably be considered as part of the baseline of the text the super/sub is relative to
Matrix riseOffsetTransform = new Matrix(0, -renderInfo.GetRise());
segment = segment.TransformBy(riseOffsetTransform);
}
TextChunk location = new FaithfulTextChunk(renderInfo.GetText(), segment.GetStartPoint(), segment.GetEndPoint(), renderInfo.GetSingleSpaceWidth(), nextIndex++);
getLocationalResult().Add(location);
}
public FaithfulLocationTextExtractionStrategy()
{
locationalResultField = typeof(LocationTextExtractionStrategy).GetField("locationalResult", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
}
List<TextChunk> getLocationalResult()
{
return (List<TextChunk>) locationalResultField.GetValue(this);
}
System.Reflection.FieldInfo locationalResultField;
int nextIndex = 0;
}
Используя эту стратегию, я извлечь «Аналитик» вместо «А nalyst», «Оператор» вместо «O perator» и «Рабочая станция» вместо «W orkstation».
Поскольку многие используемые переменные являются частными, класс использует отражение. Это может быть запрещено в некоторых контекстах. Поэтому в таких контекстах просто выполните эти изменения в копию кода LocationTextExtractionStrategy
.
Просьба поделиться с нами PDF. Дополнительные пробелы могут быть связаны либо с разрядным отступом, либо с фактически существующими (но надпечатанными) пробелами. – mkl
Привет, сэр, я также сообщаю все pdf в вашей почте. Идентификатор Пожалуйста, проверьте –
. Я посмотрю на это позже (скорее всего, в понедельник). – mkl