|
Вопрос # 5 253/ вопрос открыт / |
|
Здравствуйте, уважаемые эксперты!
мне надо писать в МП3 файл ID3 тэги. За основу взял статью https://www.delphi-int.ru/articles/1/
переделал немного для записи, получил следующее:
procedure TForm1.WriteID3tags;
var
FS: TFileStream;
resStr: string;
genre: Byte;
begin
if (ProcessingFile = '') then exit;
FS := TFileStream.Create(ProcessingFile, fmOpenReadWrite);
try
FS.Seek(-128+4, soFromEnd);
resStr := TrackNameEdit.Text;
FS.Write(resStr, Length(resStr));
FS.Seek(-128+4+30, soFromEnd);
resStr := ArtistEdit.Text;
FS.Write(resStr, Length(resStr));
FS.Seek(-128+4+30+30, soFromEnd);
resStr := AlbomEdit.Text;
FS.Write(resStr, Length(resStr));
FS.Seek(-128+4+30+30+30+4+30, soFromEnd);
genre := Byte(ComboBox1.ItemIndex);
FS.Write(genre, 1);
finally
FS.Free;
end;
end;
после выполнения функции открываю свойства файла -> сводка - все поля пустые. Что у меня не так?
|
Вопрос задал: AlexMPEI (статус: 1-ый класс)
Вопрос отправлен: 5 мая 2011, 13:28
Состояние вопроса: открыт, ответов: 1.
|
Ответ #1. Отвечает эксперт: Вадим К
Здравствуйте, AlexMPEI!
А теперь полный ответ.
Разберем, что делает функция write в данном случае - она берет переменную (причем ей все равно, какого она типа) и извлекает из нее нужное кол-во байт.
тип string по умолчанию (если опции компилятора не накрутить) - это просто 4 байта указатель на начало строки. так как функция write об этом не знает, то она запишет в результирующий файл (или поток) эти 4 байта адреса!!! (не данных, а именно адреса). Но если ее попросили записать 30 байт - то ещё 26 следующих байт. А вот что там будет - неведомо, скорее всего какой то мусор.
Когда же был выбран тип string[255] - то это 256 байт, адрес начала которых совпадает с именем переменной. И в самом начале, в нулевом байте, записана длина строки (так как длина строки не может быть больше 255 символов, потому что байт, поэтому компилятор и ругается, если написать к примеру string[300]).
Исходя из вышесказанного, для записи этого нужно либо используя string, писать что то вида s[1], а в некоторых случаях даже @s[1]. Это будет работать и для обычных строк string[255].
Но правильным способом будет использовать структуру с примера, заполнить ее, а потом одним махом записать.
|
Ответ отправил: Вадим К (статус: Академик)
Время отправки: 5 мая 2011, 16:59
Оценка за ответ: 5
Комментарий к оценке: подробно, понятно
|
Мини-форум вопроса
Всего сообщений: 10; последнее сообщение — 5 мая 2011, 21:16; участников в обсуждении: 3.
|
Вадим К (статус: Академик), 5 мая 2011, 13:44 [#1]:
Вопрос на вопрос
а до этого в файле был ID3 тэг ? причем именно первой версии? если нет - то Ваш код затирает конец файла.
Вопрос номер два - а если открыть в хекс редакторе, то строки есть в конце или мусор (подозреваю мусор в самом конце).
Галочка "подтверждения прочтения" - вселенское зло.
|
|
AlexMPEI (статус: 1-ый класс), 5 мая 2011, 13:55 [#2]:
небыло - это отграбленный мной с СД файл.
открыл блокнотом - моих строк нет
|
|
Вадим К (статус: Академик), 5 мая 2011, 14:04 [#3]:
раз их там не было, то нужно дописывать в конец, а не перетирать последние 128 байт.
открывать блокнотом... ещё бы вордом открыли.
ну и, судя по коду, Вы не совсем понимаете сущность string и чем оно отличается от string[какое то число].
Попробуйте вместо resStr: string; написать resStr: string[255]; и посмотрите результат.
Галочка "подтверждения прочтения" - вселенское зло.
|
|
AlexMPEI (статус: 1-ый класс), 5 мая 2011, 14:26 [#4]:
resStr: string[255];
FS.Seek(0, soFromEnd);
FS.Write(' ', 3);
resStr := TrackNameEdit.Text;
FS.Write(resStr, 30);
resStr := ArtistEdit.Text;
FS.Write(resStr, 30);
resStr := AlbomEdit.Text;
FS.Write(resStr, 30);
FS.Write(' ', 34);
genre := Byte(ComboBox1.ItemIndex);
FS.Write(genre, 1);
появились мои строки если смотреть в редакторе, но в свойствах файла тэги по прежнему пустые. дописываю вроде в конец теперь.
|
|
Вадим К (статус: Академик), 5 мая 2011, 14:45 [#5]:
лучше вместо FS.Write(' ', 3);
написать явно
resStr := ' ';
FS.Write(resStr, 3);
По поводу "дописывать или перезаписывать конец" - для начала подсмотрите в самый конец файла - если там теги.
И совет получше - в примере статьи, которую Вы и используете есть структура. Никто не мешает ее заполнить, а потом одним махом записать по адресу (вот дописать или переписать - это нужно смотреть детальнее). И сразу все проблемы решатся.
Галочка "подтверждения прочтения" - вселенское зло.
|
|
AlexMPEI (статус: 1-ый класс), 5 мая 2011, 16:02 [#6]:
появились тэги. но теперь другая проблема: после записи в редакторе видно что при подобном присвоении
resStr: string[255];
resStr := TrackNameEdit.Text;
первый символ всегда почему-то какой-то мусор, потом собственно идет мой текст. Откуда берется этот первый чужой символ? в дебагере все чисто, символ вижу по факту после записи.
|
|
Вадим К (статус: Академик), 5 мая 2011, 16:42 [#7]:
первый символ - это тот, который в позиции [0] ?
а если запись делать так
FS.Write(resStr[1], 30); - должно быть все ок только вместо 30 подставляем нужное число.
Галочка "подтверждения прочтения" - вселенское зло.
|
|
AlexMPEI (статус: 1-ый класс), 5 мая 2011, 16:49 [#8]:
все работает. большое спасибо
|
|
bugmenot (статус: 3-ий класс), 5 мая 2011, 20:23 [#9]:
ID3v1 устарел еще в прошлом веке, кстати
виконання програми розпочинається з того самого мiсця, де призупинилося.
|
|
Вадим К (статус: Академик), 5 мая 2011, 21:16 [#10]:
если быть честным, то mp3 давно устарел. Но ведь вопрос был не в этом, bugmenot
Галочка "подтверждения прочтения" - вселенское зло.
|
Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.
|