|
Вопрос # 1 878/ вопрос открыт / |
|
Доброго времени суток, уважаемые эксперты!
Как из текстового файла с множеством строк, заполнить массив так, чтобы каждая строка была отдельный массив из нескольких значений. И вывести информацию в Мемо, для дальнейшего использования.Причем в текстовом файле значения разделенны Табуляцией.
Заранее огромное спасибо. Файл с текстом прилогаю.
К вопросу прикреплён файл. Загрузить » (срок хранения: 60 дней с момента отправки вопроса)
 |
Вопрос задал: Felixx (статус: Посетитель)
Вопрос отправлен: 5 сентября 2008, 17:30
Состояние вопроса: открыт, ответов: 1.
|
Ответ #1. Отвечает эксперт: Вадим К
Здравствуйте, Felixx!
Я покажу, как разбить одну строку, а как разбить весь файл - попробуйте догадаться самостоятельно, это очень просто, если использовать TStringList (он как Memo, только не визульный)
var s:string;//одна строка с исходного файла для разбития
dl:TStringList;
begin
dl:=TStringList.create;
try
dl.delimeter := #9;//код табуляции.
dl.delimetertext := s;
//всё, можно пользоваться результатами. например
//сколко всего элементов нашло
dl.count
//Что там храниться в 3 позиции
dl[2];//незабываем, что счёт с 0 и всё в виде строк. причем кавычки вокруг строк тоже будут убираться
finally
dl.free;
end;
end;
 |
