Italian community of Lazarus and Free Pascal

Programmazione => Generale => Topic aperto da: Riccardo Ferrari - Febbraio 07, 2024, 10:01:25 pm

Titolo: TrueName
Inserito da: Riccardo Ferrari - Febbraio 07, 2024, 10:01:25 pm
Ho la seguente esigenza, che temo non sia molto comune perché ho cercato in rete una soluzione ma non ho trovato nulla, non solo la soluzione (succede di non trovarla) ma nemmeno qualcun altro che abbia posto la solita questione.
Dunque: Windows non è case-sensitive. Per fortuna, quando uso linux impazzisco dietro alle maiuscole, però ciò ha un portato estetico che mi disturba (lo so non è un gran problema).
Se un file si chiama Abcdefhi.Jkl e invece digito abcDEFHI.jkL al programma va bene comunque, lo riconosce e va avanti con la elaborazione.
L’estetica risiede nel fatto che rimane scritto "male" per tutto il programma. Quando il programma deve restituire il nome del file lo fa come è stato impostato non come realmente è.
Per cui ho scritto una funzione, che ho chiamato TrueName, che converte il nome impostato nel nome reale, mantenendo la sequenza di maiuscole/minuscole. Purtroppo ExpandFileName non lo fa, come avevo sperato, se hai scritto "male", non raddrizza la cosa.
TrueName funziona così: invece di verificare l’esistenza del file con FileExists, come faccio in genere, cerco con FindFirst il nome impostato, poi leggo la variabile <punto>Name del record TSearchRec che corrisponde al nome reale con le maiuscole/minuscole giuste, ovviamente FindFirst<>0 corrisponde a False di FileExists.
Tutto risolto? Manco per niente.
In primo luogo magari esiste un algoritmo più efficiente del mio, se ci fosse ne sarei felice. In secondo luogo il trucchetto del FindFirst vale solo per il nome, tutto il resto del percorso, cioè i nomi delle varie directory sovraordinate continuano a mantenere il case impostato da tastiera, anche se diverso dall’originale per quanto al case.
Dovrei quindi applicare il trucchetto del FindFirst ad ogni directory contenuta nel path. Una alla volta. Quindi se il mio algoritmo non fosse efficiente, l’inefficienza verrebbe moltiplicata per la profondità del path.
Magari, mi sono chiesto, esiste una funzione già fatta che restituisce il vero nome completo di path.
Ne sapete qualcosa? Grazie per l’attenzione.
Scusate la lunghezza ma non mi pare un problema molto sentito, quindi ho dovuto spiegarlo bene per evitate fraintendimenti.





Titolo: Re:TrueName
Inserito da: quack - Febbraio 07, 2024, 10:33:53 pm
Mai provata ma sembra essere quello che cerchi:

https://www.freepascal.org/docs-html/rtl/sysutils/expandfilenamecase.html (https://www.freepascal.org/docs-html/rtl/sysutils/expandfilenamecase.html)

Per gestire le collisioni la funzione assegna un valore a MatchFound da cui puoi capire se non ha trovato nessun file, uno o più.

PS: sarà anche scomodo digitare in maniera corretta il nome, ma così rischi di processare il file sbagliato  ;D .

Ciao
qk
Titolo: Re:TrueName
Inserito da: DragoRosso - Febbraio 07, 2024, 10:47:43 pm
La problematica generale, che è praticamente irrisolvibile, è che nomi di file e path dissimili per il case sono differenti. Quindi non esiste soluzione a:

Citazione
/FPS/Pollo/Pluto.txt
/fps/Pollo/Pluto.txt
/Fps/pollo/Pluto.txt

Su Windows sono identiche e identificano le stesso file, mentre su Linux (ad esempio) sono diverse (anche il file "Pluto.txt" ovviamente) e non c'è modo di distinguerle a partire da un "nome" case insensitive.

Infatti le funzioni che "sbrogliano" tale situazione riportano che viene prospettato il primo matching trovato, matching che non è possibile prevedere.

E' per quello che nessuno si è mai posto "il problema" più di tanto.

Diciamo che una soluzione più o meno "scritta" è quella di usare nomi di file minuscoli nei SO case sensitive.

Ciao

