Несколько вопросов для учебного проекта

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Несколько вопросов для учебного проекта

Сообщение veresk » 31.01.2012 13:55:49

Добрый день, многоуважаемое сообщество!

0. Так случилось, что лет 6 назад я написал приложение на Delphi7 и оно стало активно использоваться в моём родном техникуме. С тех пор я ушёл далеко в системное администрирование, а про программирование подзабыл даже то малое, что знал тогда. Сейчас же в полный рост встала задача: доработать программу, с учётом замечаний, которых за годы накопилось чуток. Так как большинство внешне безобидных недоработок упираются в самую суть тогдашних моих извращений, то я решил переделать заново, оставив только внешний вид и идею.
С тех пор как писалось исходное приложение (оно, кстати, позволяет проводить тестирование студентов, передачу итогов по сети серверу, подведение итогов без участия преподавателя, формирование отчёта и хранение некоторой базы ранее созданных тестов) я стал заядлым линуксятником, да и техникум перешёл на использование смешанной сети Win-Lin. Короче, при обдумывании созрело у меня несколько вопросов разного толка. Возможно, несколько тупых, всё-таки много лет прошло, да и тогда я супер-программистом не был, слова "классы" и "объекты" меня несколько смущают.
Если надобно разбить вопросы на части, не проблема, разобью. Только, пожалуйста, если можно приведите примеры кода, как это когда-то было в проекте DelphiWorld, с описанием! Без примеров я точно буду лет триста разбираться. Полученную софтину обязательно опубликую летом, если кому-то интересно порождение этого быдлописательства (заодно с актом о внедрении и исходниками :) )
Итак:

1. Как правильнее узнать системные пути, кроссплатформенно чтобы? Требуется для считывания файлов конфигурации (в Linux и Windows пути разные будут). Ну или способ узнать, какая текущая ОС, и уже ориентируясь на это искать файл конфигурации.

2. Как передать от одного приложения другому по сети файлик мегабайт на 50-100, зная только IP-адрес "сервера", то есть приложения, которое должно отдать файлик? Ну и так же, надо потом отдать файлик с итогом на тот же сервер. В исходном приложении у них просто есть общая папка на windows-шаре, хотелось бы уйти от такого костыля.

3. Как перевести картинку в Base64, чтоб можно было сохранить её внутри текстового файла? Ну и как его потом вытащить в массив пикселей, например. Может, есть альтернативные решения?

4. Как отобразить картинку, не используя LoadFromFile(), как это сделано в исходном приложении? Очень не хочется опять создавать TEMP-папку, распаковывать в неё файлики-картинки и оттуда подгружать.

5. Как учесть разрешение монитора? Я предполагаю, надо считать ВЫСОТАхШИРИНА и задать размеры контролов в процентах от этого значения. Или я серьёзно не прав? Если же прав, то как узнать эти значения кросплатформенно?

6. Есть ли способ как-то по-простому зашифровать файлик? Стойкости особо не надо, лишь бы блокнотом не открывалось как простой текст, в принципе.

7. Как вызвать приложение, находящееся в той же директории, что и вызывающее его? Желательно, кроссплатформенно.
veresk
новенький
 
Сообщения: 48
Зарегистрирован: 31.01.2012 12:23:32

Re: Несколько вопросов для учебного проекта

Сообщение Brainenjii » 31.01.2012 14:55:42

1.
Код: Выделить всё
..
Uses
  ..sysutils..;
..
Begin
  WriteLn(GetAppConfigDir); // есть параметры
  WriteLn(GetAppConfigFile)); // есть параметры
..

2. использовать сетевую библиотеку (lnet/indy/synapse) и передавать потоком (TFileStream, TMemoryStream);
Upd:
Сервер:
Код: Выделить всё
program Project1;

{$mode objfpc}{$H+}

uses
  {$IFDEF UNIX}
  cthreads,
  {$ENDIF}
  Classes, IdTCPServer, IdContext, IdGlobal
  { you can add units after this };

{$R *.res}

Type

{ TServer }

TServer = Class(TIdTCPServer)
  Private
    Procedure Execute(aThread: TIdContext);
  Public
    Constructor Create;
End;

{ TServer }

