Re[2]: Ускорить чтение CSV файла.
От: Kore Sar  
Дата: 19.07.09 17:21
Оценка:
Здравствуйте, sn175, Вы писали:

S>А с через OleDb читать не пробовали?


Думаешь это будет быстрее.
Re[2]: Ускорить чтение CSV файла.
От: Kore Sar  
Дата: 19.07.09 17:23
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Вообщето у тебя не CSV

S>http://rsdn.ru/forum/dotnet/3303143.aspx
Автор: Serginio1
Дата: 24.02.09


Да-да. Но за ссылочку спасибо.
Re[3]: Ускорить чтение CSV файла.
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 19.07.09 17:33
Оценка:
Здравствуйте, Kore Sar, Вы писали:

Прочитал топик получше.
т.к. у тебя только разделитель, то читай сам напрямую.


   case StateEnum.FieldStart :    
            if ( Ch == Delimiter)

                aList.Add(string.Empty);

          else
           {
            State = StateEnum.ScanField;
            StartPos=Inx;
            }

          break;

     case StateEnum.ScanField :
        if ( Ch == Delimiter )
           {
     int  CopyCount=Inx-StartPos;
       aList.Add(S.Substring(StartPos,CopyCount));
            State = StateEnum.FieldStart;

          }
          break;




if (State == StateEnum.ScanField)
        {
       int    CopyCount=Inx-StartPos;
       aList.Add(S.Substring(StartPos,CopyCount));
        }


Так же можешь усложнить себе задачу и самому еще парсить строку из буфера, добавив
состояние на конец строки, с подгрузкой данных в буфер
и солнце б утром не вставало, когда бы не было меня
Re[3]: Ускорить чтение CSV файла.
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 19.07.09 17:51
Оценка:
Здравствуйте, Kore Sar, Вы писали:

KS>Здравствуйте, Serginio1, Вы писали:


S>>Вообщето у тебя не CSV

S>>http://rsdn.ru/forum/dotnet/3303143.aspx
Автор: Serginio1
Дата: 24.02.09


KS>Да-да. Но за ссылочку спасибо.

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

Используй BinaryWriter для записи и BinaryReader для чтения.
и солнце б утром не вставало, когда бы не было меня
Re[12]: Ускорить чтение CSV файла.
От: Kore Sar  
Дата: 19.07.09 17:56
Оценка:
Здравствуйте, samius, Вы писали:

KS>>Ой! Время чтения, конечно же, увеличивается.

KS>>Есть мысли почему так?

S>Read() — читает по одному символу, т.е. на каждый символ добавляется вызов. Наверное, речь не о нем.


Ессно.


S>Read(char[], Int32, Int32) — тут многое зависит от диапазона, с которым он вызывается. Навскидку не должен быть медленнее чем ReadLine().

Я тоже считаю, что не должен быть медленнее.

Всё, спасибо, разобрался. Буду писать свой ReadLine.
Re[4]: Ускорить чтение CSV файла.
От: Kore Sar  
Дата: 19.07.09 18:02
Оценка:
Здравствуйте, Serginio1, Вы писали:

S> Так же можешь усложнить себе задачу и самому еще парсить строку из буфера, добавив

S>состояние на конец строки, с подгрузкой данных в буфер

Вот эти и занимаюсь щас.
Re[4]: Ускорить чтение CSV файла.
От: Kore Sar  
Дата: 19.07.09 18:06
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Здравствуйте, Kore Sar, Вы писали:


KS>>Здравствуйте, Serginio1, Вы писали:


S>>>Вообщето у тебя не CSV

S>>>http://rsdn.ru/forum/dotnet/3303143.aspx
Автор: Serginio1
Дата: 24.02.09


KS>>Да-да. Но за ссылочку спасибо.

S> Если это твой формат данных, то проще сделать аналог бинарной сериализации.
S>Если количество колононок одинаково, то записывать сначала длину строки, потом строку.
S>Если количество колонок не одинаково, то сначала записываем количество колонок потом строки.
S> Это будет значительно быстрее чем парсинг.

