Модераторы: Poseidon, Snowy, bems, MetalFan
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Старый writeln и unicode 
:(
    Опции темы
klyaksa
Дата 3.9.2010, 22:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 187
Регистрация: 15.9.2005

Репутация: нет
Всего: нет



Нужно !дописывать! немного в текстовый файл. Загружать в TStringList, добавлять и записывать не дело - значительно дольше, особенно при больших файлах - проверено. 
  AssignFile(f, ResultFullFileName);
    if not FileExists(ResultFullFileName) then ReWrite(f)
    else Append(f);
    //---
    for I := 0 to StringList.Count - 1 do
       Writeln(f, StringList[I]);
Намного быстрее...
Но с переходом на 2009/2010 возник вопрос - а как реализовать запись в ansi и в unicode?  TStringList - вроде понятно, там параметр добавился, а как быть с Writeln?
PM MAIL   Вверх
northener
Дата 4.9.2010, 00:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1361
Регистрация: 2.9.2010

Репутация: 8
Всего: 20



Цитата(klyaksa @  3.9.2010,  22:23 Найти цитируемый пост)
Но с переходом на 2009/2010 возник вопрос - а как реализовать запись в ansi и в unicode?  TStringList - вроде понятно, там параметр добавился, а как быть с Writeln? 

Перекодировать строку в нужный формат перед передачей в Writeln?


--------------------
Но только лошади летают вдохновенно.
Иначе лошади разбились бы мгновенно!
PM MAIL   Вверх
Alexeis
Дата 4.9.2010, 13:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 109
Всего: 459



klyaksa, зачем же сразу переходить на старый паскалевский файловый доступ. Открываем файл при помощи TFileStream, перемещаем файловый указатель в конец и пишем сколько влезет, хоть 1Тб .

Добавлено через 6 минут и 4 секунды
Кстати для удобства работы со строками лучше использовать дополнительный класс TWriter http://forum.vingrad.ru/forum/topic-250409.html


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
CodeMonkey
Дата 4.9.2010, 13:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1839
Регистрация: 24.6.2008
Где: Россия, Тверь

Репутация: 38
Всего: 89



Alexeis, ты ничего не попутал? smile


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
Alexeis
Дата 4.9.2010, 13:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 109
Всего: 459



Цитата(CodeMonkey @  4.9.2010,  12:30 Найти цитируемый пост)
Alexeis, ты ничего не попутал? 

  Ты по поводу чего? Размер больше 4х Гб TFileStrem точно умеет, хотя в этой теме вопрос размер не актуален.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
klyaksa
Дата 4.9.2010, 16:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 187
Регистрация: 15.9.2005

Репутация: нет
Всего: нет



Цитата(Alexeis @  4.9.2010,  13:06 Найти цитируемый пост)
Открываем файл при помощи TFileStream, перемещаем файловый указатель в конец и пишем сколько влезет

Код

  if FileExists(ResultFullFileName) then
  fs := TFileStream.Create(ResultFullFileName, fmOpenReadWrite)
  else
  fs := TFileStream.Create(ResultFullFileName, fmCreate);
  try
    fs.Seek(1, soEnd);
    for I := 0 to StringList.Count - 1 do
    begin
      Str := StringList[I];
      fs.Write(Str[1], Length(Str) * SizeOf(Char));
    end;
  finally
    fs.Free;
  end;

При увеличении размера сильно растет время... Хотя
  AssignFile(f, ResultFullFileName);
    if not FileExists(ResultFullFileName) then ReWrite(f)
    else Append(f);
продолжает писать как и писал - быстро.

Добавлено через 13 минут и 31 секунду
Да и еще как оказалось 
способ 1 - пишет Не уникод
способ 2 - может и так и так
способ 3 - почему-то Не уникод.
Это видно и по размерам получаемых файлов....
PM MAIL   Вверх
klyaksa
Дата 4.9.2010, 16:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 187
Регистрация: 15.9.2005

Репутация: нет
Всего: нет



пс
способ 1 - в первом сообщении (он самый быстрый)
способ 2- загрузить в StringList, дописать и сохранить (медлено, но можно уникод и нет)
способ 3 - чуть выше (медлено, почему-то не уникод)
PM MAIL   Вверх
RomanEEP
Дата 4.9.2010, 16:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 424
Регистрация: 18.5.2006
Где: Коломна

Репутация: 5
Всего: 8



странно при обоих методах компилятор должен генерировать сходный код может заменить
fs.Seek(1, soEnd); на fs.Seek(0, soEnd);
PM MAIL   Вверх
Alexeis
Дата 4.9.2010, 18:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 109
Всего: 459



klyaksa, TFileStream.Write вызывает почти сразу WinApi функцию WriteFile(THandle(Handle), Buffer, Count, LongWord(Result), nil) , так что это максимально быстро. Возможно разница в том, что при записи юникода объем в 2 раза больше, вот и время записи выше.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
Alexeis
Дата 4.9.2010, 18:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 109
Всего: 459



  Ааа, все понял! Прошел дебагом. Дело в буферизации. Writeln буферизирует вывод в файл до CloseFile , тоже самое можно сделать если вывод делать в TMemoryStream , а затем из него копировать в TFileStream при помощи метода CopyFrom. Метод CopyFrom записывает данные буфером 61440 . Думаю, что такой режим будет аналогичен Writeln .


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
klyaksa
Дата 7.9.2010, 16:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 187
Регистрация: 15.9.2005

Репутация: нет
Всего: нет



Цитата(Alexeis @  4.9.2010,  18:43 Найти цитируемый пост)
Дело в буферизации. 

Вряд ли только....
Тестировал все 3 варианта в цикле 1000 итераций. Записывал (дописывал) всего по 3 строки. При первом запуске (когда вначале файлов нет и они создаются в первой из 1000 итерации) способ. 1 - менее сек., сп. 2 и 3 около 3 сек. Следующий запуск 1 сп. - как было, 2 и 3 уже больше... пятый запуск (файлы уже не очень маленькие) - 1 сп. - меньше секунды, 2 и 3 несколько !десятков! секунд.

Старый writeln - быстро, но без юникода, по другому можно и юникод но долго. Вот как бы быстро дописать текст в текстовый файл причем по желанию либо ansi, либо unicode?
PM MAIL   Вверх
Alexeis
Дата 7.9.2010, 17:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Амеба
Group Icon


Профиль
Группа: Админ
Сообщений: 11743
Регистрация: 12.10.2005
Где: Зеленоград

Репутация: 109
Всего: 459



Цитата(klyaksa @  7.9.2010,  15:08 Найти цитируемый пост)
Вряд ли только....

  Еще как может быть. Накладных расходов на запись 5 ти байт в современных системах наверное как на 1кб . Так что буферизация иногда может дать прирост и в сотни раз.


--------------------
Vit вечная память.

Обсуждение действий администрации форума производятся только в этом форуме

гениальность идеи состоит в том, что ее невозможно придумать
PM ICQ Skype   Вверх
klyaksa
Дата 10.9.2010, 20:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 187
Регистрация: 15.9.2005

Репутация: нет
Всего: нет



Хочу получить нормальный текстовый файл, но получается фигня в виде иероглифов. Где моя ошибка?
Код

Str: String;
u: UTF8String;
...
ms := TMemoryStream.Create;
Str := 'Привет!' + #13#10;
u := UTF8String(Str);
ms.Write(PUTF8String(u)^, Length(u));
ms.Seek(soFromBeginning, 0);
...
fs.CopyFrom(ms, ms.Size);

PM MAIL   Вверх
klyaksa
Дата 10.9.2010, 21:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 187
Регистрация: 15.9.2005

Репутация: нет
Всего: нет



Вот так вроде бы заработало...
Код

Temp: Utf8String;
...
Str := 'Привет!' + #13#10;
Temp := Utf8Encode(Str);
ms.Write(Pointer(Temp)^, Length(Temp));
ms.Seek(soFromBeginning, 0);
...
fs.Seek(0, soEnd);
fs.CopyFrom(ms, ms.Size);


Добавлено через 7 минут и 26 секунд
Alexeis, да, кстати, так достаточно быстро, от размера файла на глаз не зависти, 1000 итераций за 4.* секунд...
 
PM MAIL   Вверх
klyaksa
Дата 11.9.2010, 10:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 187
Регистрация: 15.9.2005

Репутация: нет
Всего: нет



Все вопрос решен (наверное smile ) :

Код

procedure TForm1.AddTextToFile(FileName, Text: String; bU: Boolean = true);
var
  fs: TFileStream;
  ms: TMemoryStream;
  Temp: Utf8String;
  AStr: AnsiString;
begin
  if Text = '' then Exit;

  ms := TMemoryStream.Create;
  try

    if bU then
    begin
      Temp := Utf8Encode(Text);
      ms.Write(Pointer(Temp)^, Length(Temp));
    end
    else
    begin
      AStr := Text;
      ms.Write(Pointer(AStr)^, Length(AStr));
    end;

    ms.Seek(soFromBeginning, 0);

    if FileExists(FileName) then
      fs := TFileStream.Create(FileName, fmOpenReadWrite)
    else
      fs := TFileStream.Create(FileName, fmCreate);

    try
      fs.Seek(0, soEnd);
      fs.CopyFrom(ms, ms.Size);
    finally
      fs.Free;
    end;

  finally
    ms.Free;
  end;

end;

PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0604 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.