EDIT: ... e ovviamente anche le path minuscole
Titolo: Re:TrueName
Inserito da: nomorelogic - Febbraio 08, 2024, 10:44:08 am
ciao Riccardo

ti direi di abbandonare FindFirst/FindNext per la funzione/procedura FindAllFiles che trovi nella unit FileUtil.

La trovi documentata in: https://wiki.freepascal.org/FindAllFiles (https://wiki.freepascal.org/FindAllFiles)

La differenza sta nel fatto che hai a disposizione una TStringList con tutti i file trovati che corrispondono alla ricerca effettuata.

Non ho fatto la prova che hai descritto nel post iniziale ma credo che potrebbe funzionare in quanto, a prescindere dal "case" di ricerca, nella lista di stringhe dovresti già avere i nomi corretti (percorso cartelle incluso).

Credo che con un po' di fortuna potrebbe risolvere il tuo problema.
Facci sapere.

nomorelogic
Titolo: Re:TrueName
Inserito da: Riccardo Ferrari - Febbraio 08, 2024, 06:24:03 pm
Mai provata ma sembra essere quello che cerchi:
https://www.freepascal.org/docs-html/rtl/sysutils/expandfilenamecase.html (https://www.freepascal.org/docs-html/rtl/sysutils/expandfilenamecase.html)
Grazie.
Funziona, ma solo per il nome del file, non per l’intero path.
Per l’intero Path occorre andare all’indietro e cercare tutti i nomi.
Ho scritto una funzione che lo fa, più semplice di così non mi è venuta.
Codice: [Seleziona]
{--------------------------------------------------------------------------}
Uses sysutils;
{--------------------------------------------------------------------------}
Const
  PATH_SEP=#92;
{--------------------------------------------------------------------------}
Var
  FName,TName:String;
{--------------------------------------------------------------------------}
Function TrueName(F:AnsiString):AnsiString;
  var
    u,v:Unicodestring;
    a,z:AnsiString;
    m:TFilenameCaseMatch;
  {----------------------------------------}
  Function DueSlash(Sh:AnsiString):Boolean;
      begin
      // delete(Sh,1,pos(PATH_SEP,Sh)); e' sempre 3
      delete(Sh,1,3);
      if pos(PATH_SEP,Sh)>0 then DueSlash:=True else DueSlash:=False;
      end; // Function DueSlash
  {----------------------------------------}
  Function  StripEnd(Se:AnsiString):AnsiString;
      begin
      if AnsiLastChar(Se)=PATH_SEP then delete(Se,length(Se),1);
      StripEnd:=Se;
      end; // Function StripEnd
  {----------------------------------------}
  begin
      z:='';
      u:=f;
      v:=ExpandFileNameCase(u,m);
      a:=v;
      while DueSlash(a) do
        begin
          if z='' then z:=ExtractFileName(a) else z:=ExtractFileName(a)+PATH_SEP+z;
          a:=StripEnd(ExtractFilePath(a));
          u:=a;
          v:=ExpandFileNameCase(u,m);
          a:=v;
        end;
        z:=copy(a,1,3)+ExtractFileName(a)+PATH_SEP+z;
        TrueName:=z;
  end;
{--------------------------------------------------------------------------}
Begin
  FName:=paramstr(1);
  TName:=TrueName(FName);
  WriteLn;
  WriteLn('Input   : ',FName);
  WriteLn('Truename: ',TName);
End.
{--------------------------------------------------------------------------}
Inoltre la compilazione mi dà 4 warning:

(31,10) Warning: Implicit string type conversion from "AnsiString" to "UnicodeString"
(33,10) Warning: Implicit string type conversion with potential data loss from "UnicodeString" to "AnsiString"
(38,14) Warning: Implicit string type conversion from "AnsiString" to "UnicodeString"
(40,14) Warning: Implicit string type conversion with potential data loss from "UnicodeString" to "AnsiString"

