• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 277
  • Last Modified:

Change local to relative url

Hi all,

I have some url's in a memo which look like this:

c:\somefolder\someimage.jpg

I need to change them to:

/images/someimage.jpg

hope you can help

thx

st3vo
0
ST3VO
Asked:
ST3VO
  • 10
  • 8
  • 2
  • +1
1 Solution
 
BdLmCommented:

can you use :

http://www.experts-exchange.com/Programming/Languages/Pascal/Delphi/Q_20652014.html

below the code for the inverse function

function GetabsolutePath(Source, Relative: string): string;
var
    i, Num, num1: integer;
    St: TStringList;
    s: string;
begin
    Num := GetappearNum('..', Relative);
    St := TStringList.Create;
    decomposestr('\', Source, st);
    Num1 := st.Count;

    Result := '';

    for i := 0 to num1 - num - 1 do
    begin
        Result := Result + st[i];
    end;
    s := CopyRightNum('..\', Relative, 1);
    Result := Result + s;
    st.Free;
end;

Open in new window

0
 
epasquierCommented:
You basically have to replace in your string : 'c:\somefolder\' with '/images/' and eventually all remaining '\' into '/' so :

NewPath:=ReplacePath2URL('c:\somefolder\someimage.jpg', 'c:\somefolder\',  '/images/');
Function ReplacePath2URL(FileName,Path1, Path2:String):String;
Var
 P:Integer;
begin
 P:=Length(Path1);
// first check that FileName is starting with Path1
 if UpperCase(LeftStr(FileName,P))<>UpperCase(Path1) Then Raise Exception.Create('Bad start path');
 Result:=Path2+Copy(FileName,P+1,Length(FileName)-P);
// Then replace all '\' with '/'
 Result:=StringReplace(Result,'\','/',[rfReplaceAll]);
end;

Open in new window

0
 
ST3VOAuthor Commented:
Thanks epasquier,

I've give it a try right after work :o)
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
ST3VOAuthor Commented:
Hmm...sorry I don't think I expressed myself properly.

In a memo...

I need to replace anything that looks like this:

c:\somefolder\someimage.jpg

to:

/images/someimage.jpg

So, if we get the source path:

c:\somefolder\someimage.jpg ...anything but the filename "someimage.jpg"  is stripped off and "/images/" is added in it's place.

Hope this is clearer...sorry about that and thanks!



0
 
epasquierCommented:
Ok.
Then let's first replace all 'c:\somefolder\' with '/images/', then rescan the string for all occurences of '/images/' and replace all following '\' with '/' up to the first invalid character for a filename.
Function ReplacePath2URL(Str,Path1, Path2:String):String;
Var
 P,L,LP2:Integer;
begin
 Result:= StringReplace(Str, Path1, Path2,                          
             [rfReplaceAll, rfIgnoreCase]);
 P:=1;
 L:=Length(Result);
 LP2:=Length(Path2);
 Repeat
  P:=PosEx(Result,Path2,P);
  if P>0 Then 
   begin
    P:=P+LP2;
    while (P<=L) and Not (Result[P] In [#0..#31, '<','>','"','?','*']) do
     begin
      if Result[P]='\' Then Result[P]:='/';
      inc(P);
     end;
   end;
 Until (P>L) Or (P=0);
end;

Open in new window

0
 
ST3VOAuthor Commented:
Cool...will check it as soon as I get home...thanks :o)
0
 
epasquierCommented:
I made the same mistake again with PosEx, the order of the parameters is wrong
Function ReplacePath2URL(Str,Path1, Path2:String):String;
Var
 P,L,LP2:Integer;
begin
 Result:= StringReplace(Str, Path1, Path2,                          
             [rfReplaceAll, rfIgnoreCase]);
 P:=1;
 L:=Length(Result);
 LP2:=Length(Path2);
 Repeat
  P:=PosEx(Path2,Result,P);
  if P>0 Then 
   begin
    P:=P+LP2;
    while (P<=L) and Not (Result[P] In [#0..#31, '<','>','"','?','*']) do
     begin
      if Result[P]='\' Then Result[P]:='/';
      inc(P);
     end;
   end;
 Until (P>L) Or (P=0);
end;

Open in new window

0
 
ST3VOAuthor Commented:
Hi epasquier,

Do you have a usage example via memo please?

thx again!


0
 
epasquierCommented:
Memo.Text:=ReplacePath2URL(Memo.Text, 'c:\somefolder\',  '/images/');
0
 
ST3VOAuthor Commented:
Can c:\somefolder\ be any path that's local or do I have to manually specify the local paths?

thx

0
 
epasquierCommented:
you must have a limited list of pairs like 'c:\somefolder\' => '/images/'
find the best way that suits your needs to define such a pair list and call the function ReplacePath2URL for each
There is no other generic way
0
 
ST3VOAuthor Commented:
Sorry about my delay (christmas party's)  

Merry xmas by the way...

Anyway...could it be something like:

Memo.Text:=ReplacePath2URL(Memo.Text, 'c:\*',  '/images/');

So basically if the url has a c:\ ...we know it's local ... then it will replace the c:\ and whatever folders follow it to /images/ ...know what I mean?


thx
0
 
Ferruccio AccalaiSenior developer, analyst and customer assistance Commented:
I don't wanna take nothing to epasquier, but as I've understood how ST3VO is working and what he need I've created a function specified for his purpose.

It must be a little described.
To replace any occurrence of c:\somefolder\someimage.jpg, or c:\somefolder\somotherfolder\someotherimage.jpg or c:\somefolderagain\someother\whateverimage.jpg we must know first of all a point of start and one of end to search between them.
So the function is
function CustomReplace(Text, PathPortion, Replacing, Ext: String): String;
where
Text => The string that we must parse (e.g. Memo1.text)
PathPortion => the portion of the path we are starting to look for (e.g. 'c:\')
Replacing => what we want replace with (e.g. '/images/')
Ext => The extension of the images, needed to find the exact part of the path that must be replaced (e.g. '.jpg'), skipping the filename;

So now we can
1) find any C:\
2) from there find the .jpg starting from there
3) get the path that must be replaced reading back from that .jpg until we find the '\' (that is back where filename starts)
4) replace the found path with our Replacing value
and so on.
Better to see than explain.
Try the code attached.
function CustomReplace(Text, PathPortion, Replacing, Ext: String): String;
  var
    s, temp, temppath: String;
    i, t: integer;
  begin
    s := Text; // get the text from Memo
    while pos(PathPortion, Text) > 0 do
    begin
      temp := '';
      i := pos(PathPortion, Text); // found drive
      begin
        t := posex(Ext, Text, i+3)-1;
        while Text[t] <> '\' do
        begin
          temp := Text[t]+temp;
          dec(t);
        end;
        temppath := copy(Text, i, t-i+1);
        Text := stringreplace(Text, temppath, Replacing, []);
      end;
    end;
    result := Text;
  end;

Use it as follows
Memo1.Text := CustomReplace(Memo1.Text, 'c:\', '/images/', '.jpg');

Open in new window

0
 
Ferruccio AccalaiSenior developer, analyst and customer assistance Commented:
Just a little beautify, as there's a Var declared Temp that I've used to test filenames, but that you don't need.
This version is a little clean

function CustomReplace(Text, PathPortion, Replacing, Ext: String): String;
  var
    s, temppath: String;
    i, t: integer;
  begin
    s := Text; // get the text from Memo
    while pos(PathPortion, Text) > 0 do
    begin
      i := pos(PathPortion, Text); // found drive
      begin
        t := posex(Ext, Text, i+3)-1;
        while Text[t] <> '\' do
          dec(t);
        temppath := copy(Text, i, t-i+1);
        Text := stringreplace(Text, temppath, Replacing, []);
      end;
    end;
    result := Text;
  end;

Open in new window

0
 
ST3VOAuthor Commented:
Hmmm testing both:

Memo1.Text := CustomReplace(Memo1.Text, 'c:\', '/images/', '.jpg');
Memo1.Text := CustomReplace(Memo1.Text, 'c:\', '/images/', '.jpg'); <-- uppercase C

But it's not doing anything...Does it check the whole memo1 text from top to bottom for c:\  ???

0
 
ST3VOAuthor Commented:
My mistake...ignore my last comment...works perfect :o) Thx!!!
0
 
ST3VOAuthor Commented:
Works Perfect thx!!!
0
 
epasquierCommented:
ST3VO, when you change or precise your specifications after a while, you could at least split points to recognize initial work.

Ferruccio : That's a good thinking to take the file extension as a reference and look back for the previous slash. Still, you could have optimized :
- by first calculating i=Pos and test it instead of calling twice
- by using PosEx even for that in order to start looking other path to replace not from the beginning each time
- use 2 copy with your positions instead of one to find the middle one to extract and then call StringReplace, which will refind the position you already have
- and you have a bug in this line : t := posex(Ext, Text, i+3)-1;
instead of 3 you should have Length(PathPortion) - which equals 3 in this example only


function CustomReplace(Text, PathPortion, Replacing, Ext: String): String;
Var
 i, t, L : integer;
begin
 L:=Length(Replacing);
 i := pos(PathPortion, Text); // found drive
 while i > 0 do
  begin
   t := posex(Ext, Text, i+Length(PathPortion))-1;
   while Text[t] <> '\' do dec(t);
   Text := Copy(Text,1,i-1)+Replacing+Copy(Text,t+1,Length(Text)-t);
   i := posEx(PathPortion, Text, i+L ); 
  end;
 Result:=Text;
end;

Open in new window

0
 
epasquierCommented:
ST3VO, when you change specs in the middle of a thread you could at least split points to recognize initial work or better yet close and reopen a new question.

Ferruccio, nice thinking to use extension as reference. Still, you could optimize a lot
- call Pos once to calculate i at first and use it for the while loop
- call PosEx to update i at each end of loop, not searching from the beginning
- use directly 2 copy with i and t to replace instead of using copy and stringreplace, which will have to refind first the position
- you have a bug in the line t := posex(Ext, Text, i+3)-1;
you should use Length(PathPortion) instead of 3 even if in this example it's the correct value


function CustomReplace(Text, PathPortion, Replacing, Ext: String): String;
var
  i, t, L: integer;
begin
 L:=Length(Replacing);
 i := pos(PathPortion, Text); // found drive
 while i > 0 do
  begin
   t := posex(Ext, Text, i+Length(PathPortion))-1;
   while Text[t] <> '\' do dec(t);
   Text := Copy(Text,1,i-1)+Replacing+Copy(Text,t+1,Length(Text)-t);
   i := posEx(PathPortion, Text, i+L );
  end;
 Result:=Text;
end;  
0
 
epasquierCommented:
please forget the message sent twice as I was on the list of question interface, and it seems that a bug prevent from seeing comments of closed questions there. I supposed that the first message did not go through because I was attaching code.
0
 
ST3VOAuthor Commented:
Hi epasquier, sorry about that, didn't realize I changed the specs...
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

  • 10
  • 8
  • 2
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now