copyfile routine containing apostrophes lazarus / 10-Designer ---------------------------------------------------------------------- cazzajay · 2011-05-11 08:05 another query - thought id put it in a new topic in case anyone else does a search in the future for this: Code: [Select]var fullpathsrc: string; fullpathdest: string; begin copyfile(pchar(fullpathsrc), pchar(fullpathdest), false) end; if either fullpathsrc or fullpathdest contain an apostrophe above the procedure fails to copy the file.  I'm guessing this is because in pascal strings are terminated by an apostrophe, but is there a way around it - since Windows allows the use of an apostrophe in a filename? One counter to my above assertion is that if you do a showmessage(fullpathdest) it shows the whole string not just up to the first apostrophe as I would have expected.  Leading me to think it could also be to do with the PChar conversion? I have done my own research - but nobody else seems to have had this problem. Loads of articles explain how to use CopyFile (eg http://www.swissdelphicenter.ch/torry/showcode.php?id=101) but none seem to explain how to get around this? Thanks again for any help ---------------------------------------------------------------------- Arbee · 2011-05-11 08:37 How about scanning the strings and duplicating every single quote you encounter.  AFAIK two single quotes in a string in Pascal is interpreted as one. ---------------------------------------------------------------------- Bart · 2011-05-11 09:10 Maybe the underlying OS call interprets an apostroph? What happens if you place quotes (") around the filename? Which OS are you using? Bart ---------------------------------------------------------------------- cazzajay · 2011-05-11 10:06 Quote from: Arbee on May 11, 2011, 10:37:31 amHow about scanning the strings and duplicating every single quote you encounter.  AFAIK two single quotes in a string in Pascal is interpreted as one. i thought about that but cant really think how to do it. this obviously doesnt work because of the odd number of apostrophes: Code: [Select]fullpathdest := stringreplace(fullpathdest, ''', '''', [rfReplaceAll]); ---------------------------------------------------------------------- cazzajay · 2011-05-11 10:08 Quote from: Bart on May 11, 2011, 11:10:06 amMaybe the underlying OS call interprets an apostroph? What happens if you place quotes (") around the filename? Which OS are you using? Bart os=windows placing quotes doesnt affect anything. i used the code below to do it Code: [Select]fullpathdest := '"'+fullpathdest+'"' ---------------------------------------------------------------------- Laksen · 2011-05-11 10:27 Windows doesn't allow " in filenames. It's used in terminals to indicate a filename with space characters in it as a single path, but that doesn't make sense in a programming language where strings are a known length ---------------------------------------------------------------------- Arbee · 2011-05-11 11:11 I guess when doing a replace you will have to do the same duplication of single quotes: Code: [Select]fullpathdest := stringreplace(fullpathdest, '''', '''''', [rfReplaceAll]); ---------------------------------------------------------------------- cazzajay · 2011-05-11 11:56 Quote from: Arbee on May 11, 2011, 01:11:36 pmI guess when doing a replace you will have to do the same duplication of single quotes: Code: [Select]fullpathdest := stringreplace(fullpathdest, '''', '''''', [rfReplaceAll]); again, that doesn't work. I'm wondering if I could use an ascii reference. And even so, is the apostrophe the issue? Its not an issue when the variable is referenced in a showmessage, only in a copyfile (via Pchar conversion) ---------------------------------------------------------------------- Arbee · 2011-05-11 12:08 Have you tried doing the file copy with a TFileStream?  I don't know if it will work, but may be worth a try. ---------------------------------------------------------------------- cazzajay · 2011-05-11 12:14 Quote from: Arbee on May 11, 2011, 02:08:47 pmHave you tried doing the file copy with a TFileStream?  I don't know if it will work, but may be worth a try. ok ive put a new procedure as follows: Code: [Select]Procedure TSFileCopy(sourcefilename, targetfilename: String); Var  S, T: TFileStream; Begin  S := TFileStream.Create( sourcefilename, fmOpenRead );  try    T := TFileStream.Create( targetfilename,                             fmOpenWrite or fmCreate );    try      T.CopyFrom(S, S.Size ) ;    finally      T.Free;    end;  finally    S.Free;  end; End;  and then call this instead of copyfile Code: [Select]TSfilecopy(fullpathsrc, fullpathdest) it works fine for lower ascii files, but it gives me an exception stating that it "cannot read from file" if the filename contains upper ascii chars (its a song by singer bjork - the file is called "Björk - Possibly Maybe.mp3".  However, this song could be copied using the old copyfile. so im guessing this may not work etiher. btw- obtained code from http://www.awitness.org/delphi_pascal_tutorial /code_samples/file_copy_delphi.html ---------------------------------------------------------------------- eny · 2011-05-11 12:33 Quote from: cazzajay on May 11, 2011, 12:08:17 pmos=windows placing quotes doesnt affect anything. i used the code below to do it Code: [Select]fullpathdest := '"'+fullpathdest+'"' Back to the original question: Windows has no problem whatsoever to handle filenames with apostrophes ('single quotes'). You'd better check the actual contents of the 2 variables you use before executing the file copy. Another question: why do you typecast the filenames to PChar? Copyfile accepts normal string parms. ---------------------------------------------------------------------- cazzajay · 2011-05-11 12:37 Quote from: eny on May 11, 2011, 02:33:11 pmBack to the original question: Windows has no problem whatsoever to handle filenames with apostrophes ('single quotes'). You'd better check the actual contents of the 2 variables you use before executing the file copy. I have, the strings are fine and true with the apostrophes intact. I verified this using a showmessage.  The issue is when this is passed to copyfile, it falls over. Quote from: eny on May 11, 2011, 02:33:11 pmAnother question: why do you typecast the filenames to PChar? Copyfile accepts normal string parms. i must be doing something wrong?. see attached screenshot of v0.9.30 thanks all for your help and time with this! ---------------------------------------------------------------------- eny · 2011-05-11 12:43 Try the CopyFile function in the FileUtil unit. BTW: were you using JwaWinBase.FileCopy? If so, that function is not UTF8 compliant. Before calling that function you should translate the source and destination name to ansi strings and then it does work (even with accented characters). ---------------------------------------------------------------------- cazzajay · 2011-05-11 12:59 Quote from: eny on May 11, 2011, 02:43:00 pmTry the CopyFile function in the FileUtil unit. BTW: were you using JwaWinBase.FileCopy? If so, that function is not UTF8 compliant. Before calling that function you should translate the source and destination name to ansi strings and then it does work (even with accented characters). omg that worked a charm! super thanks!!! i was using the windows unit - not sure if thats the same as jwawinbase? anyway with fileutil it works a treat! ---------------------------------------------------------------------- cazzajay · 2011-05-11 13:39 hmm - just noticed that FileExists does not work with these accented chars, or apostrophes, too.  now i am using only fileutils. in the following: Code: [Select]var fullpathsrc: string; begin fullpathsrc := 'Björk - Possibly Maybe.mp3'; if fileexists('C:\music\' + fullpathsrc) = false then showmessage('File Does Not Exist'); end; will return false and show the message even if the file does exist in the location.  But only exhibits this behaviour for the songs with upper ascii in the name, or an apostrophe. ---------------------------------------------------------------------- cazzajay · 2011-05-11 13:44 having played about a bit more - a dirty solution to this is to use FileSize and say if > 0 then it exists. that seems to work (just in case someone else has the same problem in future and searches the forum) ---------------------------------------------------------------------- eny · 2011-05-11 14:20 Quote from: cazzajay on May 11, 2011, 03:39:00 pmhmm - just noticed that FileExists does not work with these accented chars, or apostrophes, too All works perfectly well; you just shouldn't mix ansi and utf8 character sets. If you use special characters (like ö) you should use either   FileExistsUTF8(...) or   FileExists(UTF8toAnsi(...)) ---------------------------------------------------------------------- cazzajay · 2011-05-11 15:02 Quote from: eny on May 11, 2011, 04:20:48 pmQuote from: cazzajay on May 11, 2011, 03:39:00 pmhmm - just noticed that FileExists does not work with these accented chars, or apostrophes, too All works perfectly well; you just shouldn't mix ansi and utf8 character sets. If you use special characters (like ö) you should use either   FileExistsUTF8(...) or   FileExists(UTF8toAnsi(...)) sweet. out of curiosity, does UTF8toAnsi convert the characters to their "nearest equivalent" i.e.: ö -> o ?? and what does it do to chars that dont have an obvious equivalent?