Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > .NET Frameworks (точка нет фреймворки) > C# (си шарп)
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 05.04.2012, 13:52   #1
ShamanK
Пользователь
 
Регистрация: 16.10.2009
Сообщений: 90
По умолчанию Работа с большими файлами.

Доброго времени суток!
я самоучка, и столкнулся с проблемой организации работы с достаточно крупными текстовыми файлами, размером около 80мгб (этот размер чуть ниже среднего, может достигать и гб) вот в таком виде:

Цитата:
...
6EM2 03/19/2012 14:40:07 1.3166 4 1.3166 1.3167
6EM2 03/19/2012 14:40:07 1.3166 1 1.3166 1.3167
6EM2 03/19/2012 14:40:07 1.3166 3 1.3166 1.3167
6EM2 03/19/2012 14:40:07 1.3166 5 1.3166 1.3167
...
необходимо его распарсить и внести в массив (использую LIST) для дальнейшей работы над данными.

класс в котором производится парсинг:

PHP код:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
namespace 
AMDTM
{
    class 
tickdata
    
{
        public 
DateTime Tm;
        public 
int sz;
        public 
double PrAskBid;
        public 
tickdata(string tmmstring laststring lastszstring bdstring ass)
        {
            try { 
this.Tm DateTime.Parse(tmm, new CultureInfo("en-US"false)); }
            catch (
FormatException) { }

            
this.Pr Convert.ToDouble(last);//.Replace(".", ","));
            
this.sz Convert.ToInt32(lastsz);//.Replace(".", ","));
            
this.Bid Convert.ToDouble(bd);//.Replace(".", ","));
            
this.Ask Convert.ToDouble(ass);//.Replace(".", ","));
        
}
    }

в коде программы считываю файл построчно и записываю в ЛИСТ:

PHP код:
List<tickdatadttk = new List<tickdata>();
...
            private 
void readTD()
            {
                
DateTime tm1 DateTime.Now;
                
int cnn 0;
                
string nameFile "C:\\Tiks\\222.txt";
                try
                {
                    
using (StreamReader sr = new StreamReader(nameFile))
                    {
                        
string line;

                        while ((
line sr.ReadLine()) != null)
                        {
                            var 
arr line.Split('\t');

                            if (
arr[5] != "ASK" && arr[5] !="")
                                {
                                    
dttk.Add(new tickdata(arr[1], arr[2], arr[3], arr[4], arr[5]));
                                    
cnn++; lb1.Text cnn.ToString();
                                }
                        }
                        
lb1.Text cnn.ToString();
                        
DateTime tm2 DateTime.Now;
                        
lb4.Text tm1.ToString();
                        
lb5.Text tm2.ToString();
                    }
                }
                catch (
Exception e)  {   }
            } 
в lb4 и lb5 вношу разницу во времени до и после прочтения файла.
в lb1 вношу счетчик строк.

запускаю процесс нажатием на кнопку
PHP код:
            private void button1_Click(object senderEventArgs e)
            {
                
lb3.Text "Считываю Данные";
                
readTD();
            } 
в результате получается вот так:



1 691 197 строк
время выполнения 8 минут 10 секунд.
во время чтения файла программа подвисает

вопросы:
1 - в цикле чтения файла у меня стоит отображение количества строк
PHP код:
lb1.Text cnn.ToString(); 
но все висит и ничего не отображается..
такая же строчка стоит ВНЕ цикла, и она после чтения отображает количество строк - как сделать так, чтобы количество прочтенных строк отображалось во время чтения файла?

2 - как вообще сделать так, чтобы во время чтения файла программа не подвисала?
в коде кнопки сначала прописывал так:

PHP код:
       private void button1_Click(object senderEventArgs e)
            {
                
lb3.Text "Считываю Данные";

                
Thread t = new Thread(new ThreadStart(readTD));
                
t.Start();
            } 
тогда при нажатии на кнопку программа не виснет, но ничего и не происходит. даже если скормить файл в 10 килобайт ничего не происходит.

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

4 - правильно ли ВЕСЬ объем информации вносить в массив при условии что для расчетов мне понадобится только часть данных? часть данных находится по времени, если один раз внести в массив только часть данных, то при изменении временных параметров опять прийдется парсить весь файл чтобы получить даные с другого временного отрезка.

5 - правильно ли вообще вносить эти данные в массив? может правильней всего было бы занести в базу данных? если да, то подскажите литературу по работе с БД для полных чайников. желательно с примерами ))