Lavoro sempre con le AnsiString, e prima con le String. Mai usate le UnicodeString.
Mi sono documentato (un po’) e per ora non voglio complicare ulteriormente il codice inserendo delle conversioni corrette, dovrei studiare a fondo come si facciano queste conversioni, e dovrei anche implementarle, ammesso che ci riesca.
Comunque credo di aver capito che da Ansi a Unicode non ci dovrebbero essere problemi (allora perché esce il warning?) mentre da Unicode ad Ansi si potrebbero perdere i caratteri "strani". Trattandosi di nomi di file i caratteri strani non ci dovrebbero essere, a meno di non lavorare con nomi di file Russi, o peggio, Cinesi. Non credo che mi succederà mai. Hint: vengo dall’ 8+3.
Titolo: Re:TrueName
Inserito da: Riccardo Ferrari - Febbraio 08, 2024, 06:37:25 pm
ti direi di abbandonare FindFirst/FindNext per la funzione/procedura FindAllFiles che trovi nella unit FileUtil.

La trovi documentata in: https://wiki.freepascal.org/FindAllFiles (https://wiki.freepascal.org/FindAllFiles)
Grazie del suggerimento, studierò.

Credo che con un po' di fortuna potrebbe risolvere il tuo problema.
Facci sapere.
Ho postato il codice della funzione TrueName() che ho scritto utilzzando la funzione ExpandFileNameCase dell'unit sysutils, suggerita da quack.
Se hai tempo fammi sapere cosa ne pensi, grazie.
Titolo: Re:TrueName
Inserito da: quack - Febbraio 08, 2024, 09:10:44 pm
La funzione ExpandFileName non cerca il file ma si occupa solamente di trasfomare il percorso da relativo in assoluto.
Se nel nome del file non è incluso il percorso completo aggiunge quello della directory corrente.

Infine se il nome restituito esiste assegna a FileMatch il valore mkExactMatch, mkSingleMatch o mkAmbiguous, in base alla situazione, se non esiste assegna il valore mkNone. 

Per esempio:

la directory corrente è "/pippo" e contiene solo il file "pluto.pas"

ExpandFileNameCase('PLUTO.pas', match) restituirà "/pippo/pluto.pas" e mkSingleMatch
ExpandFileNameCase('pluto.pas', match) restituirà "/pippo/pluto.pas" e mkExactMatch
ExpandFileNameCase('Mucca.pas', match) restituirà "/pippo/Mucca.pas" e mkNone.

In definitiva con ExpandFileName risali a quello che dovrebbe essere il percorso assoluto ipotetico del nome file in input, indipendentemente che il file esista o meno nel sistema.

Spero che questo ti aiuti a capire quale è la strada migliore da seguire nel tuo caso.
PS: prova ad usare il tipo string invece di ansistring.

Ciao
Titolo: Re:TrueName
Inserito da: DragoRosso - Febbraio 08, 2024, 10:37:04 pm
Comunque credo di aver capito che da Ansi a Unicode non ci dovrebbero essere problemi (allora perché esce il warning?) mentre da Unicode ad Ansi si potrebbero perdere i caratteri "strani". Trattandosi di nomi di file i caratteri strani non ci dovrebbero essere, a meno di non lavorare con nomi di file Russi, o peggio, Cinesi. Non credo che mi succederà mai. Hint: vengo dall’ 8+3.

Unicode (ce ne sono vari) e AnsiString non hanno nulla a che fare l'uno con l'altro. In comune hanno solo che entrambi sono "contenitori", la codifica dei caratteri è totalmente differente.
AnsiString si basa su un elenco di codepage di 256 caratteri, ogni codepage rappresenta un set a se stante: la "a" di un codepage potrebbe essere differente dalla "a" di un altro codepage.

AnsiString è costruita su un array di caratteri in cui ogni carattere occupa un byte. Ogni carattere Unicode invece occupa una lunghezza variabile da 1 a 5 byte a seconda degli standard (UTF-8, UTF-16LE, UTF-16BE, UTF-32, etc ...)
 
Unicode, in particolare UTF-8 che è una codifica a lunghezza variabile ha i primi 128 caratteri uguali alla codifica ANSI (conosciuta anche come "ASCII Base" + "ASCII Esteso" o informalmente "Windows 1252"). C'è una forte contrapposizione con la norma ISO-8859-1 che anch'essa rivendica la paternità di ANSI in cui alcuni caratteri "ASCII Esteso" cioè i caratteri dal 128 al 255 sono però diversi dal "Windows 1252".