S>Используй BinaryWriter для записи и BinaryReader для чтения.


Данные приходят с линкус-сервера, который написан на С++.
Всё это проектировали не мы, нам досталось по наследству. Я бы конечно сделал хранилище бинарным, будь на то моя воля.
Re[5]: Ускорить чтение CSV файла.
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 19.07.09 18:21
Оценка:
Здравствуйте, Kore Sar, Вы писали:

KS>Данные приходят с линкус-сервера, который написан на С++.

KS>Всё это проектировали не мы, нам досталось по наследству. Я бы конечно сделал хранилище бинарным, будь на то моя воля.
Сочувствую. Если строки не превышают определенный размер Например кэш процессора, то лучше использовать кольцевой буфер,
либо со сдвигом остатка строки в начало при достижении конца строки. Алгоритмы достаточно просты. Со сдвигом немного проще,
и корректировать начало строки
и солнце б утром не вставало, когда бы не было меня
Re[6]: Ускорить чтение CSV файла.
От: Kore Sar  
Дата: 19.07.09 19:06
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Здравствуйте, Kore Sar, Вы писали:


KS>>Данные приходят с линкус-сервера, который написан на С++.

KS>>Всё это проектировали не мы, нам досталось по наследству. Я бы конечно сделал хранилище бинарным, будь на то моя воля.
S> Сочувствую. Если строки не превышают определенный размер Например кэш процессора, то лучше использовать кольцевой буфер,
S>либо со сдвигом остатка строки в начало при достижении конца строки. Алгоритмы достаточно просты. Со сдвигом немного проще,
S>и корректировать начало строки
И это всё под дотнетом? Или речь уже о unmanaged?
Re[7]: Ускорить чтение CSV файла.
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 19.07.09 19:36
Оценка:
Здравствуйте, Kore Sar, Вы писали:

KS>И это всё под дотнетом? Или речь уже о unmanaged?

Конечно под дотнетом. Разница в скорости минимальна.
Единственно, что скорее всего у тебя данные в кодировке 1251, то искать побайтно, а считывать строку через энкодер.
и солнце б утром не вставало, когда бы не было меня
Re[8]: Ускорить чтение CSV файла.
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 19.07.09 19:52
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Здравствуйте, Kore Sar, Вы писали:


KS>>И это всё под дотнетом? Или речь уже о unmanaged?

S> Конечно под дотнетом. Разница в скорости минимальна.
S> Единственно, что скорее всего у тебя данные в кодировке 1251, то искать побайтно, а считывать строку через энкодер.
Еще можно использовать BitArray Что бы отсеивать символы ',' и '\r' и '\n'
и солнце б утром не вставало, когда бы не было меня
Re[3]: Ускорить чтение CSV файла.
От: Muxa  
Дата: 20.07.09 04:51
Оценка:
else
 break;

Re[5]: Ускорить чтение CSV файла.
От: Аноним  
Дата: 20.07.09 05:08
Оценка:
Здравствуйте, Kore Sar, Вы писали:

KS>Данные приходят с линкус-сервера, который написан на С++.

KS>Всё это проектировали не мы, нам досталось по наследству. Я бы конечно сделал хранилище бинарным, будь на то моя воля.

Доброе ....

Что вы делаете с этими данными? Если льете в базу — посмотрите в сторону bulk...

--
Re[6]: Ускорить чтение CSV файла.
От: Kore Sar  
Дата: 20.07.09 07:47
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Kore Sar, Вы писали:


KS>>Данные приходят с линкус-сервера, который написан на С++.

KS>>Всё это проектировали не мы, нам досталось по наследству. Я бы конечно сделал хранилище бинарным, будь на то моя воля.

А>Доброе ....


А>Что вы делаете с этими данными? Если льете в базу — посмотрите в сторону bulk...


Не льём. Мы их считаем. Статистика и всё такое...
Re[9]: Ускорить чтение CSV файла.
От: Kore Sar  
Дата: 20.07.09 07:51
Оценка:
Здравствуйте, Serginio1, Вы писали:

S>Здравствуйте, Serginio1, Вы писали:


S>>Здравствуйте, Kore Sar, Вы писали:


KS>>>И это всё под дотнетом? Или речь уже о unmanaged?

S>> Конечно под дотнетом. Разница в скорости минимальна.
S>> Единственно, что скорее всего у тебя данные в кодировке 1251, то искать побайтно, а считывать строку через энкодер.
S> Еще можно использовать BitArray Что бы отсеивать символы ',' и '\r' и '\n'

У меня пробел в знаниях.
Что это? — "использовать кольцевой буфер, либо со сдвигом остатка строки в начало при достижении конца строки"
Можно ссылками.


И, да, я уже говорил, что у нас чистый ASCII. Никаких 1251.
Re[7]: Ускорить чтение CSV файла.
От: Аноним  
Дата: 20.07.09 08:11
Оценка:
Здравствуйте, Kore Sar, Вы писали:

А>>Доброе ....


А>>Что вы делаете с этими данными? Если льете в базу — посмотрите в сторону bulk...


KS>Не льём. Мы их считаем. Статистика и всё такое...


Доброе ...
Для объемов данных, которые вы представили — имхо имеет смысл обратить взор в сторону субд...
Oracle (sqlldr) и MsSql (bcp) — имеют средства для массовых вставок ...
Для бесплатных субд можно посмотреть наличие этой опции...
Опять таки функционал по агрегации есть в самой субд ...

Я так понимаю у вас руки не связаны по постобработке предоставленных файлов csv ...

--
Re[8]: Ускорить чтение CSV файла.
От: Kore Sar  
Дата: 20.07.09 08:33
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Kore Sar, Вы писали:


А>>>Доброе ....


А>>>Что вы делаете с этими данными? Если льете в базу — посмотрите в сторону bulk...


KS>>Не льём. Мы их считаем. Статистика и всё такое...


А>Доброе ...

А>Для объемов данных, которые вы представили — имхо имеет смысл обратить взор в сторону субд...
А>Oracle (sqlldr) и MsSql (bcp) — имеют средства для массовых вставок ...
А>Для бесплатных субд можно посмотреть наличие этой опции...
А>Опять таки функционал по агрегации есть в самой субд ...

А>Я так понимаю у вас руки не связаны по постобработке предоставленных файлов csv ...


У нас Оракл. И мы вот уже второй год уговариваем наших менеджеров (которые сидят далеко за бугром) сделать аггрегирование данных прямо в СУБД.
Но, т.к. это займёт уж очень много времени, то мы этого не делаем.

ПС: хватит троеточия ставить, рябит в глазах.
Re[10]: Ускорить чтение CSV файла.
От: Ziaw Россия  
Дата: 20.07.09 09:16
Оценка:
Здравствуйте, Kore Sar, Вы писали:

KS>У меня пробел в знаниях.

KS>Что это? — "использовать кольцевой буфер, либо со сдвигом остатка строки в начало при достижении конца строки"
KS>Можно ссылками.

Простейший и быстрейший парсер CSV в ASCII будет выглядеть примерно так: (обработка ошибок здесь отсутствует в принципе)
        static IEnumerable<byte[][]> ParseCSV(byte[] data, int fieldCount)
        {
            int[] fieldPositions = new int[fieldCount + 1];

            var currentField = 0;
            var comma = toByte(',');
            var cr = toByte('\n');


            fieldPositions[currentField++] = 0;

            for (var position = 0; position < data.Length; position++)
            {
                var sym = data[position];
                
                if (sym == comma)
                {
                    fieldPositions[currentField++] = position + 1; // skip ','
                }
                else if (sym == cr)
                {
                    byte[][] result = new byte[fieldCount][];
                    fieldPositions[currentField] = position;
                    for (int i = 0; i < fieldCount; i++)
                    {
                        var length = fieldPositions[i + 1] - fieldPositions[i] - 1;
                        var field = new byte[length];
                        Array.Copy(data, fieldPositions[i], field, 0, length);
                        result[i] = field;
                    }
                    currentField = 0;
                    fieldPositions[currentField++] = position + 1; // skip lf
                    yield return result;
                }
            }
        }

        private static byte toByte(char c)
        {
            return Encoding.ASCII.GetBytes(new[] {c})[0];
        }

        static void Main(string[] args)
        {
            var testCsv = @"1,3,4,5
6, 7, 8, 9
10a, 123 bb b , sadfasdf , asdfsadf
";
            var testData = Encoding.ASCII.GetBytes(testCsv);

            foreach (var row in ParseCSV(testData, 4))
            {
                Console.WriteLine("Row -> {0}", 
                    String.Join(":", row.Select(b => Encoding.ASCII.GetString(b)).ToArray()));
            }
        }


