Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Общие вопросы > TIniFile и многострочный текст


Автор: stab 16.6.2005, 08:11
Посоветуйте каким образом в TIniFile лучше хранить многострочный текст. Надо сохранить\прочитать строковое значение такого вида:

Цитата
Line1
Line2
Line3


Хранить надо именно в ini-файлах, т.к. сторонние утилиты для, которых нужен этот файл требуют ini и ни чего другого.

Автор: Pakshin A. S. 16.6.2005, 08:32
Легче не придумать!!!

Заменяем ^M^J на какой-нить символ, например |

Запихиваем это в файл...

При чтении заменяем | на ^M^J

Запихиваем это в мемо....

Автор: stab 16.6.2005, 08:42
Парадоксально, но именно так и пробовал, пишется нормально, а вот читается только до первой трубы (|), а дальше нет, пробовал на Windows XP Pro Eng SP2. Плюс к этому, в документации написано, что символы с кодами меньше 32 (пробел) могут не читаться.

Автор: Akella 16.6.2005, 08:42
Код

Var
  slIni:TStringList;
begin
try
  slIni:=TStringList.create;
  slIni.Clear;
  slIni.loadfromfile('c:\myfolder\file.ini');
или
  slIni.savetofile('c:\myfolder\file.ini');
finally
slIni.free;
slIni:=nil;
end;


Автор: Pakshin A. S. 16.6.2005, 08:42
Вот код на всякий случай:

Код

const
 EnterI = '|'; // Переход на строку в файле
 EnterM = ^M^J; // переход на строку в компоненте

function IniEnter(Str: string):string;
begin
 if Pos(EnterI, Str) = 0
  then
   Result:=StringReplace(Str, EnterM, EnterI, [rfReplaceAll])
  else
   Result:=StringReplace(Str, EnterI, EnterM, [rfReplaceAll])
end;

Добавлено @ 08:48
Код

uses IniFiles;

const
 EnterI = '|';
 EnterM = ^M^J;

function IniEnter(Str: string):string;
begin
 if Pos(EnterI, Str) = 0
  then
   Result:=StringReplace(Str, EnterM, EnterI, [rfReplaceAll])
  else
   Result:=StringReplace(Str, EnterI, EnterM, [rfReplaceAll])
end;

procedure TForm1.Button1Click(Sender: TObject);
var
 f: TIniFile;
begin
 f:= TIniFile.Create('C:\Demo.ini');
 f.WriteString('Demo', 'Memo', IniEnter(Memo1.Lines.Text));
 f.Free;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
 f: TIniFile;
begin
 f:= TIniFile.Create('C:\Demo.ini');
 Memo1.Text:=IniEnter(f.ReadString('Demo', 'Memo', ''));
 f.Free;
end;


Все работает... на достаточно больших мемо...

Автор: stab 16.6.2005, 08:49
Pakshin A. S., не работает в общем этот метод, попробую другие разделители...

Автор: Pakshin A. S. 16.6.2005, 08:50
У меня ХР Prof работает с 1000 строк по четыре буквы в каждой...

Не наю... Может не то что-то написал?

Автор: stab 16.6.2005, 08:53
Может можно как-нибудь без разделителей обойтись? Хранить, например, каждую строку в отдельном значении... т.е. что-то вроде:

Цитата
Value_Line1=Line1
Value_Line2=Line2
Value_Line3=Line3
...


или как-то проще можно?

Автор: Pakshin A. S. 16.6.2005, 08:55
НАФИГ? Проверь корректность кода... У меня свободно работает прога с цифрами в каждой строчке от 1 до 64000... Долго правда, но все-таки работает!

Автор: stab 16.6.2005, 08:59
А все, понял в чем беда, при записи ^J оставался. Спасибо за то, что убедил, что метод рабочий, а то я уже начал всякие извращения выдумывать. smile

Автор: Pakshin A. S. 16.6.2005, 09:11
Т. е.? Что в итоге написал?
Добавлено @ 09:13
Кстати, а ини файл то не безразмерный!

Я бы все-таки в отдельном текстовом хранил... Или вообще для всего этого создал бы базу данных и работал с нею, т. к. по-моему это быстрее...
Добавлено @ 09:16
Вариант разонравился...
smile Плохой вариант smile Плохой вариант smile Плохой вариант...

Автор: Pakshin A. S. 16.6.2005, 09:27
О! Вот это больше нравится...

Код

uses IniFiles;

const
 EnterI = '|';
 EnterM = ^M^J;
 Ident = 'Memo';
 NextIdent = 'Memo2';