UTF-8 come si diceva ha i primi 128 caratteri uguali all' "ASCII base" chiamato nei tempi moderni universalmente "Basic Latin", e i successivi 128 caratteri uguali all' "ASCII esteso" (aka "Latin-1 Supplement").

ATTENZIONE che i nomi "Basic Latin" e "Latin-1 Supplement" sono normati e li troverete spesso tra le definizioni delle codifiche nei DATABASE.

La ISO/IEC 10646:2020 è la normativa (ultima edizione del 2020) che definisce a livello universale la codifica dei caratteri (UCS) e in particolare le sette possibili codifiche dei caratteri: UTF-8, UTF-16, UTF-16BE, UTF-16LE, UTF-32, UTF-32BE e UTF-32LE.

Con AnsiString, inteso come contenitore dei caratteri ANSI, è impossibile definire tutti i caratteri usati in una qualsiasi lingua e ciò complica la programmazione: si utilizza il CODEPAGE per definire quali caratteri il set ANSI rappresenta. Un elenco aggiornato di codepage è presente qui: https://learn.microsoft.com/it-it/windows/win32/intl/code-page-identifiers?redirectedfrom=MSDN (https://learn.microsoft.com/it-it/windows/win32/intl/code-page-identifiers?redirectedfrom=MSDN)

Ovviamente in una stringa AnsiString non possono essere rappresentate più "lingue" contemporaneamente ... a meno di non ricorrere a trucchi assolutamente da NON METTERE IN ATTO.

Per risolvere questo problema (pensate un doc scritto in Italia e letto in Olanda o Germania ... a parte la traduzione  ;) ) è stato inventato l'UNICODE.

Diciamo che essenzialmente vengono usati due tipi di UNICODE: UTF-8 e UTF-16LE.

UTF-8 ha caratteri che sono lunghi fino a 5 byte e può rappresentare un qualsiasi carattere in maniera universale. Posso quindi "misciare" caratteri arabi, cinesi, latini, etc. senza creare alcuna confusione. Per tale motivo tale codifica è usata praticamente universalmente nel WEB: tutte le pagine WEB e quasi tutti i formati dati (JSON, XML, etc ..) usano la codifica UTF-8.

Unicode codifica 16 "piani" ognuno dei quali contiene 65536 caratteri. Il primo "piano" chiamato BMP contiene la stragrande maggioranza di tutti i caratteri oggi noti (tra cui i cinesi, giapponesi e coreani). UTF-16 può codificare un piano completo, e normalmente viene usato con il il primo (BMP).

Per chi volesse dare una occhiata in maniera testuale descrittiva all'elenco dei caratteri oggi definiti (ultimo aggiornamento 2022) può vederlo qui: https://www.unicode.org/Public/15.0.0/ucd/UnicodeData.txt (https://www.unicode.org/Public/15.0.0/ucd/UnicodeData.txt)

Perchè la conversione AnsiString genera quell'avviso ? Perchè essendo il carattere legato ad un codepage non definito (qualunque sia non è "scritto" nella stringa) la conversione in Unicode potrebbe non avere senso.

Per convertire le AnsiString in Unicode occorrerebbe usare le funzioni specifiche che consentono di eseguire correttamente l'operazione. Ovviamente è peggio l'incontrario (UNICODE string -> AnsiString).

Dal 2001 in poi Windows ha introdotto l'uso di unicode (o meglio un subset simile al BMP di UTF-16LE) a livello di kernel e API. Dal 2005 anche Linux ha implementato nel kernel l'uso di unicode preferendo però UTF-8.

Gli ambienti di programmazione ci hanno messo un pò e con il tempo sono diventati UNICODE compatibili, anzi essenzialmente UNICODE: Delphi dal 2009, mentre FPC non è pienamente compatibile (FPC non ha il core compatibile con unicode).

Ma di fatto per il programmatore che cosa cambia (a parte non scrivere più "è" in Italiano e magari leggere "§" in tedesco ... è un esempio non sò se fosse così): cambia che l'uso di UNICODE ha portato inevitabilmente il fatto che un carattere non è più lungo 1 byte ma bensì diventa di 2 byte. Uno stravolgimento per il programmatore, molto spesso abituato a lavorare senza considerare la lunghezza effettiva dei dati (il famigerato sizeof() ).