заранее благодарю, с уважением.
ShamanK вне форума Ответить с цитированием
Старый 05.04.2012, 14:23   #2
Serge_Bliznykov
Старожил
 
Регистрация: 09.01.2008
Сообщений: 26,229
По умолчанию

во-первых, Вы в цикл засунули кучу присвоений визуальным компонентам.
Вы думаете, это ускоряет цикл?!!! Гарантирую - с точностью до наоборот!

выбрасывайте всё лишнее!

во-вторых, чтобы программа в цикле "не подвисала", добавьте обработку системных сообщений.
ну, например так:
Код:
                        lb1.Text = cnn.ToString(); 
                        DateTime tm2 = DateTime.Now; 
                        lb4.Text = tm1.ToString(); 
                        lb5.Text = tm2.ToString();
                        Application.DoEvents();
в третьих, чтобы ускорить обработку, нужно "вылизать" процедуру парсинга!
а то, что программа работает с этим файлом в реальном времени, так она же не читает ЕГО ПОЛНОСТЬЮ и не разбирает КАЖДУЮ строчку. Дописывает строчки в конец файла. - это будет очень быстро даже для Гб файла. в отличии от построчного чтения и разбора.

в-чётвёртых, я бы построчное чтение заменил на System.IO.File.ReadAllText(pathFile Lab2);

Последний раз редактировалось Serge_Bliznykov; 05.04.2012 в 14:25.
Serge_Bliznykov вне форума Ответить с цитированием
Старый 05.04.2012, 15:54   #3
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

Цитата:
в-чётвёртых, я бы построчное чтение заменил на System.IO.File.ReadAllText(pathFile Lab2);
я бы не стал, так как если размер файла может быть большим то плохо кончиться
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 05.04.2012, 16:08   #4
ShamanK
Пользователь
 
Регистрация: 16.10.2009
Сообщений: 90
По умолчанию

Цитата:
Сообщение от Serge_Bliznykov Посмотреть сообщение
во-первых, Вы в цикл засунули кучу присвоений визуальным компонентам.
Вы думаете, это ускоряет цикл?!!! Гарантирую - с точностью до наоборот!

выбрасывайте всё лишнее!

во-вторых, чтобы программа в цикле "не подвисала", добавьте обработку системных сообщений.

в третьих, чтобы ускорить обработку, нужно "вылизать" процедуру парсинга!
а то, что программа работает с этим файлом в реальном времени, так она же не читает ЕГО ПОЛНОСТЬЮ и не разбирает КАЖДУЮ строчку. Дописывает строчки в конец файла. - это будет очень быстро даже для Гб файла. в отличии от построчного чтения и разбора.

в-чётвёртых, я бы построчное чтение заменил на System.IO.File.ReadAllText(pathFile Lab2);
сделал как вы сказали :

PHP код:
          private void readTD()
            {
                
DateTime tm1 DateTime.Now;
                
int cnn 0;
                
string nameFile "C:\\Tiks\\222.txt";

                
string readText File.ReadAllText(nameFile);

                
string[] lines Regex.Split(readText"\r\n");
                foreach (
string line in lines)
                    {
                        if (
line != "" )
                        {
                            var 
arr line.Split('\t');
                            if (
arr[5] != "ASK" && arr[5] != "")
                                {
                                    
dttk.Add(new tickdata(arr[1], arr[2], arr[3], arr[4], arr[5]));
                                    
cnn++;
                                }
                     
                        }
                    }
                
lb1.Text cnn.ToString();
                
DateTime tm2 DateTime.Now;
                
lb4.Text tm1.ToString();
                
lb5.Text tm2.ToString();
            } 
время чтения и парсинга файла сократилось до 4 минут 29 секунд, тоесть вдвое.

что вы имели в виду - "вылизать" парсинг? не подскажете?
ShamanK вне форума Ответить с цитированием
Старый 05.04.2012, 17:11   #5
Скарам
Дружите с Linq ;)
Форумчанин
 
Аватар для Скарам
 
Регистрация: 15.10.2008
Сообщений: 822
По умолчанию