Для работы с потоком нужно работать не со всеми данными, а с буфером. Для этого требуется чтобы одно поле всегда находилось в буфере полностью либо склеивать его из кусочков. Для первого случая применяется кольцевой буфер, он требует больше памяти чем обычный (как минимум maxFieldSize * 2), данные читаются в него кусками по maxFieldSize поочередно в первую и вторую половину. При работе с кольцевым буфером алгоритм почти не требует переделки, кроме адресации данных (вместо position используем position % buffer.Length) и обработки ситуации где начало поля в конце буфера, а конец в начале.
... << RSDN@Home 1.2.0 alpha 4 rev. 1228>>
Re[10]: Ускорить чтение CSV файла.
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 20.07.09 09:22
Оценка:
Здравствуйте, Kore Sar, Вы писали:
S>> Еще можно использовать BitArray Что бы отсеивать символы ',' и '\r' и '\n'

KS>У меня пробел в знаниях.

KS>Что это? — "использовать кольцевой буфер, либо со сдвигом остатка строки в начало при достижении конца строки"
KS>Можно ссылками.


KS>И, да, я уже говорил, что у нас чистый ASCII. Никаких 1251.

Кольцевой буфер это фиксированный массив где индекс начало строки может быть больше индекса конца строки.
Пример Queue.
При достижении конца считанных данных, новые данные считываются до конца буфера и с начало буфера до начала строки.
Сдвиг остатка строки в начало, тоже использует, фиксированный массив, но для того что бы начало строки было всегда меньше конца,
То есть при достижении конца буфера, неполная строка сдвигается в начало и данные считываются от конца строки в конец буфера.

Тогда проще модифицировать StreamReader.readLine, но обрабатывать байты а не чары с использованием BitArray.

Ссылок уже и не помню.
Вот пример кольцевого буфера правда на Delphi


unit TextReader;

interface
 Uses Classes,SysUtils;
 Const TextBuferSize=$10000;
       TextBuferSizeMaxIndex=TextBuferSize-1;
  Type
 TTextReader= Class
  Private
   FStream:Tstream;
   Buffer:Array[0..TextBuferSizeMaxIndex] of char;
   DelemiterSet:Set of Char;
   EndBuffer,BeginString,EndString,CurrentPos:Integer;
   FEof:Boolean;

   Protected
   Procedure CheckDelemiter;
   Function GetCurrentString:String;
   Procedure ReadFromStream;
   Function CanRead:Boolean;
  public
   Constructor Create(FileName:String);
   Destructor Destroy; override;
   Procedure Readln;
   Property CurrentString:String read GetCurrentString;
   Property Eof:Boolean read FEOF;
 end;
implementation

{ TTextReader }

function TTextReader.CanRead: Boolean;
begin
 Result:= FStream.Position<Fstream.Size;
end;

procedure TTextReader.CheckDelemiter;
begin
 //If CurrentPos=EndBuffer
end;

