Как получить все индексы строк в большом файле? - PullRequest
1 голос
/ 08 октября 2011

Представьте себе, что есть очень большой HTML-файл с большим количеством HTML-тегов. Я не могу загрузить весь файл в память.

Мое намерение состоит в том, чтобы извлечь все индексы для этой <p> и этой </p> строк. Как мне этого добиться? Пожалуйста, предложите мне несколько способов сделать это.

Ответы [ 5 ]

3 голосов
/ 11 октября 2011

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

2 голосов
/ 13 октября 2011

Если ваш HTML является чистым XHTML, то вы можете рассматривать его как документ XML. Загрузите свой XHTML в System.Xml.XmlDocument и затем используйте метод GetElementsByTagName("p"), чтобы получить список

-tags. Это намного безопаснее и проще, чем пытаться разобрать html напрямую.

2 голосов
/ 12 октября 2011

Пример использования потоков файлов:

/// <summary>
/// Get a collection of index,string for everything inside p tags in the html file
/// </summary>
/// <param name="htmlFilename">filename of the html file</param>
/// <returns>collection of index,string</returns>
private Dictionary<long, string> GetHtmlIndexes(string htmlFilename)
{
    //init result
    Dictionary<long, string> result = new Dictionary<long, string>();

    StreamReader sr = null;
    try
    {
        sr = new StreamReader(htmlFilename);
        long offsetIndex = 0;
        while (!sr.EndOfStream)
        {

            string line = sr.ReadLine(); //assuming html isn't condensed into 1 single line
            offsetIndex += line.Length;  //assuming 'index' you require is the file offset
            int openingIndex = line.IndexOf(@"<p");
            int closingIndex = line.IndexOf(@">");
            if ( openingIndex > -1)
            {
                int contentIndex = openingIndex + 3; // as in <p tag or <p>tag
                string pTagContent = line.Substring( contentIndex);
                if(closingIndex> contentIndex)
                {
                    int tagLength = closingIndex - contentIndex;
                    pTagContent = line.Substring( contentIndex, tagLength);
                }
                //else, the tag finishes on next or subsequent lines and we only get content from this line

                result.Add(offsetIndex + contentIndex, pTagContent);
            }


        } //end file loop

    }
    catch (Exception ex)
    {
        //handle error ex
    }
    finally
    {
        if(sr!=null)
            sr.Close();
    }


    return result;
}

Это имеет ограничения, которые вы можете увидеть в комментариях. Я подозреваю, что использование LINQ будет намного аккуратнее. Я надеюсь, что это дает вам отправную точку?

2 голосов
/ 08 октября 2011

Вам следует попробовать Html Agility Pack .

1 голос
/ 18 октября 2011

Я бы начал с создания токенайзера HTML, который с использованием IEnumerable, yield return и т. Д. Был бы простым. Он может прочитать файл char-by-char, используя StreamReader.Read, и конечный автомат switch определит текущее состояние и выдаст последовательность токенов или Tuple с.

Я нашел старый HTML-токенайзер здесь (часть старого BlogX блогового движка Криса Андерсона), который можно было бы адаптировать для решения проблемы.

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