Welcome, Guest
Username: Password: Remember me
This public forum is meant for questions and discussions about Visual FoxPro
  • Page:
  • 1
  • 2

TOPIC:

StrToFile ( cExpression, cFileName [, lAdditive | nFlag]) 01 Jun 2020 20:19 #14794

  • Karl-Heinz
  • Karl-Heinz's Avatar
  • Topic Author


  • Posts: 774
  • Hi Antonio,

    I think we're addressing different issues, here. What I said was that I wouldn't feel too comfortable to have error messages as literal strings spreading around the code. That would not be beneficial to localization and style consistency. So, THROW SomeException {} instead of THROW SomeException { "Error message" }.

    The VO Dialect has predefined and localized error messages, and Robert has already added to VFP some predefined error messages. Try this
    ? __VfpStr(VFPErrors.INVALID_DATE)
    ? __VfpStr(VFPErrors.INVALID_RANGE)

    Take a look at these VFP sources where you can see how __VfpStr() is used. github.com/X-Sharp/XSharpPublic/blob/a9b...FP/DateFunctions.prg But I think at the moment it is more important to write VFP functions ;-)

    As per the help file,

    Using THROW within a CATCH block without any arguments re-throws the exception, passing it unchanged to the next highest TRY-CATCH block.

    you are right, i haven't noticed that this does the same !
    TRY       
    	do some nonsense here ;-)
    
    CATCH 
    
        THROW 	
    	
    END TRY

    thanks for the hint !

    regards
    Karl-Heinz

    Please Log in or Create an account to join the conversation.

    StrToFile ( cExpression, cFileName [, lAdditive | nFlag]) 03 Jun 2020 22:07 #14835

    • atlopes
    • atlopes's Avatar


  • Posts: 84
  • Karl-Heinz,

    Thank you for your directions. That was really important to know.

    Now, back to some more VFP functions...

    Please Log in or Create an account to join the conversation.

    StrToFile ( cExpression, cFileName [, lAdditive | nFlag]) 22 Jun 2020 16:31 #15053

    • robert
    • robert's Avatar


  • Posts: 3595
  • Guys,
    What is the status of this function now?
    Does anybody have the 'final' version ?

    Robert
    XSharp Development Team
    The Netherlands

    Please Log in or Create an account to join the conversation.

    StrToFile ( cExpression, cFileName [, lAdditive | nFlag]) 23 Jun 2020 01:09 #15054

    • atlopes
    • atlopes's Avatar


  • Posts: 84
  • Robert (and Karl-Heinz),

    This is what I came up with, taking into consideration the remarks from Karl-Heinz. I tested the interoperability of these functions (STRTOFILE() and FILETOSTR()) with VFP and they seem to be working as expected.

    A test can be performed against binary files by reading and then writing an image file, for instance:
    STRTOFILE(FILETOSTR("C:\Temp\image.jpg"), "C:\Temp\copy of image.jpg")

    The proposed "final" implementation:
    * VFP standard flags
    DEFINE S2F_FLAG_OVERWRITE           = 0x0000
    DEFINE S2F_FLAG_APPEND              = 0x0001
    DEFINE S2F_FLAG_UNICODE_LE          = 0x0002
    DEFINE S2F_FLAG_UTF8                = 0x0004
    * X# extension flags
    DEFINE S2F_FLAG_UNICODE_BE          = 0x0008
    DEFINE S2F_FLAG_UNICODE_FORMATS     = S2F_FLAG_UNICODE_LE | S2F_FLAG_UTF8 | S2F_FLAG_UNICODE_BE
    DEFINE S2F_FLAG_UNICODE_TEXT        = 0x0100
    
    FUNCTION StrToFile (Expression AS String, Filename AS String) AS Int
        RETURN StrToFile(Expression, Filename, S2F_FLAG_OVERWRITE)
    
    FUNCTION StrToFile (Expression AS String, Filename AS String, Additive AS Boolean) AS Int
        RETURN StrToFile(Expression, Filename, IIF(Additive, S2F_FLAG_APPEND, S2F_FLAG_OVERWRITE))
    
    FUNCTION StrToFile (Expression AS String, Filename AS String, Flags AS Int) AS Int
        
        LOCAL Additive = .F. AS Boolean
        LOCAL BOM = "" AS String
        LOCAL Result = 0 AS Int
        LOCAL FHandle AS Int
        LOCAL VFPBehavior = .T. AS Boolean      // it means the string must hold an already prepared buffer, or it is binary
        LOCAL UnicodeEncoding AS System.Text.Encoding
        LOCAL IOError AS Exception
    
        DO CASE
            * VFP behavior, append to a file with no Unicode encoding
            CASE Flags = S2F_FLAG_APPEND
                Additive = .T.
                
            * VFP behavior, create a Unicode file (source buffer already prepared)
            CASE Flags = S2F_FLAG_UNICODE_LE
                BOM = e"\xFF\xFE"
    
            * VFP behavior, create a UTF-8 file (source buffer already prepared)
            CASE Flags = S2F_FLAG_UTF8
                BOM = e"\xEF\xBB\xBF"
    
            * extension to VFP behavior, create a Unicode Big-Endian file (source buffer already prepared)
            CASE Flags = S2F_FLAG_UNICODE_BE
                BOM = e"\xFE\xFF"
    
            * if not simply overwrite, the file will be treated as a Unicode text file
            CASE Flags != S2F_FLAG_OVERWRITE
    
                IF (Flags & S2F_FLAG_UNICODE_TEXT) != 0
    
                    VFPBehavior = .F.
                    
                    Additive = (Flags & S2F_FLAG_APPEND) != 0
                
                    * set the Unicode encoding
                    SWITCH Flags & S2F_FLAG_UNICODE_FORMATS
                        CASE S2F_FLAG_UNICODE_LE
                            UnicodeEncoding = System.Text.Encoding.Unicode
                            
                        CASE S2F_FLAG_UTF8
                            UnicodeEncoding = System.Text.Encoding.UTF8
                            
                        CASE S2F_FLAG_UNICODE_BE
                            UnicodeEncoding = System.Text.Encoding.BigEndianUnicode
                            
                        * error if Unicode encoding not properly set
                        OTHERWISE
                            THROW ArgumentException {}
                            
                    END SWITCH
                ELSE
                    THROW ArgumentException {}
                ENDIF
        END CASE
        
        * append mode?
        IF Additive
    
            IF VFPBehavior
    
                * open an existing file, or create if it does not exists
                FHandle = FOpen(Filename, FO_READWRITE + FO_SHARED)
                IF FHandle != F_ERROR
                    * try to move to the end of the file
                    FSeek3(FHandle, 0, FS_END)
                    * and write the contents of the buffer
                    IF FError() == 0
                        Result = FWrite(FHandle, Expression)
                    ENDIF
                    * if everything went ok, close the file handle
                    IF FError() == 0
                        FClose(FHandle)
                        IF FError() != 0
                            THROW FException()
                        ENDIF
                    * if not, before throwing the exception...
                    ELSE
                        IOError = FException()
                        FClose(FHandle)         // ... try to close the handle, anyway
                        THROW IOError
                    ENDIF
                ELSE
                    THROW FException()
                ENDIF
                
            ELSE
                
                * in non-VFP behavior, just append the Unicode string to an existing file
                TRY
                    File.AppendAllText(Filename, Expression, UnicodeEncoding)
                CATCH
                    THROW
                ENDTRY
                    
                Result = Expression:Length
                
            ENDIF
    
        ELSE
            
            * TO-DO: check on SET("Safety") 
    
            * create a new file
            IF VFPBehavior
            
                * get an handle for a new file
                FHandle = FCreate(Filename)
                IF FHandle != F_ERROR
                    * start with the BOM of the file
                    IF ! (BOM == "")
                        Result = FWrite(FHandle, BOM)
                    ENDIF
                    * try to write the contents from the buffer
                    IF FError() == 0
                        Result += FWrite(FHandle, Expression)
                    ENDIF
                    * and close the file
                    IF FError() == 0
                        FClose(FHandle)
                        IF FError() != 0
                            THROW FException()
                        ENDIF
                    * if an error occurred...
                    ELSE
                        IOError = FException()
                        FClose(FHandle)     // ... try to not leave the handle open, in any case
                        THROW IOError
                    ENDIF
                ELSE
                    THROW FException()
                ENDIF
     
            ELSE
                
                * write the Unicode string to a text file
                TRY
                    File.WriteAllText(Filename, Expression, UnicodeEncoding)
                CATCH
                    THROW
                ENDTRY
                
                Result = Expression:Length
                
            ENDIF
    
        ENDIF
    
        * return the length of bytes / characters
        RETURN Result
    
    ENDFUNC
    
    FUNCTION FileToStr (Filename AS String) AS String
        RETURN FileToStr(Filename, S2F_FLAG_OVERWRITE)
    
    FUNCTION FileToStr (Filename AS String, Flags AS Int) AS String
        
        LOCAL FHandle AS Int
        LOCAL StrLen AS Int
        LOCAL Result = "" AS String
        LOCAL IOError AS Exception
    
        IF (Flags & S2F_FLAG_UNICODE_TEXT) = 0      // VFP behavior, read file as binary, even if it is a Unicode text
    
            * TO-DO - work with the SET("Path") setting to look for a file
    
            FHandle = FOpen(Filename, FO_READ + FO_SHARED)
            IF FHandle != F_ERROR
                * success opening the file, get its size...
                StrLen = FSize(FHandle)
                IF StrLen > 0
                    * ...and allocate a buffer for it
                    Result = SPACE(StrLen)
                    IF FRead(FHandle, @Result, StrLen) != StrLen
                        Result = ""
                    ENDIF
                ELSE
                    Result = ""
                ENDIF
                * any IO error will throw an exception
                IF FError() != 0
                    IOError = FException()
                    FClose(FHandle)
                    THROW IOError
                ELSE
                    FClose(FHandle)
                ENDIF
            ELSE
                THROW FException()
            ENDIF
    
        ELSE
            
            * for a Unicode text file, just read it into a string 
            TRY
                Result = File.ReadAllText(Filename)     // read a text file
            CATCH
                THROW
            ENDTRY
            
        ENDIF
    
        * return the contents of the file
        RETURN Result
        
    ENDFUNC

    Please Log in or Create an account to join the conversation.

    • Page:
    • 1
    • 2