constructor TTextReader.Create(FileName: String);
begin
 Fstream:=TFileStream.Create(FileName,fmOpenRead or fmShareDenyWrite);
 EndBuffer:= Fstream.Read(buffer[0],TextBuferSize)-1;
 FeOf:=(EndBuffer=-1);
  If Not FEof Then
   FEof:=(buffer[0]=#0);
 DelemiterSet:=[#0,#10,#13];
 BeginString:=0;
 EndString:=0;
 CurrentPos:=0;
end;

destructor TTextReader.Destroy;
begin
 If Assigned(Fstream) Then Fstream.Free;
  inherited;
end;

function TTextReader.GetCurrentString: String;

  Begin
  If  BeginString=-1 Then
  Begin
      Result:='';
      Exit;
    end;
//     If EndString=BeginString Then
//      Result:=buffer[EndString]
 //     else
    If EndString>=BeginString
      Then
      Begin
      SetLength(Result,EndString-BeginString+1);
      Move(buffer[BeginString],Result[1],Length(Result));
      end
      Else
        Begin
       SetLength(Result,TextBuferSize-BeginString+EndString+1);
   //    FillChar(result[1],Length(Result),0);
       Move(buffer[BeginString],result[1],TextBuferSize-BeginString);
       Move(buffer[0],result[TextBuferSize-BeginString+1],EndString+1);
        end;
  end;



procedure TTextReader.ReadFromStream;
begin
  If  BeginString=-1 Then
    Begin

    EndBuffer:=Fstream.Read(buffer[0],TextBuferSize)-1;
    CurrentPos:=0;
    Exit
     end;

     //-------------------
       If  EndBuffer=TextBuferSizeMaxIndex Then
        Begin
         If BeginString=0 Then Raise Exception.Create('Слишком длинная строка');
          EndBuffer:= Fstream.Read(buffer[0],BeginString)-1;
        end
     //-------------------
        else If BeginString<=EndBuffer Then
     //---------------------------
      Begin
      EndBuffer:=EndBuffer+ Fstream.Read(buffer[EndBuffer+1],TextBuferSize-EndBuffer-1);


      end
     //---------------------------
      else
       //------------------------------------------
         Begin
         If BeginString=(EndBuffer+1) Then Raise Exception.Create('Слишком длинная строка');
        EndBuffer:=EndBuffer+Fstream.Read(buffer[EndBuffer+1],BeginString-EndBuffer-1);
          end;
       //------------------------------------------

end;

procedure TTextReader.Readln;
begin
    BeginString:=-1;
   If Not (Buffer[CurrentPos]  in  DelemiterSet) Then
    BeginString:=CurrentPos;

 While Not (Buffer[CurrentPos]  in  DelemiterSet) Do
  Begin
   If CurrentPos=EndBuffer Then
    ReadFromStream;
    CurrentPos:=(CurrentPos+1) mod TextBuferSize;
    End;

      If CurrentPos=0 Then
      EndString:=TextBuferSizeMaxIndex
       else
       EndString:=CurrentPos-1;


        If Buffer[CurrentPos]=#0 Then
         Begin
          FEof:=True;
          exit;
         End;


        If CurrentPos=EndBuffer Then
         //----------------------------------
          If self.CanRead Then
           Begin
           ReadFromStream;
           end
          Else
          Begin
          FEof:=True;
          exit
         end;

        CurrentPos:=(CurrentPos+1) mod TextBuferSize;


         If Buffer[CurrentPos]= #10 then
          Begin
         If CurrentPos=EndBuffer Then
         //----------------------------------
          If self.CanRead Then
           Begin
           ReadFromStream;
           end
          Else
          Begin
          FEof:=True;
          exit
         end;

        CurrentPos:=(CurrentPos+1) mod TextBuferSize;

        If Buffer[CurrentPos]=#0 Then
         Begin
          FEof:=True;
          exit;
         End;


       end;



end;

end.
и солнце б утром не вставало, когда бы не было меня
Re[11]: Ускорить чтение CSV файла.
От: Kore Sar  
Дата: 20.07.09 09:59
Оценка:
Здравствуйте, Serginio1, Вы писали:

S> Тогда проще модифицировать StreamReader.readLine, но обрабатывать байты а не чары с использованием BitArray.

Про буфер ясно. А вот чем тут поможет BitArray и как его заюзать — это не ясно.
(И, да, я знаю что такое BitArray.)
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.