Read / Write a file CSV 'UTF-16 LE'

Post Reply
User avatar
max
Posts: 130
Joined: Fri Jun 30, 2006 2:14 pm
Location: Ancona - Italy

Read / Write a file CSV 'UTF-16 LE'

Post by max »

I should read from and/or create a new file CSV with 'UTF-16 LE' Encoding (UTF 'Little Endian'). A machine of my customer seems read only this format of CSV and not a CSV with Ansi standard encode created with 'memowrit()' or 'copy to' or similar functions/commands.
Apparently opening with text editor this two variations has the same content, but it's not like that.
It had never happened to me before.
Someone can help me? Thank you.
User avatar
Enrico Maria Giordano
Posts: 8784
Joined: Thu Oct 06, 2005 8:17 pm
Location: Roma - Italia
Has thanked: 1 time
Been thanked: 9 times
Contact:

Re: Read / Write a file CSV 'UTF-16 LE'

Post by Enrico Maria Giordano »

To see the differences, you have to open those two files with an hex editor.
User avatar
max
Posts: 130
Joined: Fri Jun 30, 2006 2:14 pm
Location: Ancona - Italy

Re: Read / Write a file CSV 'UTF-16 LE'

Post by max »

Ok. Differences seen viewing both files in Hexadecimal editor PSPAD.
Now, how can i read and write correctly in Hexadecimal from my FWH app converting characters to (and from) ANSI standard <-> Hexadecimal?
To manipulate string i use abitually memowrit() or copy to or memoread() functions and similar, but all of these commands/functions works fine only with ANSI standard characters. Perhaps i have to use other functions i never use before and i don't know, i suppose.
Jack
Posts: 292
Joined: Wed Jul 11, 2007 11:06 am

Re: Read / Write a file CSV 'UTF-16 LE'

Post by Jack »

User avatar
cnavarro
Posts: 6660
Joined: Wed Feb 15, 2012 8:25 pm
Location: España
Has thanked: 9 times
Been thanked: 12 times

Re: Read / Write a file CSV 'UTF-16 LE'

Post by cnavarro »

max wrote: Thu Apr 17, 2025 12:40 pm Ok. Differences seen viewing both files in Hexadecimal editor PSPAD.
Now, how can i read and write correctly in Hexadecimal from my FWH app converting characters to (and from) ANSI standard <-> Hexadecimal?
To manipulate string i use abitually memowrit() or copy to or memoread() functions and similar, but all of these commands/functions works fine only with ANSI standard characters. Perhaps i have to use other functions i never use before and i don't know, i suppose.
Please try this sample ( pure harbour ) and apply these functions to your code

Code: Select all | Expand

#include "hbclass.ch"
#include "mysql.ch"

Function Main()
   LOCAL oServer, oQuery, oRow
   LOCAL cCsvFile := "output.csv"
   LOCAL cQuery := "SELECT * FROM clientes"
   Local cTable := "fwh"
   LOCAL hFile, cLine, aFields, nI
   Local nFields
   LOCAL cBOM := Chr(0xFF) + Chr(0xFE) // BOM para UTF-16 LE

   oServer := TMySQLServer():New("localhost", "root", "", 3306 )
   
   IF oServer:NetErr()
      ? "Error de conexión: ", oServer:Error()
      RETURN
   ENDIF

   oServer:SelectDB( cTable )

   oQuery := oServer:Query( cQuery )
   
   IF oQuery:NetErr()
      ? "Error en la consulta: ", oQuery:Error()
      oServer:End()
      RETURN
   ENDIF

   hFile := FCreate(cCsvFile)
   
   IF hFile == -1
      ? "Error al crear el archivo CSV"
      oQuery:End()
      oServer:End()
      RETURN
   ENDIF

   // Escribir BOM para UTF-16 LE
   FWrite(hFile, cBOM)                 // LOOK

   nFields := oQuery:FCount()
   cLine := ""
   FOR nI := 1 TO nFields
      cLine += '"' + oQuery:FieldName( nI ) + '"'
      IF nI < nFields
         cLine += ","
      ENDIF
   NEXT
   cLine += hb_eol()
   FWrite(hFile, StrToUTF16LE( cLine ))                 // LOOK

   DO WHILE !oQuery:Eof()
      oRow := oQuery:GetRow()
      cLine := ""
      
      FOR nI := 1 TO nFields
         cLine += '"' + hb_ValToStr(oRow:FieldGet(nI)) + '"'
         IF nI < nFields
            cLine += ","
         ENDIF
      NEXT
      
      cLine += hb_eol()
      FWrite(hFile, StrToUTF16LE( cLine ) )    // LOOK
      oQuery:Skip()
   ENDDO

   FClose(hFile)
   oQuery:End()
   oServer:End()
   
   ? "Archivo CSV generado exitosamente: ", cCsvFile

Return nil

// IMPORTANT
// Function convert strint to UTF-16 LE
STATIC FUNCTION StrToUTF16LE(cStr)
   LOCAL cResult := ""
   LOCAL nI, cChar

   FOR nI := 1 TO Len(cStr)
      cChar := SubStr(cStr, nI, 1)
      cResult += Chr(Asc(cChar)) + Chr(0) // Little Endian: byte bajo primero
   NEXT

RETURN cResult

Cristobal Navarro
Hay dos tipos de personas: las que te hacen perder el tiempo y las que te hacen perder la noción del tiempo
El secreto de la felicidad no está en hacer lo que te gusta, sino en que te guste lo que haces
Post Reply