Экспертная система Delphi.int.ru

Сообщество программистов
Общение, помощь, обмен опытом

Логин:
Пароль:
Регистрация | Забыли пароль?

Delphi.int.ru Expert

Другие разделы портала

Переход к вопросу:

#   

Статистика за сегодня:  


Лучшие эксперты

Подробнее »



Вопрос # 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 Вопрос ожидает решения (принимаются ответы, доступен мини-форум)

Вопрос задал: 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

AlexMPEI (статус: 1-ый класс), 5 мая 2011, 13:55 [#2]:

небыло - это отграбленный мной с СД файл.
открыл блокнотом - моих строк нет
Вадим К

Вадим К (статус: Академик), 5 мая 2011, 14:04 [#3]:

раз их там не было, то нужно дописывать в конец, а не перетирать последние 128 байт.
открывать блокнотом... ещё бы вордом открыли.
ну и, судя по коду, Вы не совсем понимаете сущность string и чем оно отличается от string[какое то число].
Попробуйте вместо resStr: string; написать resStr: string[255]; и посмотрите результат.
Галочка "подтверждения прочтения" - вселенское зло.
AlexMPEI

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

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

AlexMPEI (статус: 1-ый класс), 5 мая 2011, 16:49 [#8]:

все работает. большое спасибо
bugmenot

bugmenot (статус: 3-ий класс), 5 мая 2011, 20:23 [#9]:

ID3v1 устарел еще в прошлом веке, кстати
виконання програми розпочинається з того самого мiсця, де призупинилося.

Вадим К

Вадим К (статус: Академик), 5 мая 2011, 21:16 [#10]:

если быть честным, то mp3 давно устарел. Но ведь вопрос был не в этом, bugmenot:)
Галочка "подтверждения прочтения" - вселенское зло.

Чтобы оставлять сообщения в мини-форумах, Вы должны авторизироваться на сайте.

Версия движка: 2.6+ (26.01.2011)
Текущее время: 10 января 2025, 06:53
Выполнено за 0.03 сек.