Oui, j'ai résolu mon problème avec le
principe KISS. J'ai donc une valeur chaîne de clé de registre qui contient "cmd /c chcp 1252 & cmd /c dir "%1" /A /S /C > _Listing.txt".
La valeur "CMD.EXE /u /c DIR "%1" /A /S /C >"_Listing.txt"" fonctionnait mais le fichier UNICODE généré ne s'affichait pas correctement dans Chrome.
Par contre, j'ai finalisé mon programme PureBasic dont voici le listing complet :
Code : Tout sélectionner
EnableExplicit
Enumeration File
#SourceFile
EndEnumeration
Procedure ConvertFile(sFileName.s)
Protected.i iStrIndex, iFileLength, iBytes, *MemoryID
Protected.a aCharVal, aCP850
Static.s sCP1252to850LUT = "ÇüéâäàåçêëèïîìÄÅÉæÆôöòûùÿÖÜø£Ø׃áíóúñѪº¿®¬½¼¡«»¦¦¦¦¦ÁÂÀ©¦¦++¢¥++--+-+ãÃ++--¦-+¤ðÐÊËÈiÍÎÏ++¦_¦Ì¯ÓßÔÒõÕµþÞÚÛÙýݯ´-±=¾¶§÷¸°¨·¹³²¦ "
; Static Dim aCP1252to850LUT.a(128)
If OpenFile(#SourceFile, sFileName, #PB_Ascii)
iFileLength = Lof(#SourceFile)
If iFileLength
If ReadCharacter(#SourceFile, #PB_Ascii) = $A0 ; Make sure the file hasn't been already converted
MessageRequester("Information", "File '" + sFileName + "' already converted")
Else
FileSeek(#SourceFile, 0)
Debug "File Length: " + Str(iFileLength)
*MemoryID = AllocateMemory(iFileLength)
If *MemoryID
iBytes = ReadData(#SourceFile, *MemoryID, iFileLength) ; Read the Data in the File and store then in the Memory block
Debug "Nombre d'octets lus: " + Str(iFileLength)
iFileLength = iFileLength ; Both should be identical but it's safer to work with actually read data size
ShowMemoryViewer(*MemoryID, iFileLength)
; ShowMemoryViewer(@sCP1252to850LUT, 256) ; LUT is 16bit UNICODE; 128 char => 256 bytes
; If Not(aCP1252to850LUT(0)) ; Initialize aCP1252to850LUT array only once
; For iStrIndex = 0 To 127
; aCP1252to850LUT(iStrIndex) = Asc(Mid(sCP1252to850LUT, iStrIndex, 1))
; Next
; EndIf
PokeA(*MemoryID, $A0) ; invisible tag (in replacement of SPC = $20) for the new file
For iStrIndex = 1 To iFileLength - 1
aCharVal = PeekA(*MemoryID + iStrIndex)
; Debug "aCharVal = '" + Chr(aCharVal) + "' = Chr(" + aCharVal + ")"
If aCharVal > 127
aCP850 = Asc(Mid(sCP1252to850LUT, aCharVal - 127, 1))
; aCP850 = Asc(sCP1252to850LUT(aCharVal - 128))
; aCP850 = aCP1252to850LUT(aCharVal - 128)
; Debug "New Val = '" + aCP850 + "'"
PokeA(*MemoryID + iStrIndex, aCP850)
; ShowMemoryViewer(*MemoryID, iFileLength)
EndIf
Next
ShowMemoryViewer(*MemoryID, iFileLength)
FileSeek(#SourceFile, 0)
iBytes = WriteData(#SourceFile, *MemoryID, iFileLength)
FreeMemory(*MemoryID)
Else
MessageRequester("Warning", "Memory Allocation Error !", #PB_MessageRequester_Warning)
EndIf
CloseFile(#SourceFile)
; MessageRequester("Information", "File '" + sFileName + "' converted")
EndIf
Else
MessageRequester("Warning", "File '" + sFileName + "' is Empty !", #PB_MessageRequester_Warning)
EndIf
Else
MessageRequester("Warning", "Can't open '" + sFileName + "' !", #PB_MessageRequester_Warning)
EndIf
EndProcedure
Procedure.i BackwardFind(sString.s, sSearchFor.s, iStart)
Protected.i iStrIndex, iSearchLength = Len(sSearchFor)
If iStart >= iSearchLength
iStrIndex = iStart - iSearchLength + 1 ; + 1 because Mid() is 1 based
Else
iStrIndex = 0
EndIf
While iStrIndex And Mid(sString, iStrIndex, iSearchLength) <> sSearchFor
iStrIndex = iStrIndex - 1
Wend ; Exit with 0 if none
ProcedureReturn iStrIndex
EndProcedure
;****************************************************** Main ********************************************************************;
Define.i iProgramParametersNum, iCharIndex, iIsFile, iRunProgramValue
Define.s sDirectory, sWorkingDirectory, sCliCommand, sTrash, sFileName
iProgramParametersNum = CountProgramParameters()
If iProgramParametersNum
iIsFile = ReadFile(#SourceFile, ProgramParameter(0), #PB_File_NoBuffering)
If iIsFile
CloseFile(#SourceFile)
ConvertFile(ProgramParameter(0))
Else
sDirectory = ProgramParameter(0)
If iProgramParametersNum >= 2
sFileName = ProgramParameter(1)
Else
sFileName = "_Listing.txt"
EndIf
; Move to parent directory (to mimic original behavior)
iCharIndex = BackwardFind(sDirectory, "\", Len(sDirectory) - 1) ; - 1 to get rid of the last char (in case it's a '\')
If iCharIndex
sWorkingDirectory = Left(sDirectory, iCharIndex)
Else
sWorkingDirectory = "C:\Windows\System32\"
EndIf
sCliCommand = "/C DIR " + Chr(34) + sDirectory + Chr(34) + " /A /S /C >" + Chr(34) + sFileName + Chr(34) + " 2>&1"
iRunProgramValue = RunProgram("CMD.EXE", sCliCommand, sWorkingDirectory, #PB_Program_Wait | #PB_Program_Hide)
ConvertFile(sWorkingDirectory + sFileName)
EndIf
EndIf
End
Il permet donc aussi de convertir un fichier avec" iIsFile = ReadFile(#SourceFile, ProgramParameter(0), #PB_File_NoBuffering)". Je ne suis pas certain du rôle de "#PB_File_NoBuffering", mon but était de ne pas perdre de temps à transférer le fichier en mémoire...
Il subsiste des tentatives infructueuses d'utilisation d'un tableau d'ASCII.a pour une accès plus direct par "aCP480 = aCP1252to480LUT(aCharVal - 128)" plutôt que par "aCP480 = Asc(Mid(sCP1252to480LUT, aCharVal - 127, 1))". Cela a-t-il un intérêt ? Comment auriez-vous fait ?
Le mot clé Static n'aurait d’intérêt que si la fonction était appelée plusieurs fois. Comme ce n'est pas le cas ici, il n'est là que pour le principe...
Dernier point, j'ai un peu de mal à savoir si je convertis de CP1252 vers CP850 ou le contraire... Ma LUT est CP850(128-255) mais, si j'utilise la console, je demande "chcp 1252"...