Procedure TServer.Execute(aThread: TIdContext);
Var
  aFileStream: TFileStream;
Begin
  If aThread.Connection.IOHandler.ReadLn = 'GiveMeFile' Then // Читаем строку
    Begin
      aFileStream := TFileStream.Create('/home/Brainenjii/Documents/Pictures/Untitled.png', fmOpenRead); // Создаём поток
      aFileStream.Seek(0, soFromBeginning); // Переходим на начало потока
      aThread.Connection.IOHandler.Write(aFileStream.Size, FALSE); // Посылаем размер потока, чтобы корректно его принять
      aThread.Connection.IOHandler.Write(aFileStream, aFileStream.Size); // Послыаем сам поток
      aFileStream.Free; //Освобождаем поток
    End;
  aThread.Connection.Disconnect; // Отключаемся
End;

Constructor TServer.Create;
Begin
  Inherited Create(nil);
  DefaultPort := 7448; // Назначаем порт
  OnExecute := @Execute; // Назначаем обработчик
  Bindings.Clear; // Магия
  Bindings.Add; // Магия
  Bindings.Items[0].SetPeer('localhost', 7448, id_IPV4);  // Магия
  Active := TRUE;
End;

begin
  With TServer.Create Do
    Begin
      ReadLn;
      Free;
    End;
end.

Client (на форме Image1: TImage):
Код: Выделить всё
Unit Unit1;

{$mode objfpc}{$H+}

Interface

Uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,
    IdTCPClient;

Type

  { TForm1 }

  TForm1 = Class(TForm)
    Image1: TImage;
    Procedure FormCreate(Sender: TObject);
  Private
    { private declarations }
  Public
    { public declarations }
  End;

Var
  Form1: TForm1;

Implementation

{$R *.lfm}

{ TForm1 }

Procedure TForm1.FormCreate(Sender: TObject);
Var
  aSize: Int64;
  aStream: TMemoryStream;
Begin
  With TIdTCPClient.Create(nil) Do //Создаём клиент
    Begin
      Connect('localhost', 7448); // Подключаемся к порту, который слушает сервер
      IOHandler.WriteLn('GiveMeFile'); // Отправляем строку
      aStream := TMemoryStream.Create; // Подготавливаем поток, в который будем считывать картинку
      aSize := IOHandler.ReadInt64; // Берём размер
      IOHandler.ReadStream(aStream, aSize); // Загружаем поток
      aStream.Seek(0, soFromBeginning); // Переходим на начало потока
      Image1.Picture.LoadFromStream(aStream); // Помещаем Загружаем в картинку
      aStream.Free; // Освобождаем поток
      Free; // Освобождаем клиент
    End;
end;

End.

3. Цель? Почему нельзя оставить картинкой? Вообще есть http://www.freepascal.org/docs-html/fcl ... index.html
4. Можно загружать из потока:
Код: Выделить всё

Procedure TForm1.FormCreate(Sender: TObject);
Begin
  Image1.Picture.LoadFromStream(GetStream);
end;

Function TForm1.GetStream: TMemoryStream;
Begin
  // Здесь будет получение потока по сети
  Result := TMemoryStream.Create;
  Result.LoadFromFile('/home/Brainenjii/Documents/Pictures/Untitled.png');
End;

5. Пользоваться редактором привязок: http://wiki.lazarus.freepascal.org/Anchor_Sides
6. xor?
7.
Код: Выделить всё
..
Uses
  ..process..;
..
  With TProcess.Create(nil) Do
    Begin
      CommandLine := './filename';
      Execute;
      Free;
    End;

8. Большую часть этих вопросов можно решить, перенеся приложение в веб
Последний раз редактировалось Brainenjii 31.01.2012 15:13:23, всего редактировалось 1 раз.
Аватара пользователя
Brainenjii
энтузиаст
 
Сообщения: 1351
Зарегистрирован: 10.05.2007 00:04:46

Re: Несколько вопросов для учебного проекта

Сообщение Odyssey » 31.01.2012 14:58:14

veresk писал(а):1. Как правильнее узнать системные пути, кроссплатформенно чтобы? Требуется для считывания файлов конфигурации (в Linux и Windows пути разные будут).
http://www.freepascal.org/docs-html/rtl ... igdir.html
http://wiki.lazarus.freepascal.org/Mult ... tion_files