Qui mi fermo perchè già sono state scritte pagine e pagine anche in questo forum sull'argomento ...

Ciao

P.S.: dimenticavo la cosa più importante, anche se si legge tra le righe sopra, ossia che in Lazarus / FPC la definizione di "String" equivale alla "AnsiString" come definizione di lunghezza del carattere ed è di 1 byte, a differenza dei linguaggi di programmazione "unicode" come Delphi in cui la "String" definisce un carattere di due byte e la "AnsiString" invece è di 1 byte.
Titolo: Re:TrueName
Inserito da: bonmario - Febbraio 09, 2024, 10:00:06 am
Scusa, ma ho letto solo oggi ...
Avevo avuto lo stesso problema su Windows, e ne avevamo discusso qui:
https://www.lazaruspascal.it/index.php?topic=2534.msg16335#msg16335

Alla fine avevo usato "expandfilenamecase", partendo dal nome del file, ed andando a ritroso per i domi delle varie cartelle del percorso.

Ciao, Mario
Titolo: Re:TrueName
Inserito da: nomorelogic - Febbraio 09, 2024, 10:13:41 am
[...]
Ho postato il codice della funzione TrueName() che ho scritto utilzzando la funzione ExpandFileNameCase dell'unit sysutils, suggerita da quack.
Se hai tempo fammi sapere cosa ne pensi, grazie.

ok, appena ho modo gli do un'occhiata

riporto anche il link sul forum internazionale con lo stesso argomento
https://forum.lazarus.freepascal.org/index.php/topic,66144.0.html (https://forum.lazarus.freepascal.org/index.php/topic,66144.0.html)


@Riccardo Ferrari
chiedere aiuto anche nel forum internazionale è un'ottima idea  :)
quando capita sarebbe bene mettere il link così si possono sfruttare anche le altre  risposte ;)

Titolo: Re:TrueName
Inserito da: nomorelogic - Febbraio 09, 2024, 06:00:17 pm
[...]
Ho postato il codice della funzione TrueName() che ho scritto utilzzando la funzione ExpandFileNameCase dell'unit sysutils, suggerita da quack.
Se hai tempo fammi sapere cosa ne pensi, grazie.

ok, appena ho modo gli do un'occhiata

ho provato il tuo codice e devo dire che sembra una buona soluzione

un paio di appunti:
Titolo: Re:TrueName
Inserito da: Riccardo Ferrari - Febbraio 10, 2024, 02:30:07 pm
Per esempio:

la directory corrente è "/pippo" e contiene solo il file "pluto.pas"

ExpandFileNameCase('PLUTO.pas', match) restituirà "/pippo/pluto.pas" e mkSingleMatch
ExpandFileNameCase('pluto.pas', match) restituirà "/pippo/pluto.pas" e mkExactMatch
ExpandFileNameCase('Mucca.pas', match) restituirà "/pippo/Mucca.pas" e mkNone.
Così dice la documentazione, ma non è questo ciò che accade, almeno nel mio sistema (Win 10 e Fpc 3.2.2, ho provato sia compilato a 32 bit che a 64).
Anche se il case è diverso, TFilenameCaseMatch restituisce sempre mkExactMatch oppure mkNone se il file non c’è; mkSingleMatch e mkAmbiguous non escono mai.
mkExactMatch esce anche se metti una wildcard, e viene restituito anche il nome esatto (il primo che trova con quella wildcard).

PS: prova ad usare il tipo string invece di ansistring.
Avevo già provato, con poca convinzione, ed infatti non cambia nulla.
Per quel poco che ho capito la String e l’AnsiString differiscono solo per la lunghezza massima, per il resto si comportano allo stesso modo.