function IniEnter(Str: string):string;
var
 i:integer;
begin
 if Pos(EnterI, Str) = 0
  then
   Result:=StringReplace(Str, EnterM, EnterI, [rfReplaceAll])
  else
   Result:=StringReplace(Str, EnterI, EnterM, [rfReplaceAll])
end;

procedure TForm1.Button1Click(Sender: TObject);
var
 f: TIniFile;
begin
 f:= TIniFile.Create('C:\Demo.ini');
 f.WriteString('Demo', Ident, IniEnter(Memo1.Lines.Text));
 f.Free;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
 s:string;
begin
 RichEdit1.Lines.LoadFromFile('C:\Demo.ini');
 s:=RichEdit1.Text;
 Delete(s, 1, Pos(Ident, s) + Length(Ident));
 s:=Copy(s, 1, Pos(NextIdent+'=', s)-1);
 Memo1.Lines.Text:=IniEnter(s);
end;


Только RichEdit нуна спрятать или заменить его на что-нить создаваемое тут же...
Добавлено @ 09:29
Вместо NextIdent можно какой-нить постфикс использовать и дописывать его к преобразованному тексту...

Автор: stab 16.6.2005, 10:29
Цитата(Pakshin @ 16.6.2005, 06:11)
Т. е.? Что в итоге написал?

Как у тебя, у меня замена была по ^M только.
Цитата(Pakshin @ 16.6.2005, 06:11)
Я бы все-таки в отдельном текстовом хранил... Или вообще для всего этого создал бы базу данных и работал с нею, т. к. по-моему это быстрее...

Я бы тоже, но нужно, как говориться, backward compatibility обеспечить.

Автор: Pakshin A. S. 16.6.2005, 10:31
Цитата
backward compatibility


А по-русски?

Автор: <Spawn> 16.6.2005, 12:21
Pakshin A. S. Видимо, "обратная совместимость" smile

Добавлено @ 12:24
Имхо, плохая идея хранить такие массивы текста в Ini... Обязательно должен быть другой выход. Почему, к примеру, не хранить пути в INI к реальным файлам с данными?

Автор: Pakshin A. S. 16.6.2005, 16:41
Цитата

Видимо, "обратная совместимость"


Все-равно ен понял, что требуется... smile

Автор: EKoshelev 17.6.2005, 07:28
Ребята, я может тормоз, но чем не подходит то, что dsergey предложил??????

Автор: stab 17.6.2005, 08:54
Цитата(Pakshin @ 16.6.2005, 13:41)
Все-равно ен понял, что требуется...

Требуется хранить многострочный текст в одном из значений в ini файле, есть уже готовый софт (не мой), который эти ini файлы читает и переделывать его ни кто не собирется, следовательно так просто формат\способ хранения данных изменить нельзя, т.е. нужна обратная совместимость с этим софтом. Что бы хотя бы эти файлы коректно (без эксепшенов) читались без модификации софта, не важно что данные слегка кривоватые будут, надо что бы просто читалось.

Цитата
Имхо, плохая идея хранить такие массивы текста в Ini... Обязательно должен быть другой выход. Почему, к примеру, не хранить пути в INI к реальным файлам с данными?

Там тексты маленькие, максимум строчек 10, так что все ок.

Цитата(EKoshelev @ 17.6.2005, 04:28)
Ребята, я может тормоз, но чем не подходит то, что dsergey предложил??????

Пардон, но мне кажется, что его код к ini файлам имеет отношение только одним местом -- расширением, если его поменять на bmp, то можно будет сказать, что многострочный текст можно хранить и в графических файлах smile Надеюсь не нужно объяснять, что такое форматы файлов?

Автор: Dynamic 17.6.2005, 13:07
Цитата(cully @ 17.6.2005, 08:54)
Пардон, но мне кажется, что его код к ini файлам имеет отношение только одним местом -- расширением, если его поменять на bmp, то можно будет сказать, что многострочный текст можно хранить и в графических файлах  Надеюсь не нужно объяснять, что такое форматы файлов?

имелось ввиду, что твои ini-файлы именно как INI рассматривает, возможно та чужая прога, а что тебе мешает рассматривать их как обычные текстовые файлы и работать с ними обычным способом (см. совет dsergey)??

Лучше покажи один файлик и что с ним надо сотворить.

Автор: s-mike 17.6.2005, 13:14
Многострочный текст лучше всего хранить в XML.