veresk писал(а):Ну или способ узнать, какая текущая ОС, и уже ориентируясь на это искать файл конфигурации.
{$IFDEF Windows} {код для Windows} {$ENDIF}
{$IFDEF Unix} {код для Unix} {$ENDIF}
{$IFDEF Darwin} {код для MacOS X} {$ENDIF}

veresk писал(а):3. Как перевести картинку в Base64, чтоб можно было сохранить её внутри текстового файла?
http://www.freepascal.org/docs-html/fcl ... tream.html
http://www.lazarus.freepascal.org/index ... l#msg54602

veresk писал(а):4. Как отобразить картинку, не используя LoadFromFile(), как это сделано в исходном приложении? Очень не хочется опять создавать TEMP-папку, распаковывать в неё файлики-картинки и оттуда подгружать.
LoadFromStream

veresk писал(а):5. Как учесть разрешение монитора? Я предполагаю, надо считать ВЫСОТАхШИРИНА и задать размеры контролов в процентах от этого значения. Или я серьёзно не прав?
Серьёзно неправ. См. http://freepascal.ru/article/lazarus/20090217210602/
Если нужно разрешение монитора, его можно получить через Screen.Width и Screen.Height.

veresk писал(а):6. Есть ли способ как-то по-простому зашифровать файлик? Стойкости особо не надо, лишь бы блокнотом не открывалось как простой текст, в принципе.
Для шифрования строк можно использовать
http://www.freepascal.org/docs-html/rtl ... ncode.html
http://www.freepascal.org/docs-html/rtl ... ecode.html
а уже строки писать в файл/читать из файла.
Если нужно шифрование покрепче, то есть
http://wiki.freepascal.org/DCPcrypt
http://www.lazarus.freepascal.org/index ... ic=10970.0

veresk писал(а):7. Как вызвать приложение, находящееся в той же директории, что и вызывающее его? Желательно, кроссплатформенно.
Как вызвать приложение: http://wiki.lazarus.freepascal.org/Exec ... rograms/ru
В той же директории: SysUtils.ExecuteProcess(ExtractFilePath(ParamStr(0)) + 'application_filename.ext'),['arg1','arg2']);
Ещё следует учесть, что в Linux установленные программы обычно размещаются не так, как в Windows:
http://otvety.google.ru/otvety/thread?t ... 8227&pli=1
http://wiki.lazarus.freepascal.org/Mult ... rectory.22

Добавлено спустя 6 минут 21 секунду:
Brainenjii писал(а):8. Большую часть этих вопросов можно решить, перенеся приложение в веб

+1. Только документации по fcl-web маловато, так что даже ссылок подкинуть сложно.
Odyssey
энтузиаст
 
Сообщения: 580
Зарегистрирован: 29.11.2007 17:32:24

Re: Несколько вопросов для учебного проекта

Сообщение Vadim » 31.01.2012 15:07:47

6. Самый простой способ - использовать операцию XOR. Каждая буква может быть представлена как некое число, которое соответствует коду представления буквы в данной ОС. Если мы возьмём некое произвольное число (в качестве пароля), то шифровка и расшифровка будет происходить с помощью одной и той же операции. Естественно, главное будет не перепутать, какой текст Вы скармливаете шифрователю - шифрованный или нешифрованный.
Вот небольшой пример:
Код: Выделить всё
Function Codec(phrase: string): string;
{В качестве параметра функции передаётся текст, который надо зашифровать
или расшифровать.
В качестве результата возвращается зашифрованный или расшифрованный текст}
Var
  password: byte; //Это будет цифра-пароль
  i: integer;
Begin
  password:=18;  //Для примера ;)
  //В этом цикле каждая буква текста будет шифроваться, если текст ещё незашифрован
  //или наоборот, расшифровываться, если текст шифрованый
  For i:=1 To Length(phrase) Do
     phrase[i]:=Char(Ord(phrase[i]) xor password);
  result:=phrase;
End;
Vadim
долгожитель
 
Сообщения: 4112
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: Несколько вопросов для учебного проекта

Сообщение veresk » 31.01.2012 18:11:00