Titolo: Re:TrueName
Inserito da: quack - Febbraio 10, 2024, 02:54:39 pm
[
Così dice la documentazione, ma non è questo ciò che accade, almeno nel mio sistema (Win 10 e Fpc 3.2.2, ho provato sia compilato a 32 bit che a 64).
Anche se il case è diverso, TFilenameCaseMatch restituisce sempre mkExactMatch oppure mkNone se il file non c’è; mkSingleMatch e mkAmbiguous non escono mai.

I risultato che hai riscontrato è corretto. Su window non ci possono essere due file i cui nomi differiscono solo per qualche lettere in maiuscolo o minuscolo.
Appena ho un attimo faccio quanche prova e ti risondo anche sul resto.
Ciao
Titolo: Re:TrueName
Inserito da: Riccardo Ferrari - Febbraio 10, 2024, 03:09:49 pm
Perchè la conversione AnsiString genera quell'avviso ? Perchè essendo il carattere legato ad un codepage non definito (qualunque sia non è "scritto" nella stringa) la conversione in Unicode potrebbe non avere senso.

Per convertire le AnsiString in Unicode occorrerebbe usare le funzioni specifiche che consentono di eseguire correttamente l'operazione. Ovviamente è peggio l'incontrario (UNICODE string -> AnsiString).
Ti ringrazio per la lunga spiegazione. Ho capito qualcosa in più, anche se non posso dire di padroneggiare l’argomento, tutt’altro.
Se ho capito bene, Ansistring e Unicodestring sono uguali solo per ASCII < 127
Infatti il warning che ho ricevuto funziona, nel senso che era un effettivo invito all’attenzione.
Ho nominato un file con una lettera accentata e la funzione TrueName che ho scritto l’ha sbagliata, solo un carattere sbagliato. Tutto il resto giusto.
Sbagliano anche i professionisti, se passo un testo (copia/incolla) da Notepad a Scite, alcune volte mi sbaglia gli accenti, non ho capito ancora bene come e perché. Se ho entrambi i programmi aperti il copia incolla viene bene. Se passo dal disco, cioè se salvo il file di Notepad e lo apro in Scite i caratteri non a 7 bit sono mal interpretati. Magari ho sbagliato qualche settaggio iniziale.
Studierò anche come fare una conversione seria tra Ansistring e Unicodestring. Anche il contrario, ma, se ho ben capito, non è detto che si possa fare: Da Ansi ad Uni si aggiunge, quindi si fa sapendo cosa si deve aggiungere. Da Uni ad Ansi si toglie e non credo che sia sempre possibile.
Detto questo devo ricordare che sono partito dai nomi dei file ed i loro percorsi. Che necessità c’è di superare l’ASCII 127? Basterebbe scrivere i nomi di file a 7-bit, così vanno bene in tutto mondo.
Ultimamente mi hanno inviato via email il file Carta_identità.Pdf Ma che bisogno c’è??? Se scrivessi Carta_Identita.Pdf non si capisce? Forse 8.3 era troppo limitante ma qui si esagera. Che poi era 8 e basta visto che il 3 spesso era  "prenotato"

Titolo: Re:TrueName
Inserito da: DragoRosso - Febbraio 10, 2024, 03:18:38 pm
@Riccardo Ferrari

Ho provato sotto Linux e la funzione "ExpandFileNameCase" funziona correttamente, fatto salvo che bisogna vedere come ho detto quali sono i tuoi scopi ...

Vedi Allegato
Titolo: Re:TrueName
Inserito da: Riccardo Ferrari - Febbraio 10, 2024, 03:29:07 pm
Alla fine avevo usato "expandfilenamecase", partendo dal nome del file, ed andando a ritroso per i domi delle varie cartelle del percorso.
Grazie per l’attenzione.
Sono arrivato parallelamente al tuo solito risultato che ho scoperto dopo.
Me lo hanno suggerito su un forum in inglese
https://forum.lazarus.freepascal.org/index.php/topic,66144.msg505648.html#msg505648
non direttamente a te, hanno postato un link e ti ho trovato
Il codice che ho scritto è molto simile al tuo. Ciò è male perché speravo di trovare una funzione diretta senza fare ricorsioni all’indietro. Se entrambi siamo arrivati lì significa (credo) che la funzione diretta non c’è.
Inquietante anche il fatto che abbiamo usato lo stesso esempio, tu hai usato 'c:\users\bonmar\downloads' nel mio esempio di prova (non pubblicato) cambia bonmar e avevo aggiunto anche un Pdf scaricato.

Titolo: Re:TrueName
Inserito da: DragoRosso - Febbraio 10, 2024, 03:35:43 pm
Ti ringrazio per la lunga spiegazione.....

La conversione non avviene correttamente neanche da ANSI a Unicode se non si usa la esatta "formula". Per convertirlo devi esattamente sapere quale è il codepage che stai usando.

Il problema è che il codepage non dipende da te, ma da chi ha scritto il testo e da come ti è arrivato.

E' per questo che si usano i caratteri UNICODE e non ANSI, così la maggior parte dei problemi viene eliminata. In particolare, se si usano UTF-8 non ci sono problemi di codifica (a parte la versione che si usa, magari la libreria di sistema che si stà usando non è aggiornatissima).

Se scrivi un carattere in Portoghese, quel carattere sarà letto correttamente ovunque. E' per questo che puoi vedere un sito cinese, senza capire niente, ma correttamente dal punto di vista formattazione e caratteri oppure uno russo o arabo: viene usato UTF-8.

Ma ciò avviene secondo certe regole:

1) Uso di UTF-8;
2) Il salvataggio nei file DEVE essere effettuato in formato UTF-8 con BOM.
3) Ovviamente il sistema di scrittura e di lettura deve supportare la lettura UNICODE.

