Счетчик HotLog

На главнуюЧто я делаю...Программы автора и не только...Творчество
Статьи автораКнига отзывов и предложенийОбо мне, любимомФотоальбом

 
 

FileTranslator - работа над ошибками

Ранее я написал статью Как я писал программу FileTranslator. Программа предназначалась для транслитерации названий mp3-файлов и предполагалось, что будет использоваться для формирования файлов для записи на CD и последующего их воспроизведения на музыкальных центрах. На тех центрах, где есть функция вывода названия файлов при проигрывании, транслитерированные названия смотрятся более выигрышно в сравнении с набранными кириллицей и отображающимися кракозябрами.
Так, суть давней работы я напомнил, пришло время выполнить работу над ошибками, так как поработать есть над чем.

Для начала переделаем функцию транслитерации. Вместо длиннющего оператора case, написанного, кроме всего прочего, неправильно, введем константные строку, состоящую из всех символов русского алфавита, и массив, содержащий транслитерированные значения.

const
  CYRILLIC_SYMBOLS =
    'АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ' +
    'абвгдеёжзийклмнопрстуфхцчшщъыьэюя';
  LATIN_SYMBOLS: array[1..66] of String =
    ('A', 'B', 'V', 'G', 'D', 'E', 'Yo', 'Zh', 'Z', 'I', 'Y', 'K', 'L',
    'M', 'N', 'O', 'P', 'R', 'S', 'T', 'U', 'F', 'H', 'Ts', 'Ch', 'Sh',
    'Chsh', '''''', 'Y', '''', 'E', 'Yu', 'Ya',
    'a', 'b', 'v', 'g', 'd', 'e', 'yo', 'zh', 'z', 'i', 'y', 'k', 'l',
    'm', 'n', 'o', 'p', 'r', 's', 't', 'u', 'f', 'h', 'ts', 'ch', 'sh',
    'chsh', '''''', 'y', '''', 'e', 'yu', 'ya');

function Transliterate(const Source: String): String;
var
  I, Index: Integer;
begin
  Result := '';
  for I := 1 to Length(Source) do
  begin
    Index := Pos(Source[I], CYRILLIC_SYMBOLS);
    if Index > 0 then
      Result := Result + LATIN_SYMBOLS[Index]
    else
      Result := Result + Source[I];
  end;
end;

На вход функции подается строка, на выходе получаем ее транслитерацию.

Далее, для хранения списка файлов я воспользовался временным текстовым файлом. Это не совсем правильное решение. Во-первых, нельзя сказать, что оно достаточно удобно, во-вторых, файловые операции выполняются медленно (сравнительно с выполняемыми в памяти).

Для хранения списка файлов воспользуемся возможностями класса TStringList. Напрашивается применение свойств класса Names и Values. В Name-части поместить исходное имя, в Value – транслитерированное. Проблема в том, что имя исходного файла может содержать символ "=", что нарушит работу. Можно поместить имя в кавычки: Windows не разрешает использовать этот символ в именах файлов, и это снимет проблему, но, с моей точки зрения, проще применить два объекта класса TStringList. В одном будем хранить оригинальные названия, в другом – транслитерацию.

Применив всё на практике, получаем такой код программы:

program TransLangCon10_lite;

uses
  Classes, SysUtils;

const
  CYRILLIC_SYMBOLS =
    'АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ' +
    'абвгдеёжзийклмнопрстуфхцчшщъыьэюя';
  LATIN_SYMBOLS: array[1..66] of String =
    ('A', 'B', 'V', 'G', 'D', 'E', 'Yo', 'Zh', 'Z', 'I', 'Y', 'K', 'L',
    'M', 'N', 'O', 'P', 'R', 'S', 'T', 'U', 'F', 'H', 'Ts', 'Ch', 'Sh',
    'Chsh', '''''', 'Y', '''', 'E', 'Yu', 'Ya',
    'a', 'b', 'v', 'g', 'd', 'e', 'yo', 'zh', 'z', 'i', 'y', 'k', 'l',
    'm', 'n', 'o', 'p', 'r', 's', 't', 'u', 'f', 'h', 'ts', 'ch', 'sh',
    'chsh', '''''', 'y', '''', 'e', 'yu', 'ya');
  // Маска поиска файлов .mp3.
  MP3_SEARCH_MASK = '*.mp3';

var
  SourceFile: TSearchRec;
  I: Integer;
  SourceNames, TransliteratedNames: TStringList;

// Транслитерировать строку.
function
Transliterate(
  // Исходная строка.
  const Source: String): String;
var
  I, Index: Integer;
begin
  Result := '';
  for I := 1 to Length(Source) do
  begin
    Index := Pos(Source[I], CYRILLIC_SYMBOLS);
    if Index > 0 then
      Result := Result + LATIN_SYMBOLS[Index]
    else
      Result := Result + Source[I];
  end;
end;

begin
  if FindFirst(MP3_SEARCH_MASK, faAnyFile, SourceFile) = 0 then
  try
    SourceNames := TStringList.Create;
    try
      TransliteratedNames := TStringList.Create;
      try
        repeat
          SourceNames.Add(SourceFile.Name);
          TransliteratedNames.Add(Transliterate(SourceFile.Name));
        until FindNext(SourceFile) <> 0;
        for I := 0 to SourceNames.Count - 1 do
          if not FileExists(TransliteratedNames[I]) then
            RenameFile(SourceNames[I], TransliteratedNames[I]);
      finally
        TransliteratedNames.Free;
      end;
    finally
      SourceNames.Free;
    end;
  finally
    FindClose(SourceFile);
  end;
end.

Не правда ли, получилось гораздо короче, чем в прошлый раз. Можно еще вынести процедуру переименования файлов:

// Переименовать файлы.
procedure RenameFiles(
  // Список исходных имен файлов.
  const FromList: TStringList;
  // Список новых имен файлов.
  const ToList: TStringList);
var
  I: Integer;
begin
  for I := 0 to FromList.Count - 1 do
    if not FileExists(ToList[I]) then
      RenameFile(FromList[I], ToList[I]);
end;

Программу можно продолжить улучшать. Возможно, в ближайшее время этим мы и займемся.

Скачать исходник File Translator Lite v.1.1: Скачать 1.42 kB
Скачать программу File Translator Lite v.1.1: Скачать 48.8 kB
 
 

08.02.2006

 
     
Hosted by uCoz