2014-07-07 6 views
0

Я пытаюсь разобрать таблицу в текстовом формате. Программа написана в Visual Studio с использованием C#. Мне нужно проанализировать таблицу и вставить данные в базу данных.Parsing Plain Text Table

Ниже приведен пример таблицы я буду чтение в:

ID Name   Value1  Value2   Value3  Value4 //header 
1  nameA   3.0   0.2   2   6.2 
2  nameB 
3  nameC   2.9       3.0   7.3 
4  nameD   1.5   3.0   1.8   1.1 
5  nameE 
6  nameF  1.2  2.4   3.3   2.5 
7  nameG  3.0  3.2   2.1   4.5 
8  nameH     88   12.4   28.9 

В примере, мне нужно будет захватить данные для идентификатора 1, 3, 4, 6, 7 и 8.

Я думал о двух подходах к этому, но ни один из них не работает на 100%.

Метод 1:

Читая в заголовке, я могу получить начальный индекс для каждого столбца. Затем я буду использовать Substring для сбора данных для каждой строки.

ВОПРОС: раз ему после определенного ряда (который я не будет иметь ни малейшего представления, когда это происходит), столбцы не сдвинуть, и Substring больше не будет собирать правильные данные.

Этот метод будет собирать только правильные данные в течение 1, 3 и 4.

Способ 2:

Использование Regex собрать все матчи. Я надеюсь, что это может собрать ID, Name, Value1, Value2, Value3, Value4 в этом порядке.

Моя картина (\d*?)\s\s\s+(.*?)\s\s\s+(\d*\.*\d*)\s\s\s+(\d*\.*\d*)\s\s\s+(\d*\.*\d*)\s\s\s+(\d*\.*\d*)

ВОПРОС: данные, которые собираются сдвигаются влево на несколько строк. Например, в ID 3 Value2 должен быть пустым, но регулярное выражение будет читать Value2 = 3.0, Value3 = 7.3 и Value4 = blank. То же самое относится и к ID 8.

Вопрос:

Как я могу читать всю таблицу и проанализировать их правильно?

(1) Я не знаю, начиная с которого строка значения будут сдвинуты и

(2) Я не знаю, сколько клеток будет сдвинуты, и если они совместимы.

Дополнительная информация

таблица находится в файле PDF, я преобразовал PDF в текстовый файл, так что я могу читать в данных. Данные смены происходят, когда таблица проходит через несколько страниц, но она несовместима.

EDIT

Ниже приведены некоторые фактические данные:

68      BENZYL ALCOHOL        6.0       0.4   1     7.4 

91      EVERNIA PRUNASTRI (OAK MOSS)     34        3    3     10 

22      test                  2323   23     12 
+0

Может ли значения иметь пробелы? – dognose

+0

Есть ли в таблице пробелы ('')? если нет, вы можете просто прочитать одну строку и разделить на все пробелы и отсортировать все пустые строки. – coolerfarmer

+0

@coolerfarmer думал то же самое - но не работает, потому что могут быть пустые ячейки. Таким образом, вы не знаете, как распределить 3 значения по 4 столбцам. (Если вы не создаете какую-то ошибочную логику с подсчетом пробелов между ними, чтобы определить это.) – dognose

ответ

1

нормально, здесь у идти! Используйте это регулярное выражение:

ПРИМЕЧАНИЕ: вы должны сопоставить это с любой отдельной строкой, а не со всем документом! Если вы хотите сделать это для всего документа, вам нужно добавить модификатор «multiline» («m»). Вы можете сделать это, добавив (?m) в начале шаблона регулярного выражения!

EDIT:

Вы представили некоторые линии ваших реальных данных. Вот мой обновленный шаблон регулярного выражения:

^(?<id>\d+)(?:\s{2,25})(?<name>.+?)(?:\s{2,45})(?<val1>\d+(?:\.\d+)?)?(?:\s{2,33})(?<val2>\d+(?:\.\d+)?)?(?:\s{2,14})(?<val3>\d+(?:\.\d+)?)?(?:\s{2,19})(?<val4>\d+(?:\.\d+)?)?$ 
+0

большое вам спасибо! Я попробовал ваше регулярное выражение, и он работает для образца, который я предоставил, однако, когда я подключаю его к фактическим данным, он не работает. Это одна строка из фактических данных «68 BENZYL ALCOHOL 6.0 0.4 1 7.4», можете ли вы объяснить, почему она не захватывает и не помогает мне ее изменить? – sora0419

+0

Хорошо, я попробую. Можете ли вы выслать мне еще несколько строк данных, чтобы я мог проверить их с ними? – coolerfarmer

+0

, пожалуйста, ознакомьтесь с моими изменениями, спасибо! – sora0419

1

Как насчет лечения этого файла, как фиксированной длины файла, в котором вы можете определить каждый столбец по индексу и длины.После того, как вы определили столбцы фиксированной длины, вы можете просто получить значение для столбца с Substring, затем Trim, чтобы очистить его.

Вы можете обернуть все это в оператор Linq, чтобы проецировать тип анонимного письма и фильтровать нужные вам идентификаторы.

Что-то вроде этого:

static void Main(string[] args) 
{ 
    int[] select = new int[] { 1, 3, 4, 6, 7, 8 }; 
    string[] lines = File.ReadAllLines("TextFile1.txt"); 

    var q = lines.Skip(1).Select(l => new { 
     Id = Int32.Parse(GetValue(l, 0, 6)), 
     Name = GetValue(l, 6, 11), 
     Value1 = GetValue(l, 17, 11), 
     Value2 = GetValue(l, 28, 13), 
     Value3 = GetValue(l, 41, 14), 
     Value4 = GetValue(l, 55, 13), 
    }).Where(o => select.Contains(o.Id)); 

    var r = q.ToArray();   
} 

static string GetValue(string line, int index, int length) 
{ 
    string value = null; 
    int lineLength = line.Length; 

    // Take as much of the line as we can up to column length 
    if(lineLength > index)    
     value = line.Substring(index, Math.Min(length, lineLength - index)).Trim(); 

    // Return null if we just have whitespace 
    return String.IsNullOrWhiteSpace(value) ? null : value; 
}