2009-05-06 3 views
1

Я пытаюсь разобрать текстовый файл с заголовком и телом. В заголовке этого файла есть ссылки на номера строк на разделы тела. Например:Анализ текстового файла в C# с пропуском некоторого содержимого

SECTION_A 256 
SECTION_B 344 
SECTION_C 556 

Это означает, что SECTION_A начинается в строке 256.

Что бы лучший способ разобрать этот заголовок в словаре, а затем при необходимости прочитать разделы.

Типичные сценарии будут:

  1. Разбираем заголовок и читать только раздел SECTION_B
  2. Разбираем заголовок и прочитать кулака абзац каждого раздела.

Файл данных довольно большой, и я определенно не хочу загружать его все в память, а затем работать с ним.

Буду признателен за ваши предложения. Моя среда - VS 2008 и C# 3.5 SP1.

ответ

2

Ну, очевидно, вы можете сохранить имя + номер строки в словаре, но это не принесет вам никакой пользы.

Ну, конечно, это позволит вам узнать, какую строку начать читать, но проблема в том, где в файле находится эта строка? Единственный способ узнать - начать с начала и начать подсчет.

Лучшим способом было бы написать обертку, которая декодирует текстовое содержимое (если у вас есть проблемы с кодировкой) и может дать вам номер строки в байтовом типе сопоставления, тогда вы можете взять номер этой строки, 256 и посмотрите в словаре, чтобы узнать, что строка 256 начинается с позиции 10000 в файле и начинает читать оттуда.

Это одноразовая ситуация с обработкой? Если нет, считаете ли вы, что весь файл загружен в локальную базу данных, такую ​​как база данных SQLite? Это позволит вам иметь прямое сопоставление между номером строки и ее содержимым. Конечно, этот файл будет даже больше, чем ваш исходный файл, и вам нужно будет скопировать данные из текстового файла в базу данных, так что есть некоторые накладные расходы в любом случае.

+0

спасибо, я боялся, что мне придется предварительно обработать файл, прежде чем я начну работать с ним. Внешняя база данных для меня не является вариантом, так как файл данных слишком часто меняется для этого, так или иначе, спасибо за ваш ответ. –

+0

Вы можете лениться об этом и только выполнять предварительную обработку от начала до интересующей вас части. от 0 до этой точки будет .Seek(): возможно, и если вас интересуют более поздние части, вы можете продолжить предварительную обработку с того места, где вы остановились. Также сохраните индекс с отметкой времени и любой идентифицируемой информацией для последующего использования (или удалите ее при обновлении данных). –

+0

Мне нравится предложение Паси, спасибо! –

0

Просто прочитайте файл по одной строке за раз и проигнорируйте данные, пока не дойдете до тех, которые вам нужны. У вас не будет проблем с памятью, но производительность, вероятно, будет невелика. Вы можете сделать это легко в фоновом потоке.

+0

Наверное, неплохо было бы отсортировать требуемые разделы, определенные в заголовке по номеру строки, а затем прочитать их в этом порядке, так что нужен только один проход. –

0

Прочтите файл до конца заголовка, предполагая, что вы знаете, где это. Разделить строки вы хранящиеся на пробельном, например, так:

Dictionary<string, int> sectionIndex = new Dictionary<string, int>(); 
List<string> headers = new List<string>(); // fill these with readline 

foreach(string header in headers) { 
    var s = header.Split(new[]{' '}); 
    sectionIndex.Add(s[0], Int32.Parse(s[1])); 
} 

Найти словарную запись, которую вы хотите, сохранить подсчет количества прочитанных строк в файле, и цикл, пока вы не нажмете, что номер строки, а затем прочитайте, пока не дойдете до стартовой линии следующего раздела. Я не знаю, можете ли вы гарантировать порядок ключей в словаре, поэтому вам, вероятно, понадобятся имена текущего и следующего раздела.

Обязательно выполните некоторые проверки ошибок, чтобы убедиться, что раздел, который вы читаете, находится не до раздела, в котором вы читаете, и любых других случаев ошибок, о которых вы можете думать.

0

Вы можете читать строки за строкой, пока все данные заголовка не будут захвачены и не остановлены (при условии, что все указатели разделов находятся в заголовке).У вас будут номера разделов и строк для использования при получении данных позднее.

string dataRow = ""; 

try 
{ 
    TextReader tr = new StreamReader("filename.txt"); 

    while (true) 
    { 
     dataRow = tr.ReadLine(); 
     if (dataRow.Substring(1, 8) != "SECTION_") 
      break; 
     else 
      //Parse line for section code and line number and log values 
      continue; 
    } 
    tr.Close(); 
} 
catch (Exception ex) 
{ 
    MessageBox.Show(ex.Message); 
} 
3

Вы можете сделать это довольно легко.

В комплект поставки входят три части.

1) Как найти, где начинается строка в файле. Единственный способ сделать это - прочитать строки из файла, сохранив список, который записывает начальную позицию в файле этой строки. например

 
List lineMap = new List(); 
lineMap.Add(0); // Line 0 starts at location 0 in the data file (just a dummy entry) 
lineMap.Add(0); // Line 1 starts at location 0 in the data file 

using (StreamReader sr = new StreamReader("DataFile.txt")) 
{ 
    String line; 
    int lineNumber = 1; 
    while ((line = sr.ReadLine()) != null) 
     lineMap.Add(sr.BaseStream.Position); 
} 

2) Прочитайте и проанализируйте индексный файл в словаре.

 
Dictionary index = new Dictionary(); 

using (StreamReader sr = new StreamReader("IndexFile.txt")) 
{ 
    String line; 
    while ((line = sr.ReadLine()) != null) 
    { 
     string[] parts = line.Split(' '); // Break the line into the name & line number 
     index.Add(parts[0], Convert.ToInt32(parts[1])); 
    } 
} 

Затем найти строку в файле, используйте:

 
int lineNumber = index["SECTION_B";];   // Convert section name into the line number 
long offsetInDataFile = lineMap[lineNumber]; // Convert line number into file offset 

Затем откройте новый FileStream на DataFile.txt, Seek (offsetInDataFile, SeekOrigin.Begin), чтобы перейти к старту и используйте StreamReader (как указано выше) для чтения строк (строк) из него.

+0

+1 лучший ответ, чем мой – ajdams

Смежные вопросы