Огромное спасибо!
Даже и не думал, что так быстро и активно помогут на форуме! Буду пробовать и кодить.

Перенести в web - тоже вариант рассмотренный, но там есть некоторые замороки. Читать из файлов плохо тем, что их надо где-то хранить перед открытием, мне такое решение кажется не красивым.
veresk
новенький
 
Сообщения: 48
Зарегистрирован: 31.01.2012 12:23:32

Re: Несколько вопросов для учебного проекта

Сообщение OberonAR » 06.03.2012 15:12:00

7.

Код: Выделить всё
..
Uses
..process..;
..
With TProcess.Create(nil) Do
Begin
CommandLine := './filename';
Execute;
Free;
End;




А является ли этот вариант кроссплатформенным:
'./filename'

Ведь для винды вроде как должно быть '.\filename'. Или просто нужно оформлять оба варианта в тегах IFDEF с указанием целевой ОС?
Аватара пользователя
OberonAR
новенький
 
Сообщения: 73
Зарегистрирован: 08.02.2012 11:46:04
Откуда: Краснодарский край

Re: Несколько вопросов для учебного проекта

Сообщение Sergei I. Gorelkin » 06.03.2012 18:20:31

OberonAR писал(а):Ведь для винды вроде как должно быть '.\filename'. Или просто нужно оформлять оба варианта в тегах IFDEF с указанием целевой ОС?

Вообще, большинство процедур RTL для работы с файлами и путями написаны с претензией на кроссплатформенность, поэтому понимают прямые и обратные слеши и меняют их на те, что нужны целевой системе. Но заглянуть лишний раз в код и убедиться, что это так и в данном конкретном случае, не помешает.
Аватара пользователя
Sergei I. Gorelkin
энтузиаст
 
Сообщения: 1407
Зарегистрирован: 24.07.2005 14:40:41
Откуда: Зеленоград

Re: Несколько вопросов для учебного проекта

Сообщение veresk » 05.06.2012 10:42:14

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

UTF8ToSys(); спасло положение.
veresk
новенький
 
Сообщения: 48
Зарегистрирован: 31.01.2012 12:23:32

Re: Несколько вопросов для учебного проекта

Сообщение xcod » 05.06.2012 11:08:25

TProcessUTF8 Вам в помощь :)
xcod
постоялец
 
Сообщения: 108
Зарегистрирован: 07.08.2009 12:37:23

Re: Несколько вопросов для учебного проекта

Сообщение svk12 » 05.06.2012 17:53:31

veresk писал(а):поэтому понимают прямые и обратные слеши и меняют их на те, что нужны целевой системе


Если использовать константу "PathDelim".
svk12
постоялец
 
Сообщения: 408
Зарегистрирован: 09.06.2008 18:42:47

Re: Несколько вопросов для учебного проекта

Сообщение veresk » 06.06.2012 11:18:04

До сих пор не победил передачу файла по сети. Слишком сложно для быдлокодеришки, типа меня :-(
Поставил LNET, поглядел на всё это безобразие и впал в уныние. Надо что-то типа

Код: Выделить всё
function sendfile(filename: string; ip_remote: string; port_remote: integer): boolean;
begin
end;


Про принимающую сторону вообще мысли вразброд. А дедлайн уже нынче, на этой неделе :-( Поможите, люди! Я-то надеялся на какую-нить реализацию сервера типа FTP, а LNET умеет только FTP-client. А ещё оказалось очень важным размер буфера сетевого, для приличных файлов его мало, надо передавать кусочками. Документации очень мало и руки кривые :-)

ЗЫ. Зато первая часть пакета программ работает хорошо. Умеет создать файл, открыть, отредактировать, сохранить. При этом не падает даже и всё полностью работает и в Linux и Windows. Плюс ко всему, работает офигенно быстро, в отличие от прототипа, которым пользуется техникум сейчас.

Добавлено спустя 1 минуту 36 секунд:
svk12 писал(а):Если использовать константу "PathDelim".


Не понадобилось, слеши автоматически работают. А русские буквы в пути победил отдельно.
veresk
новенький
 
Сообщения: 48
Зарегистрирован: 31.01.2012 12:23:32


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 267

Рейтинг@Mail.ru
cron