Page 1 of 1

Windows: CreateTemporaryFileName

Posted: Wed Jul 28, 2004 11:24 pm
by tinman
Not much past the Win32 API, but takes away all the nasty hassle of doing this yourself or embedding lots of crap inline into your code. See the description in the function header - there's a demo below it.

Code: Select all

; Name:         CreateTemporaryFileName
; Synopsis:     filename = CreateTemporaryFileName(prefix)
; Parameters:   prefix.s - The prefix to be applied to the temporary filename
; Returns:      filename.s - A filename in the temporary directory, with a temporary name
; Globals:      None
; Description:  Creates a filename for a temporary file, which will be in the format of
;               <temp_dir>\<prefix><uuuu>.TMP where temp_dir is the temporary directory (see
;               below), prefix is up to 3 characters from the passed prefix string and
;               uuuu is a unique identifier generated by the OS.
;
;               <temp_dir> calculation (taken from MSDN docs for GetTempPath
;                   The GetTempPath function does not verify that the directory specified by the TMP Or TEMP environment variables exists. The function gets the temporary file path as follows:
;                       The path specified by the TMP environment variable. 
;                       The path specified by the TEMP environment variable, If TMP is not defined. 
;                       The Windows directory, If both TMP And TEMP are not defined. 
;                   Windows Me/98/95:  The GetTempPath function gets the temporary file path as follows:
;                       The path specified by the TMP environment variable. 
;                       The path specified by the TEMP environment variable, If TMP is not defined Or If TMP specifies a directory that does not exist. 
;                       The current directory, If both TMP And TEMP are not defined Or specify nonexistent directories. 
Procedure.s CreateTemporaryFileName(prefix.s)
    DefType.s   filename
    
    DefType.l   temp_path_length            ; Length of the string in the temporary path
    Dim         temp_path.w(0)              ; Array of words (string of TCHARs) to hold the temporary pathname, if required
    Dim         temp_file.w(MAX_PATH + 1)   ; Array of words (string of TCHARs) to hold the temporary filename, if required
    Dim         prefix_oem.w(4)             ; TCHAR string for the prefix string if any
    
    ; Set return filename to empty (to indicate failure of some sort)
    filename = ""
    
    ; Get required length of temporary directory
    temp_path_length = GetTempPath_(0, @temp_path(0)) - 1   ; GTP_() includes terminating NULL, remove that
    If temp_path_length And temp_path_length <= (#MAX_PATH-14)
    
        ; Create TCHAR string for the number of characters required + NULL and get string
        Dim temp_path.w(temp_path_length + 1)
        If temp_path_length = GetTempPath_(temp_path_length + 1, @temp_path(0))

            ; Try to create the prefix 3 characters
            OemToCharBuff_(@prefix, @prefix_oem(0), 3)
            
            ; Get temporary filename in entirety
            If GetTempFileName_(@temp_path(0), @prefix_oem(0), 0, @temp_file(0))
                ; Convert TCHAR string to ASCII, for use with PB
                filename = Space(temp_path_length)
                If CharToOem_(@temp_file(0), @filename)=0
                    filename = ""
                EndIf ; Failed to convert the TCHAR string to ASCII
            EndIf ; Created a temporary filename
        EndIf ; Temporary path copied successfully
    EndIf ; Temporary path had a valid length

    ProcedureReturn filename
EndProcedure

tfn.s = CreateTemporaryFileName("foo")
If tfn<>"" And CreateFile(0, tfn)
    WriteStringN("Hello, I am a temporary file")
    CloseFile(0)
Else
    MessageRequester("Gack!", "Could not create temporary file", #PB_MessageRequester_OK)
EndIf
End
PS, I searched here (and the Code Archive) first but could only find some discussion of GetTempFileName_(), but nothing showing a simple way to use it, so apologies if this already exists somewhere.

Re: Windows: CreateTemporaryFileName

Posted: Thu Jul 29, 2004 4:44 am
by PB
Bah, I just do this (much simpler and smaller code):

Code: Select all

Procedure.s CreateTempFile()
  tmpdir$=Space(255) : GetTempPath_(255,tmpdir$)
  Repeat : file$=tmpdir$+Str(Random(99999999)) : Until FileSize(file$)=-1
  ProcedureReturn file$
EndProcedure

tfn$=CreateTempFile()
If tfn$<>"" And CreateFile(0,tfn$)
  WriteStringN("Hello, I am a temporary file")
  CloseFile(0)
Else
  MessageRequester("Gack!", "Could not create temporary file", #PB_MessageRequester_OK)
EndIf 
It actually works extremely well. For it to fail, you'd need 99999999 numbered
files in your system's TEMP folder to exist, which is unlikely to ever be the case.

;)

Posted: Thu Jul 29, 2004 4:31 pm
by sec
will be nice if purebasic use these stuffs to create temp file/test file instead of installed dir or in C:\ as some reports. So purebasic windows xp/2000 compliant :D

Re: Windows: CreateTemporaryFileName

Posted: Thu Jul 29, 2004 4:45 pm
by GPI
@PB

two problems. First: You Temp-Directory-Variabel is a little bit too small.

Code: Select all

  tmpdir$=Space(#Max_Path) : GetTempPath_(#Max_Path,tmpdir$)
Second: With your routine it is possible, You have no prevention for doubles. For example when you start your program more than on, it is possible, that two ditances of your program will use your temp twice...


By the way: This is shorter and work too

Code: Select all

Procedure.s CreateTempFile(); - Return an name for temporary files (the file is created and closed!)
  temp$=Space(#MAX_PATH)
  tmpdir$=Space(#MAX_PATH) : GetTempPath_(#MAX_PATH,tmpdir$)
  If GetTempFileName_(@tmpdir$,@"~PB",0,@temp$)=0
    temp$=""
  EndIf
  ProcedureReturn temp$
EndProcedure

Re: Windows: CreateTemporaryFileName

Posted: Thu Jul 29, 2004 4:56 pm
by tinman
GPI wrote:

Code: Select all

  If GetTempFileName_(@tmpdir$,@"~PB",0,@temp$)=0
I thought that using the TCHAR strings required two bytes per character, that's why my code is a bit longer. Or is it that PureBasic only calls the ASCII version of the function (if it exists)?

Posted: Thu Jul 29, 2004 5:04 pm
by sec
sec wrote:. So purebasic windows xp/2000 compliant :D
it is PB IDE windows xp/2000 compliant . (sorry)
wow 130 posts

Re: Windows: CreateTemporaryFileName

Posted: Thu Jul 29, 2004 5:53 pm
by GPI
tinman wrote:I thought that using the TCHAR strings required two bytes per character, that's why my code is a bit longer.
MSDN wrote:UINT GetTempFileName(
LPCTSTR lpPathName,
LPCTSTR lpPrefixString,
UINT uUnique,
LPTSTR lpTempFileName
);

Parameters
lpPathName
[in] Pointer to a null-terminated string that specifies the directory path for the file name. Applications typically specify a period (.) for the current directory or the result of the GetTempPath function. The string cannot be longer than MAX_PATH-14 characters. If this parameter is NULL, the function fails.
lpPrefixString
[in] Pointer to a null-terminated prefix string. The function uses up to the first three characters of this string as the prefix of the file name. This string must consist of characters in the OEM-defined character set.

Re: Windows: CreateTemporaryFileName

Posted: Thu Jul 29, 2004 6:21 pm
by tinman
GPI wrote:
MSDN wrote:UINT GetTempFileName(
An actual answer to my question might have been nice rather than a cut and paste from a document which I obviously looked at to get the use of the function.

My confusion came from the size of a TCHAR and mentions of "OEM" strings. It seems it is 1 byte, although in the windows headers it is possible to have it defined as a WCHAR which is 2 bytes but I don't know whether or when it would ever be.

But thanks for your explanation. It really helped.

Posted: Thu Jul 29, 2004 8:08 pm
by GPI
Where stand something about TCHAR in the description?

Re: Windows: CreateTemporaryFileName

Posted: Thu Jul 29, 2004 9:42 pm
by PB
> You Temp-Directory-Variabel is a little bit too small.

#MAX_PATH = 260, and I used 255 (a common number)... it's only 5 characters
shorter, which isn't really a problem; especially considering that on all versions
of Windows the TEMP folder path is never more than 100 chars (I've checked).

> it is possible, that two ditances of your program will use your temp twice.

It's not possible, because the temp file only gets created if it doesn't already
exist (FileSize=-1), so two instances of my app simply can't use the same file.

Posted: Thu Jul 29, 2004 9:52 pm
by tinman
GPI wrote:Where stand something about TCHAR in the description?
from winnt.h

"typedef const TCHAR *LPCTSTR;"

Posted: Fri Jul 30, 2004 7:50 pm
by Flype
maybe it's because TCHARs are coded the same way than ASCII...
if it's the case TCHARs are for encoding UTF-8 not UNICODE.
somebody can confirm ?

taken from this url :
http://www.ioplex.com/~miallen/libmba/d ... tails.html

Code: Select all

TCHAR in Microsoft Windows
For programmers that have used the variety of string handling functions on the Microsoft Windows platform this character abstraction technique should look familar. It is indeed the same. The abstract character type in the Win32 environment is named TCHAR in uppercase rather than lower and the string functions are prefixed with _tcs like _tcsncpy rather than tcsncpy but after macro processing the resulting code is the same. The identifier names where chosen to be the same as those found on Windows (minus a few Windows coding conventions that clash with Unix/Linux conventions) simply becuase the Windows platform is very popular and there was no practical reason to use different names. The exception is that USE_WCHAR is used to signal that wide characters should be used rather than _UNICODE because on Unix and Unix-like systems multi-byte strings support Unicode in the UTF-8 locale which would make the _UNICODE macro somewhat inaccurate.