Как прочитать большой XML-файл, не загружая его в памяти и с помощью XElement

Я хочу прочитать большой XML-файл (100+M). Из-за его размера, я не хочу загружать его в памяти с помощью XElement. Я использую запросы linq-xml, чтобы проанализировать и считать его.

Что лучший способ состоит в том, чтобы сделать это? Какой-либо пример на комбинации XPath или XmlReader с linq-xml/XElement?

Помогите.Спасибо.

6
задан Jon Seigel 14 March 2010 в 19:59
поделиться

2 ответа

Да, вы можете объединить XmlReader с методом XNode.ReadFrom, смотрите пример в документации, который использует C# для выборочной обработки узлов, найденных XmlReader, как XElement.

8
ответ дан 8 December 2019 в 16:02
поделиться

Если вы используете boost, вы можете использовать thread:: sleep function:

#include <boost/thread/thread.hpp>
boost::system_time time = boost::get_system_time();
time += boost::posix_time::seconds(1);
boost::thread::sleep(time); 

В противном случае вам придется использовать win32 api:

#include <windows.h>
Sleep(1000);

И, видимо, C++ 0x включает в себя следующее:

#include <thread>
std::this_thread::sleep_for(chrono::seconds(1));
-121--1720599-

Я решил попробовать что-то сам. Я придумал простой код GDI +, который использует плитки, которые у меня уже есть. Я просто отфильтровываю детали, релевантные для текущей области отсечения. Это работает как магия! Пожалуйста, найдите мой код ниже. (Параметры формы: двойная буферизация для наилучших результатов)

 protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);
        Graphics dc = e.Graphics;
        dc.ScaleTransform(1.0F, 1.0F);
        Size scrollOffset = new Size(AutoScrollPosition);

        int start_x = Math.Min(matrix_x_size, 
                             (e.ClipRectangle.Left - scrollOffset.Width) / 256);
        int start_y = Math.Min(matrix_y_size, 
                             (e.ClipRectangle.Top - scrollOffset.Height) / 256);
        int end_x = Math.Min(matrix_x_size, 
                        (e.ClipRectangle.Right - scrollOffset.Width + 255) / 256);
        int end_y = Math.Min(matrix_y_size, 
                      (e.ClipRectangle.Bottom - scrollOffset.Height + 255) / 256);

        // start * contain the first and last tile x/y which are on screen 
        // and which need to be redrawn.
        // now iterate trough all tiles which need an update 
        for (int y = start_y; y < end_y; y++)
            for (int x = start_x; x < end_x; x++)
            {  // draw bitmap with gdi+ at calculated position.
                dc.DrawImage(BmpMatrix[y, x], 
                           new Point(x * 256 + scrollOffset.Width, 
                                     y * 256 + scrollOffset.Height));
            }
    }

Для ее тестирования создана матрица 80x80 из 256 плиток (420 MPixel). Конечно, мне придется добавить отложенную нагрузку в реальной жизни. Я могу оставить плитки (пустыми), если они еще не загружены. На самом деле, я попросил моего клиента воткнуть 8 Гбайт в его машину, чтобы не беспокоиться о производительности слишком много. После загрузки плитка может оставаться в памяти.

public partial class Form1 : Form
{
    bool dragging = false;
    float Zoom = 1.0F;
    Point lastMouse;
    PointF viewPortCenter;

    private readonly Brush solidYellowBrush = new SolidBrush(Color.Yellow);
    private readonly Brush solidBlueBrush = new SolidBrush(Color.LightBlue);
    const int matrix_x_size = 80;
    const int matrix_y_size = 80;
    private Bitmap[,] BmpMatrix = new Bitmap[matrix_x_size, matrix_y_size];
    public Form1()
    {
        InitializeComponent();

        Font font = new Font("Times New Roman", 10, FontStyle.Regular);
        StringFormat strFormat = new StringFormat();
        strFormat.Alignment = StringAlignment.Center;
        strFormat.LineAlignment = StringAlignment.Center;
        for (int y = 0; y < matrix_y_size; y++)
            for (int x = 0; x < matrix_x_size; x++)
            {
                BmpMatrix[y, x] = new Bitmap(256, 256, PixelFormat.Format24bppRgb);
                //                    BmpMatrix[y, x].Palette.Entries[0] = (x+y)%1==0?Color.Blue:Color.White;

                using (Graphics g = Graphics.FromImage(BmpMatrix[y, x]))
                {
                    g.FillRectangle(((x + y) % 2 == 0) ? solidBlueBrush : solidYellowBrush, new Rectangle(new Point(0, 0), new Size(256, 256)));
                    g.DrawString("hello world\n[" + x.ToString() + "," + y.ToString() + "]", new Font("Tahoma", 8), Brushes.Black,
                        new RectangleF(0, 0, 256, 256), strFormat);
                    g.DrawImage(BmpMatrix[y, x], Point.Empty);
                }
            }

        BackColor = Color.White;

        Size = new Size(300, 300);
        Text = "Scroll Shapes Correct";

        AutoScrollMinSize = new Size(256 * matrix_x_size, 256 * matrix_y_size);
    }   

Оказался, что это было легкой частью. Получения async многопоточный i/o, сделанный на заднем плане, было намного более трудно достигнуть. Тем не менее, я работаю в описанном здесь пути. Проблемы, которые необходимо решить, были связаны с многопоточностью .NET/Form больше, чем с этим разделом.

В псевдокоде он работает так:

after onPaint (and on Tick)
   check if tiles on display need to be retrieved from disc
       if so: post them to an async io queue
       if not: check if tiles close to display area are already loaded
           if not: post them to an async io/queue
   check if bitmaps have arrived from io thread
      if so: updat them on screen, and force repaint if visible

Результат: теперь у меня есть собственный Пользовательский контроль, который использует примерно 50 Мбайт для очень быстрого доступа к файлам произвольного размера (мозаичным) TIFF.

-121--1930378-

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

1
ответ дан 8 December 2019 в 16:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: