Article ID 1693
Article Title INFO: CSV file format problems
Article URL http://www.dataaccess.com/kbasepublic/KBPrint.asp?ArticleID=1693
KBase Category Visual DataFlex
Date Created 10/01/2002
Last Edit Date 02/01/2005


Article Text
The "CSV" abbreviation as data exchange format stands for Comma Separated Values. In such a file the character data (strings) should be enclosed by double or single quotes. Numeric data can have a decimal separator, which is a decimal point (dot) in the USA, and a comma in Europe. So, when the system reads a comma, should this be considered a value terminator or a decimal separator?
For this the value separator character has been made configurable in Windows and is set to semi-colon in Europe. The DataFlex READ command, however, does always expect a comma as value terminator and does not use the Windows Locale setting called ListSeparator. This means that if you want to use the READ command your data should contain a dot as decimal separator and the DF_DECIMAL_SEPARATOR should be set to (Ascii (".")) before reading. Thousand separators should not be present in CSV files.

If your CSV file does not use the comma as value separator, you can use a function like:

Function ReadData Integer iChannel Returns String
    String sData sCharacter sListSeparator sLiteralTerminator
    Boolean bEndOfValue bFirstChar bInLiteral

    // Get the Windows Locale Listseparator (see Article link).
    Get LocaleListSeparator To sListSeparator

    Move True To bFirstChar // For TRUE/FALSE see also article link

    Repeat
        // Read character by character until the listseparator has been found.
        Read_Block Channel iChannel sCharacter 1
        If (bInLiteral And sCharacter = sLiteralTerminator) Begin
           Move False To bInLiteral
        End
        If (bFirstChar) Begin
           Move False To bFirstChar
           If (sCharacter = '"' Or sCharacter = "'") Begin
              Move sCharacter To sLiteralTerminator
              Move True To bInLiteral
           End
        End
        If (Not (bInLiteral)) Begin
           Move (sCharacter = sListSeparator) To bEndOfValue
        End
        If (Not (bEndOfValue) And sCharacter <> sLiteralTerminator) Begin
           Move (sData + sCharacter) To sData
        End
    Until (bEndOfValue)

    Function_Return sData
End_Function // ReadData

Your code can be changed from:

Get_Attribute DF_DECIMAL_SEPARATOR To sDecimalSep
Set_Attribute DF_DECIMAL_SEPARATOR To (Ascii ("."))
Repeat
    Read Channel 1 SomeFile.Code
    Read Channel 1 SomeFile.Descr
    Read Channel 1 SomeFile.Amount
    Read Channel 1 SomeFile.Descr2
Until (bEofData)
Set_Attribute DF_DECIMAL_SEPARATOR To sDecimalSep

to:

Get_Attribute DF_DECIMAL_SEPARATOR To sDecimalSep
Set_Attribute DF_DECIMAL_SEPARATOR To (Ascii ("."))
Repeat
    Get ReadData 1 To SomeFile.Code
    Get ReadData 1 To SomeFile.Descr
    Get ReadData 1 To SomeFile.Amount
    Get ReadData 1 To SomeFile.Descr2
Until (bEofData)
Set_Attribute DF_DECIMAL_SEPARATOR To sDecimalSep


Contributed By:
Vincent Oorsprong
Company: Data Access Worldwide
email: vincent.oorsprong@dataaccess.eu
Web Site: http://www.dataaccess.eu

Links Related to this Article
DAW Knowledge Base article 1388: HOWTO: Getting the list separator for your Windows locale
DAW Knowledge Base article 1631: INFO: The history of True and False according to DataFlex

Email this Article
Email this Article to a Colleague
Send Feedback on this Article to Data Access Worldwide
Copyright ©2020 Data Access Corporation. All rights reserved.

The information provided in the Data Access Technical Knowledge Base is provided "as is" without warranty of any kind. Data Access Corporation disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. In no event shall Data Access Corporation or its suppliers be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages, even if Data Access Corporation or its suppliers have been advised of the possibility of such damages. Some states do not allow the exclusion or limitation of liability for consequential or incidental damages so the foregoing limitation may not apply.