Ответ отправил: Вадим К (статус: Академик)
Время отправки: 5 сентября 2008, 17:58
Оценка за ответ: 5
|
Мини-форум вопроса
Всего сообщений: 19; последнее сообщение — 6 сентября 2008, 16:29; участников в обсуждении: 3.
|
Мережников Андрей (статус: Абитуриент), 5 сентября 2008, 19:37 [#1]:
как объявить массив зависит от того - одинаковое ли количество элементов подразумевается в строках. И еще уточняющий вопрос - что именно и в каком виде Вы хотите выводить в memo?
|
|
Felixx (статус: Посетитель), 5 сентября 2008, 19:44 [#2]:
Если конкретно, то я пытаюсь из этого файла сделать SQL запрос...
Сделал следующее:
В одно мемо загружаю весь файл
потом по нажатию кнопки выполняю..
procedure TForm1.Button4Click(Sender: TObject);
var
s:string;//одна строка с исходного файла для разбития
dl:TStringList;
i:integer;
begin
for i:=0 to Memo2.Lines.Count-1 do
begin
s:= Memo2.Lines[0+i];
dl:=TStringList.create;
try
dl.Delimiter:=#9;
dl.DelimitedText:=s;
memo1.Text:=(Memo1.Text+'INSERT INTO `recitems` VALUES');
memo1.Text:=(Memo1.Text+'('+dl[1]+','+dl[2]+','+dl[8]+','+'0'+');'+#13);
finally
dl.free;
end;
end;
end;
Получаются множество запросов в мемо.. и сохраняю в файл.
Но там получается не корректный переход на новую строку после каждого запроса. Подскажите как сделать корректно переход?
|
|
Вадим К (статус: Академик), 5 сентября 2008, 19:52 [#3]:
ну зачем писать так хитро
memo1.Text:=(Memo1.Text+'('+dl[1]+','+dl[2]+','+dl[8]+','+'0'+');'+#13);
во первых, надо знать, что под виндовсом перевод строки - это #13#10.
Но лучше писать так.
var s:string;
begin
...
if dl.count < 9 then ShowMessage('ЧП мирового масштаба, либо просто плохой файл')
else begin
s:='INSERT INTO `recitems` VALUES' +
'('+dl[1]+','+dl[2]+','+dl[8]+','+'0'+');');
Memo1.lines.add(s);
end;
Галочка "подтверждения прочтения" - вселенское зло.
|
|
Мережников Андрей (статус: Абитуриент), 5 сентября 2008, 19:57 [#4]:
Думаю, что лучше сделать следующим образом:
перед циклом выполнить: memo1.lines.clear;
ввести дополнительную переменную s1. В цикле делать:
s1:='insert into ... values ('+dl[1]+','+...;
memo1.lines.add(s1);
Кстати, а почему в запросе нет перечисления полей, которым присваиваются значения? Есть опасность нарваться на неприятность - если порядок полей в таблице не совпадет с порядком перечисления значений.
|
|
Мережников Андрей (статус: Абитуриент), 5 сентября 2008, 20:00 [#5]:
to Вадим К : переменая s уже используется (а то "вопрошающий сделает так как написано" и получит геморой)
|
|
Вадим К (статус: Академик), 5 сентября 2008, 20:04 [#6]:
и что, будет работать. посмотрите внимательней После присваивания она уже не нужна и можно использовать снова
Галочка "подтверждения прочтения" - вселенское зло.
|
|
Мережников Андрей (статус: Абитуриент), 5 сентября 2008, 20:05 [#7]:
to Вадим К:ЧП мирового масштаба не получиться - там стоит try finally end
просто строка не добавиться в memo.
Да и еще to Felixx: вынесите строки dl:=TStringList.create и dl.free и конструкцию try finally end из цикла и используйте проверку, предложенную Вадим К .
|
|
Мережников Андрей (статус: Абитуриент), 5 сентября 2008, 20:07 [#8]:
to Вадим К:Переменная то уже не нужна, но у Вас написано s:=s+..., то есть все что было в строке s, добавиться в memo
|
|
Мережников Андрей (статус: Абитуриент), 5 сентября 2008, 20:07 [#9]:
Было написано Вы поправились
|
|
Вадим К (статус: Академик), 5 сентября 2008, 20:09 [#10]:
to Мережников Андрей
Ну раз уж так
Лучше получить ShowMessage с ругательством, чем просто будет проглочено неверную строку без каких то замечаний.
Конечно, для релиза эту строку лучше заменить на что то более внятное с выводом номера строки в файле, например.
А вообще для отладки удобно использовать так называемые "утверждения" - assert
----
Поправился, ибо умею
Галочка "подтверждения прочтения" - вселенское зло.
|
|
Мережников Андрей (статус: Абитуриент), 5 сентября 2008, 20:15 [#11]:
to Вадим К: Про проверку, которую Вы предложили, я уже написал (там где советую вынести создание dl за пределы цикла - зачем переменную много раз создавать, а потом уничтожать? вдруг проц перегреется? ). На самом деле - зачем лишние тормоза?
|
|
Felixx (статус: Посетитель), 5 сентября 2008, 20:36 [#12]:
Большое спасибо вам за ответы, первую часть того чего хотел реализовал)
В конечном результате вышел такой Код:
[code]
procedure TForm1.Button4Click(Sender: TObject);
var
s:string;
dl:TStringList;
i:integer;
begin
for i:=0 to Memo2.Lines.Count-1 do
begin
s:= Memo2.Lines[0+i];
dl:=TStringList.create;
try
dl.Delimiter:=#9;
dl.DelimitedText:=s;
if dl.count < 9 then ShowMessage('Битый файл')
else
begin
s:='INSERT INTO `recitems` VALUES' + '('+dl[1]+','+dl[8]+','+'0'+');';
Memo1.lines.add(s);
end;
finally
dl.free;
end;
end;
end;
[/code]
Теперь осталось самое сложное думаю..
например строка:
INSERT INTO `recitems` VALUES(1,[0(1864)],[4(1869)],0);
в предпоследнем значении у нас выходит строка [0(1864)],[4(1869)]
так вот мне нужно что бы то что в скобках [..] писалочь отдеотно в новую строку... например вот так должен был получиться запрос:
INSERT INTO `recitems` VALUES(1,1666,1864,0,0);
INSERT INTO `recitems` VALUES(1,1666,1869,4,0);
Это думаю тоже нужно как то в массив впихать ...
|
|
Felixx (статус: Посетитель), 5 сентября 2008, 20:44 [#13]:
Поясню, в SQL
1е значение - ID рецепта.
2е значение - ID Первой вещи для изготовления рецепта.
3е значение - Количество первой вещи.
4е значение - если вещ для изготовления рецепта имеет свой рецепт записать его ID , эти ID находятся в dl [2]
Поправочка из вышесказанного... вот правельный запрос:
INSERT INTO `recitems` VALUES(1,1864,0,0);
INSERT INTO `recitems` VALUES(1,1869,4,0);
А если например у нас в [..] 5 или 6 вещей требуется то нужно сделать 5-6 запросов для этого ID рецепта..
Как такое можно реализовать?
|
|
Мережников Андрей (статус: Абитуриент), 5 сентября 2008, 21:57 [#14]:
например так:
s:='insert into... values('+dl[1]+',[],0)';
s1:=trim(dl[8]);
repeat
x:=pos(']',s1);
if x=0
then begin
s2:=ansireplacestr(s,'[]',s1);
s1:='';
end
else begin
s3:=copy(s1,2,x-2);
s1:=copy(s1,x+2,length(s1);//тут надо предусмотреть проверку, чтобы между ] и [ был только один символ
//разбираем строку s3
x:=pos('(',s3);
s4:=leftstr(s3,x-1);
s3:=rightstr(s3,length(s3)-x);
x:=pos(')',s3);
s4:=leftstr(s,x-1)+','+s4;
s2:=ansireplacestr(s,'[]',s4);
end;
memo1.lines.add(s2);
until s1='';
И все таки - укажите список полей перед values : insert into таблица (список полей) values(список значений); А то переделает кто-нибудь структуру таблицы и всю прогу переписывать
|
|
Felixx (статус: Посетитель), 5 сентября 2008, 22:10 [#15]:
Структуру таблицы не переделают, исходный файл тоже)))
Программка нужна всего на 1 раз 
По сути это из файла клиента игры, мы берем и заполняем таблицу SQL..
на данный момент реализовал в программе такой вывод SQL:
INSERT INTO `recitems` VALUES(1,1864)],2,0);
INSERT INTO `recitems` VALUES(1,1869)],2,0);
INSERT INTO `recitems` VALUES(2,2005)],18,0);
INSERT INTO `recitems` VALUES(2,1869)],18,0);
INSERT INTO `recitems` VALUES(2,1870)],18,0);
INSERT INTO `recitems` VALUES(3,2006)],12,0);
INSERT INTO `recitems` VALUES(3,1869)],12,0);
INSERT INTO `recitems` VALUES(3,1872)],12,0);
INSERT INTO `recitems` VALUES(3,1864)],12,0);
Осталось
1) Заменить ")]", на" ,"
2) Огранизовать поиск последнего значения...
Если нужно могу выложить исходники, посмотрите что я там натворил, мож какие получше идеи будут)
если нужно то выложу...
|
|
Мережников Андрей (статус: Абитуриент), 5 сентября 2008, 22:18 [#16]:
заменить )] на запятую можно одной строкой кода:
AnsiReplaceStr(memo.text,')]',','); только не забудьте подключить модуль StrUtils;
"Программка нужна всего на 1 раз" - как знать, а вдруг еще пригодится?
На будущее советую все таки указывать список полей. Удачи в дальнейшем решении.
|
|
Felixx (статус: Посетитель), 6 сентября 2008, 05:12 [#17]:
Всем большое спасибо вот что у меня получилось...
http://plusfile.ru/8003435
кое что конесчно не реализовал, в том числе проверку на то что с исходного файла нельзя удалять 1ю строку... но принципе работает)
Может кто - нить что предложит свое?)
|
|
Вадим К (статус: Академик), 6 сентября 2008, 12:23 [#18]:
А смысл, если это "одноразовая задача". В таких задачах оправданны любые "грязные трюки", главное, что бы выполнило свою работу.
Галочка "подтверждения прочтения" - вселенское зло.
|
Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.
|