Попробуй еще распараллелить. Измени код так:
Код:
private void readTD() 
            { 
                DateTime tm1 = DateTime.Now; 
                int cnn = 0; 
                string nameFile = "C:\\Tiks\\222.txt"; 

                string readText = File.ReadAllText(nameFile); 

                string[] lines = Regex.Split(readText, "\r\n"); 
                 System.Threading.Tasks.Parallel.ForEach(lines, line =>
                { 
                        if (line != "" ) 
                        { 
                            var arr = line.Split('\t'); 
                            if (arr[5] != "ASK" && arr[5] != "") 
                                { 
                                    dttk.Add(new tickdata(arr[1], arr[2], arr[3], arr[4], arr[5])); 
                                    cnn++; 
                                } 
                      
                        } 
                    } );
                lb1.Text = cnn.ToString(); 
                DateTime tm2 = DateTime.Now; 
                lb4.Text = tm1.ToString(); 
                lb5.Text = tm2.ToString(); 
            }
Не тестировал, но должно работать, отпиши о результатах.
Не давай организму поблажки, каждый день тренируй его в шашки..
Скарам вне форума Ответить с цитированием
Старый 05.04.2012, 17:39   #6
ShamanK
Пользователь
 
Регистрация: 16.10.2009
Сообщений: 90
По умолчанию

Цитата:
Сообщение от Скарам Посмотреть сообщение
Попробуй еще распараллелить. Измени код так:
Не тестировал, но должно работать, отпиши о результатах.
так получилось несколько хуже - длительность 6 минут.
загрузка процессора до 90 процентов, памяти заняло 500 мгб.
ShamanK вне форума Ответить с цитированием
Старый 05.04.2012, 17:42   #7
Скарам
Дружите с Linq ;)
Форумчанин
 
Аватар для Скарам
 
Регистрация: 15.10.2008
Сообщений: 822
По умолчанию

Странно, скинь демо проект и файл, профайлером гляну что и как там.
Не давай организму поблажки, каждый день тренируй его в шашки..
Скарам вне форума Ответить с цитированием
Старый 05.04.2012, 17:46   #8
ShamanK
Пользователь
 
Регистрация: 16.10.2009
Сообщений: 90
По умолчанию

Цитата:
Сообщение от Скарам Посмотреть сообщение
Странно, скинь демо проект и файл, профайлером гляну что и как там.
куда скинуть?
ShamanK вне форума Ответить с цитированием
Старый 05.04.2012, 17:53   #9
ShamanK
Пользователь
 
Регистрация: 16.10.2009
Сообщений: 90
По умолчанию

Цитата:
Сообщение от Скарам Посмотреть сообщение
Странно, скинь демо проект и файл, профайлером гляну что и как там.
вот архив проекта и самого файла.
проект как есть.
вочеры закомментированы, работает только чтение файла.
Вложения
Тип файла: rar AMDTM.rar (2.27 Мб, 40 просмотров)
ShamanK вне форума Ответить с цитированием
Старый 05.04.2012, 19:00   #10
m0nax
Форумчанин
 
Аватар для m0nax
 
Регистрация: 25.09.2009
Сообщений: 525
По умолчанию

убери из tickdata кусок с try-catch для даты
оставь только это
Код:
        public tickdata(string tmm, string last, string lastsz, string bd, string ass)
        {
            this.Tm = DateTime.Parse(tmm);
            this.Pr = Convert.ToDouble(last);//.Replace(".", ","));
            this.sz = Convert.ToInt32(lastsz);//.Replace(".", ","));
            this.Bid = Convert.ToDouble(bd);//.Replace(".", ","));
            this.Ask = Convert.ToDouble(ass);//.Replace(".", ","));
        }
чтоб оно работало используй это
Код:
                Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
читается 6 секунд.
m0nax вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Работа с большими числами tae1980 Microsoft Office Excel 3 25.12.2010 20:41
C++ Работа с большими числами airwind Помощь студентам 4 08.12.2010 15:26
Работа с большими числами в Дельфи motorway Общие вопросы Delphi 5 02.05.2010 02:14
Работа с большими числами SanekIrk Общие вопросы Delphi 3 11.07.2008 22:11
работа с большими числами sasadabest Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM 2 16.10.2007 10:51