Tutti gli altri sistemi, di qualsiasi natura / complessità / ingegnosità, possono solo che fallire.

L'unico sistema che mappa i caratteri ... TUTTI I CARATTERI AL MONDO, COMPRESI GRAFI VARI ... è l'UNICODE.

Quando apri Notepad e "salvi con nome" vedrai che ci sono delle opzioni (vedi allegato): ecco scegliendo quella strada puoi scambiare dati universalmente, altrimenti se salvi in ANSI non c'è speranza.

Per la programmazione è uguale, e non si "scampa" neanche se usi solo l'Italiano ... i caratteri accentati sono mappati in UNICODE in maniera diversa dall'ANSI, e ciò fà si che pacchetti di terze parti che usi in Lazarus / FPC non li elaborino correttamente e quindi visualizzi caratteri strani al loro posto.

In tanto ciò per farti riflettere. Se cerchi nel forum UNICODE troverai diversi articoli ed esempi.
Titolo: Re:TrueName
Inserito da: Riccardo Ferrari - Febbraio 10, 2024, 03:48:06 pm
credo sia scritto con windows in mente (mi riferisco a copy(a,1,3) ), forse dovresti mettere qualche direttiva per fare in modo che negli OS *nix non ci siano risultati anomali
Grazie. Immaginavo che ci sarebbero stati dei problemi su Linux.
Non solo il copy che segnali, ma anche quando cerco la prima backslash che do per scontato che sia a Pos=3.
Lo è solo su Windows. Su *nix la Pos=1, credo. Ma ho evitato di stare a cercare una Pos che so già qual è, uso Linux molto sporadicamente e non ho mai pensato di scrivere qualcosa per quello, per ora. Forse, come suggerisci, si risolve con le direttive: 3 per Win 1 per Linux.
Direi che per il TrueName abbiamo detto tutto, ma avrei in serbo un’altra questione molto più importante, se trovo il tempo la posto oggi stesso.
Il TrueName è solo un fatto estetico, almeno per me.

Titolo: Re:TrueName
Inserito da: DragoRosso - Febbraio 10, 2024, 04:07:50 pm
3 per Win 1 per Linux.

Non dare per scontato ciò che appare ovvio. Le PATH e i nomi dei file non sono solo espressi in "C:" e "/" ... ci sono i percorsi UNC (come i percorsi di rete), e tralasciamo i riferimenti a file su servizi vari leggibili con le normali API.

