На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! ПРАВИЛА РАЗДЕЛА · FAQ раздела Delphi · Книги по Delphi
Пожалуйста, выделяйте текст программы тегом [сode=pas] ... [/сode]. Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля.
Следующие вопросы задаются очень часто, подробно разобраны в FAQ и, поэтому, будут безжалостно удаляться:
1. Преобразовать переменную типа String в тип PChar (PAnsiChar)
2. Как "свернуть" программу в трей.
3. Как "скрыться" от Ctrl + Alt + Del (заблокировать их и т.п.)
4. Как прочитать список файлов, поддиректорий в директории?
5. Как запустить программу/файл?
... (продолжение следует) ...

Вопросы, подробно описанные во встроенной справочной системе Delphi, не несут полезной тематической нагрузки, поэтому будут удаляться.
Запрещается создавать темы с просьбой выполнить какую-то работу за автора темы. Форум является средством общения и общего поиска решения. Вашу работу за Вас никто выполнять не будет.


Внимание
Попытки открытия обсуждений реализации вредоносного ПО, включая различные интерпретации спам-ботов, наказывается предупреждением на 30 дней.
Повторная попытка - 60 дней. Последующие попытки бан.
Мат в разделе - бан на три месяца...
Модераторы: jack128, D[u]fa, Shaggy, Rouse_
Страницы: (2) [1] 2  все  ( Перейти к последнему сообщению )  
> Перемешивание строк / Delphi/RAD XE4
    Ребята как переделать вот этот код - под чтение построчно. Что бы не загружать в память.
    ExpandedWrap disabled
      var
        s: TStringList;
        z, p, q: Integer;
      begin
        s := TStringList.Create;
        s.LoadFromFile('C:\text.txt');
        z := 50;
        while (z > 0) do begin
          p := random(s.Count); q := random(s.Count);
          s.Exchange(p, q);
          dec(z);
        end;
        s.SaveToFile('c:\text.txt');
        s.Free;
      end;


    Начал переделывать вот так (но вот в регуляровкой рандом не дружу):

    ExpandedWrap disabled
      var
          z, p, q: Integer;
          ft, ft2: TextFile;
          s:string;
       
      begin
        if OpenDialog1.Execute then begin
        AssignFile(ft, OpenDialog1.FileName);
        Reset(ft);
        AssignFile(ft2, ExtractFileDir(OpenDialog1.FileName)+'\rez.txt');
        Rewrite(ft2); // чтобы создался новый, если нету, или перезаписался с нуля
        Append(ft2); // чтобы можно было добавлять строки, а не перезаписывать каждый раз
       begin
      while not eof(ft) do
       begin
      readln(ft,s);
      //////////////////////////////////////
      Вот тут не знаю что дописать ?
      //////////////////////////////////////
      writeln(ft2,s)
       end;
      closefile(ft);
      closefile(ft2);
      end;
      end;
      end;


    Подскажите кто сможет ?
    То есть решение задачи: перемешивание строк в текстовом файле размером 500 - 700 мегабайт.
      На SO ты сонм своих однообразных вопросов под женским ником пишешь.
      Раздвоение личности мешает разобраться однажды и навсегда?
        Цитата Kirilis2018 @
          Rewrite(ft2); // чтобы создался новый, если нету, или перезаписался с нуля
          Append(ft2); // чтобы можно было добавлять строки, а не перезаписывать каждый раз

        Так не прокатит.
        ExpandedWrap disabled
          If FileExist(ft2) Then Append(ft2) else  Rewrite(ft2);
          Цитата MBo @
          На SO ты сонм своих однообразных вопросов под женским ником пишешь.
          Раздвоение личности мешает разобраться однажды и навсегда?

          То я с сестрой по очереди. Учим вместе Delphi, потому так (один аккаунт на двоих).

          Добавлено
          ^D^ima
          А как тогда проще сделать ? Подскажите пожалуйста.
          Сообщение отредактировано: Kirilis2018 -
            Пока самым оптимальным вариантом вижу такой:
            1. Открываем файл со строками в двоичном режиме.
            2. Читаем файл побайтно(пословно, если уникод), узнавая где строки начинаются, занося в память (в таблицу) начало каждой новой строки.
            3. Создаём массив номеров строк в памяти.
            4. Перемешиваем этот массив тем случайным способом.
            5. Аккуратно идём по этим перемешаным номерам, понимаем какая строка нужна сюда и двоично читаем её из того файла со смещением из таблицы, пишем в результат.
            Всё.

            П.С. тьма двоичных перемещений по файлу со строками всё равно останется. Что весьма печально. Но памяти будет расходоваться крайне мало!
              Цитата Kirilis2018 @
              А как тогда проще сделать ? Подскажите пожалуйста.

              Тогда нужно понимать из чего состоит файл, из строк фиксированной длины или чего-то ещё?
                Цитата ^D^ima @
                Тогда нужно понимать из чего состоит файл, из строк фиксированной длины или чего-то ещё?

                Файл состоит из строк разной длины. Разные предложения и цифры.
                  Это самый плохой вариант в данном случаи. Возможно меня коллеги поправят но я думаю что стратегия зсключается в считывании в случайном порядке строк из входящего файла и последовательной записи в исходялий. Для этого нужно составить карту файла и найти смещения и длину всех строк. Данные записать в массив. Массив перемешать и перемещаясь по файлу согласно даному массиву вычитывать файл. Если бы строки былибы фиксированной длины, былобы проще в разы
                    примерно так:
                    ExpandedWrap disabled
                      procedure TForm1.Button1Click(Sender: TObject);
                      Type
                        TRec = record
                                 SeekBegin:Longint;
                                 StringLength:Longint;
                               end;
                      Var
                      FInMap:TextFile;
                      FIn,FOut:File;
                      S:String;
                       
                      StringCount,NumRead:Longint;
                       
                      FileMap:array[0..1000] of TRec;
                       
                      C:array[1..2048] of char;
                       
                      begin
                        assignfile(FInMap,'c:\123.txt');
                        Reset(FInMap);
                        StringCount:=1;
                          While not eof(FInMap) do
                            Begin
                              Readln(FInMap,s);
                              FileMap[StringCount].SeekBegin:=FileMap[StringCount-1].SeekBegin+FileMap[StringCount-1].StringLength;
                              FileMap[StringCount].StringLength:=Length(s)+2;
                              Inc(StringCount);
                            End;
                        FileMap[StringCount].StringLength:=FileMap[StringCount].StringLength-2;
                        CloseFile(FInMap);
                       
                      //тут перемешиваем   FileMap
                       
                       
                        assignfile(FIn,'c:\123.txt');
                        assignfile(FOut,'c:\321.txt');
                        Reset(FIn,1);
                        Rewrite(FOut,1);
                       
                          For StringCount:=1 To StringCount-1 do
                            Begin
                            Seek(FIn,FileMap[StringCount].SeekBegin);
                              BlockRead(FIn,C,FileMap[StringCount].StringLength,NumRead);
                              BlockWrite(FOut,C,NumRead);
                            End;
                        CloseFile(FOut);
                        CloseFile(FIn);
                      end;


                    Тут такая особенность работы с текстовыми файлами: Каждая строка заканчивается невидимым символом в блокноте CRLF, поэтому работая через поблочное чтение\запись учитываем 2 байта. Везде кроме последней строки. Так что при перемешивании учитываем такую особенность.Или не перемешивать последнюю сроку или отслеживать самостоятельо данный момент. Возможен вариант когда уже в поблочной записи вставляются эти символы. В коде не отработаен вариант с динамическим масивом FileMap, а его нужно делать по хорошему динамическим иначе может быть вариант когда кол-во строк ыайла выше 1000, или любого другого значения. который мы поставим.

                    Добавлено
                    Ну и да, нет самого перемешивания массива
                      Цитата Kirilis2018 @
                      в регуляровкой рандом не дружу

                      Random() и Randomoze() - http://delphi-help.ru/index.php?option=com...hislah-v-delphi
                      Пример на С++ Builder, сорри, думаю - разберёшься. Или тут помогут переписать.
                      ExpandedWrap disabled
                          TStringList *src = new TStringList(); // источник
                          TStringList *dst = new TStringList(); // приёмник
                          src->LoadFromFile("src.txt");
                          int count = src->Count; // начальное количество строк - значение счётчика
                          Randomize();
                          int pos = Random(count); // случайнаяпозиция строки для копирования
                          while (coumt >= 0) {
                            dst->Add(src->Strings[pos]); // скопировать из источника в приёмник
                            dst->Delete(pos); // УДАЛИТЬ строку из источника, она уже есть в приёмнике
                            count--; // уменьшить счётчик
                            pos = Random(count); // получить новую случайную позицию в мсточнике
                          }
                          dst->SaveToFile("dst.txt");
                          detete src;
                          delete dst;
                        Цитата Kirilis2018 @
                        решение задачи: перемешивание строк в текстовом файле размером 500 - 700 мегабайт.

                        Судя по тому, что у тебя в нескольких темах фигурирует размер файла (именно) до 700 Мб и платформа Delphi\RAD XE4, то это похоже на "вопрос на засыпку".
                        Дело в том, что если текстовый файл представлен в кодировке ANSI (что скорее всего), то на старом\добром Delphi 7 загрузка 700 Мб в TStringList не должна представлять особых проблем. А в версиях Delphi\RAD, использующих по умолчанию юникод, скорее всего будут проблемы в 32-битных приложениях, т.к. при преобразовании ANSI в юникод объем занимаемой памяти (тупо\бестолково) возрастает в два раза. Поэтому, если речь идет о размерах файла до 500-700 Мб (а не о "страшных" гигабайтах, которые явно невозможно загрузить в память в 32-битных приложениях), то решением "проблемы" может быть загрузка строк не в стандартный TStringList, хранящий string в формате юникод, а в некий TList (обычный или дженерик), хранящий AnsiString.
                          И всё же, leo, наибольший интерес представляет именно сортировка текстового файла с количеством строк в миллионы..миллиарды. Именно такое красивое решение я бы, как преподаватель, оценил=похвалил. А пока никто такового не предложил.
                            Цитата Славян @
                            наибольший интерес представляет именно сортировка текстового файла с количеством строк в миллионы..миллиарды.

                            А я считаю, что текстовые файлы размером даже в сотни Мб - это уже нонсенс и верх тупости\идиотизма. А заниматься тупой "сортировкой" таких файлов (без преобразования формата, создания вспомогательных индексных файлов и т.п.) - это еще большая тупость\идиотизм ;)
                              leo, кабы сортировка! У ТС надо просто перемешать. А на... э-э-э, зачем???
                                LMM
                                Так в задании сказано что нельзя копироввть в память
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0427 ]   [ 16 queries used ]   [ Generated: 18.04.24, 00:36 GMT ]