Автор: Pakshin A. S. 17.6.2005, 18:13
Цитата
Лучше покажи один файлик и что с ним надо сотворить.


Вот ини файл, в котором текс от двух компонентов:

Memo1=asdfasdfasdfkadhfkajdghfkjagfsdf...
Memo2=asdfasjdgfasdhfgkasjgfkasjfhgkasjfhgk...

Причем В тексте обоих компонентов может встречаться и Enter, который выводит в файле вот это:

Memo1=asdfasdfasdfkadhfkajdghfkjagfsdf...
asdfasdfasdfasdf...
Memo2=asdfasjdgfasdhfgkasjgfkasjfhgkasjfhgk...

Т. е. нарушается структура файла... smile

Автор: EKoshelev 20.6.2005, 10:58
Pakshin A. S., это единственное, что мешает рассматривать файл как текстовый. Или есть ещё причины???

Автор: Pakshin A. S. 20.6.2005, 11:03
Впринцепе да...

Автор: Quadr0 20.6.2005, 11:19
...

Автор: Dynamic 20.6.2005, 11:27
Ну сохраняй типа такого:
Код
var i: integer;
begin
  with TStringList.Create do
  try
   Add(['Memo1']);
   for i := 0 to Memo1.Count-1 do
    Add('Part' + IntToStr(i+1) + '=' + Memo1.Lines[i]);
  finally
    free;
  end;
Получишь свой ини:
Цитата
[Memo1]
Part1=Строка1
Part2=Строка2
Part3=Строка3
.....
И так для всех мемо.

Автор: Pakshin A. S. 20.6.2005, 11:40
Т.к. наш ини файл не резиновый, то последний метод занимать будет больше места... Вообще по-нормальному соответственно нужен отдельный файл для инфы!

Автор: Dynamic 20.6.2005, 12:16
Автору топика, кажись, эта дискуссия уже неинтересна....

Автор: Pakshin A. S. 20.6.2005, 12:18
Наверное... ведь решение как я понимаю он получил...
Добавлено @ 12:20
Блин... не прочитал один пост: smile
Цитата

Требуется хранить многострочный текст в одном из значений в ini файле, есть уже готовый софт (не мой), который эти ini файлы читает и переделывать его ни кто не собирется, следовательно так просто формат\способ хранения данных изменить нельзя, т.е. нужна обратная совместимость с этим софтом. Что бы хотя бы эти файлы коректно (без эксепшенов) читались без модификации софта, не важно что данные слегка кривоватые будут, надо что бы просто читалось.


И ЭТИМ РЕАЛЬНО ВСЕ СКАЗАНО!

Автор: Lence 25.12.2006, 05:24
у меня такая проблема - в ini файл сохраняется даные из стороннего компонента, сохраняются цифры, компонет делит введенное число на сотни, например если в обычном Edit написать 1111111 - то так и будет написано, в этом компоненте остается 1 111 111 - и таким же образом сохраняется в ини файл. 
Я попробовал проверять на пробелы и заменять их. Не помогло. Сам ини выглядит так :
Цитата

[Form2]
100=11 111
110=1 111 111
1102=111 111
111=1 111
1112=1 111
120=11 111
1202=11 111


я посмотрел данный файл HEX редактором и вот что в нем. 
Цитата

[Form2]..100=11.111..110=1.111.111..1102=111.111..111=1.111..1112=1.111..120=11.111..1202=11.111..

5B46 6F72 6D32 5D0D 0A31 3030 3D31 31A0 3131 310D 0A31 3130 3D31 A031 3131 A031 3131 0D0 A313 1303 23D3 1313 1A03 1313 10D0 A313 1313 D31A 0313 1310 D0A3 13131 323D 31A0 3131 310D 0A31 3230 3D31 31A0 3131 310D  0A31 3230 323D 3131 A031 3131 0D0A


в HEX символ пробела  20, а здесь почемуто A0 между цифрами 1[A0]111[A0]111 - вот такая фигня по идеии smile а при чтении ини файла в компоненте 1 111 111. 

кто знает как мне читать данный символ и заменять его ??? и что это вообще за символ ? 

Автор: Lence 25.12.2006, 06:45
решил проблему добавив chr($A0)

Код

function IniSpace(Str: string):string;
begin
 if Pos(Enterq, Str) = 0
  then
   Result:=StringReplace(Str, chr($A0), Enterq, [rfReplaceAll])
  else
   Result:=StringReplace(Str, Enterq, chr($A0), [rfReplaceAll])
end;

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)