In alcune modalità, i file si accedono solo ed esclusivamente con definizioni vari (mai usato "\?\" oppure "\.\" ) e così vanno "memorizzati" ...
Titolo: Re:TrueName
Inserito da: Riccardo Ferrari - Febbraio 10, 2024, 05:06:24 pm
La conversione non avviene correttamente neanche da ANSI a Unicode se non si usa la esatta "formula". Per convertirlo devi esattamente sapere quale è il codepage che stai usando.
Temo che questa faccenda dell’Unicode sia scappata di mano, almeno a me. Non sono preparato per approfondire la questione, mi interesserebbe ma ho molte altre lacune che desiro colmare e l’Unicode è proprio l’ultima. Ne ho parlato perché sono usciti i warning di compilazione, altrimenti nemmeno me ne accorgevo.
Per cortesia confermami o meno solo se ho capito bene: a 7-bit (cioè sino ad ASCII 127) Ansi e Unicode sono identici. Se è così posso ignorare i warning. Per i nomi file vado, tassativamente, a 7-bit.
Se scrivi un carattere in Portoghese, quel carattere sarà letto correttamente ovunque. E' per questo che puoi vedere un sito cinese, senza capire niente, ma correttamente dal punto di vista formattazione e caratteri oppure uno russo o arabo: viene usato UTF-8.
Si’, vabbe’ (l’ho scritto apposta: "i" ed "e" accentate a 7 bit, ai più farà schifo (a me no) ma vuoi mettere la semplificazione) … Comunque: sì vabbe’, ma si potrebbe evitare di esagerare. Passi per il Cinese ma dici che se scrivi “Ci vediamo a Munchen” con la u normale senza la dieresi un Tedesco non capisce? Gira per tutta la Germania finché non trova un posto che si chiama uguale ma senza i due punti?
Quando apri Notepad e "salvi con nome" vedrai che ci sono delle opzioni (vedi allegato): ecco scegliendo quella strada puoi scambiare dati universalmente, altrimenti se salvi in ANSI non c'è speranza.
L’avevo intuito e mi pare di averci anche provato, ma Scite non legge l’Unicode (almeno la versione che uso) per cui ho lasciato perdere, quei due o tre caratteri sbagliati li correggo a mano e finisce lì.
Finisce lì la codifica dei caratteri, ho una questione che mi preme molto di più. Se ne hai voglia vedi se puoi rispondermi, grazie. Tra una mezz’ora posterò il testo
Titolo: Re:TrueName
Inserito da: Riccardo Ferrari - Febbraio 10, 2024, 05:27:15 pm
Non dare per scontato ciò che appare ovvio. Le PATH e i nomi dei file non sono solo espressi in "C:" e "/" ... ci sono i percorsi UNC (come i percorsi di rete), e tralasciamo i riferimenti a file su servizi vari leggibili con le normali API.
In alcune modalità, i file si accedono solo ed esclusivamente con definizioni vari (mai usato "\?\" oppure "\.\" ) e così vanno "memorizzati" ...
Capisco e ringrazio per la segnalazione, ma preciso che scrivo programmi (Pascal e Lisp) che uso solo io, quindi scrivere programmi universali sarebbe uno spreco, ammesso che ne sia in grado. Comunque “\?\" oppure "\.\" li ho visti i giro, ma non ho mai capito a cosa si riferiscano.
Per la verità in qualche lavoro di gruppo mi sono portato dietro i miei Lisp, che ho usato su computer di colleghi. A distanza di un paio d’anni vedo che qualcuno li usa ancora …
Titolo: Re:TrueName
Inserito da: DragoRosso - Febbraio 10, 2024, 06:50:22 pm
Per cortesia confermami o meno solo se ho capito bene: a 7-bit (cioè sino ad ASCII 127) Ansi e Unicode sono identici. Se è così posso ignorare i warning. Per i nomi file vado, tassativamente, a 7-bit.

Ti confermo ma solo per Unicode UTF-8. Gli altri usano la codifica a 2 byte, per cui i caratteri non sono uguali.
Ma all'interno di Lazarus / FPC puoi usare ANSI senza problemi.

Ciao

Titolo: Re:TrueName
Inserito da: quack - Febbraio 10, 2024, 07:22:05 pm
rispondo agli altri punti rimasti in sospeso:

...
mkExactMatch esce anche se metti una wildcard, e viene restituito anche il nome esatto (il primo che trova con quella wildcard).
c'è una nota nella documentazione della funzione che suggerisce di non utilizzare le wildcard proprio per il malfunzionamento che segnali.

Citazione
PS: prova ad usare il tipo string invece di ansistring...
Si è stata una mia svista, non avevo visto che assegnavi alla stringa ansi il valore della unicode, il warning nasce da lì ... come ha spiegato DragoRosso.

Ciao