Probleme mit FileWriteString(), FileReadString()

Einloggen oder registrieren, um einen Kommentar zu schreiben
Otto Pauser
1874
Otto Pauser  

Das hat doch bisher funktioniert.

Teile des Codes eines NewsReaders:

         int filehandle=FileOpen("news-log.txt",FILE_WRITE|FILE_BIN);
         if(filehandle!=INVALID_HANDLE)
            {
               FileWriteArray(filehandle,WebResult,0,ArraySize(WebResult));  // alles ok
               FileClose(filehandle);                                        // alles ok

               filehandle=FileOpen("news-log.txt",FILE_READ|FILE_BIN);
               if(filehandle!=INVALID_HANDLE)
                  {
                     string text=FileReadString(filehandle,ArraySize(WebResult));
                     FileClose(filehandle);
                     return(text);
                 }
            }
         else
            Print("Error in FileOpen. Error code =",GetLastError());
char WebResult[]; enthält gültige Textzeichen, Die Datei wird auch ordnungsgemäß geschrieben:
<!DOCTYPE HTML>
<html dir="ltr" xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:schema="http://schema.org/" class="com" lang="en">
    <head>
    <meta name="robots" content="noindex">
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />

    <!-- css -->

usw....
Das Ergebnis in der variablen text (etwas gekürzt)  ist allerdings nicht gerade das was ich will:
ℼ佄呃偙⁅呈䱍ാ㰊瑨汭搠物∽瑬≲砠汭獮∽瑨灴⼺眯睷眮⸳牯⽧㤱㤹砯瑨汭•浸㩬慬杮∽湥•浸湬㩳捳敨慭∽瑨灴⼺猯档浥⹡牯⽧•汣獡㵳挢浯•慬杮∽湥㸢਍††格慥㹤਍††洼瑥⁡慮敭∽潲潢獴•潣瑮湥㵴渢楯摮硥㸢਍††洼瑥⁡瑨灴攭畱癩∽ⵘ䅕䌭浯慰楴汢≥挠湯整瑮∽

Die Doku sagt:

FILE_BIN 4 Binary read/write mode (without string to string conversion). Flag is used in FileOpen().
 

Also sollten die Zeichen 1:1 gelesen werden. Wieso dann chinesische (oder was auch immer) Zeichen?

Die Textdatei hab ich mit einem Hex-Editor überprüft, ist standard 1 byte Ascii-Datei.

Dank im Vorraus für Info!

Alain Verleyen
38374
Alain Verleyen  

Verwenden

filehandle=FileOpen("news-log.txt",FILE_READ|FILE_TXT|FILE_ANSI);

Oder

filehandle=FileOpen("news-log.txt",FILE_READ|FILE_BIN);
if(filehandle!=INVALID_HANDLE)
 {
   uchar read[];
   FileReadArray(filehandle,read);
   FileClose(filehandle);
   return(CharArrayToString(read));
 }
Otto Pauser
1874
Otto Pauser  
Alain Verleyen:

Das ist leider auch nicht die Lösung.

Im Fall 1

FILE_READ|FILE_TXT|FILE_ANSI

erhalte ich den Text Zeilenweise da cr lf berücksichtigt wird. Und der String zusammengebastelt werden muss

Im Fall 2

FILE_READ|FILE_BIN

erhalte ich den Text als Array. Ich will aber einen STRING!!!!!

In MQL4 funktioniert das problemlos. Wofür gibt es denn die option FILE_BIN wenn da was konvertiert wird.

DAS IST EIN SCHWERER BUG in MQL5

WARUM GLAUBT MIR DENN KEINER ?

Chris70
599
Chris70  

Hallo Otto,

ich konnte das Problem bei mir reproduzieren, i.e. ich bekomme ebenfalls chinesische Zeichen ausgegeben.

Es sind allerdings auch die Flaggen FILE_BIN und FILE_ANSI kombinierbar. Eigentlich macht eine Codepage nach meinem Verständnis bei nackten Binärdaten ja keinen Sinn, jedoch scheint es eine Auswirkung auf FileReadString zu haben - das macht ja hingegen wieder Sinn, denn irgendwie muss dieses Funktion ja auch bei der Interpretation von Char-Arrays aus .bin-Dateien wissen, welche Codepage anzuwenden ist. Keine Ahnung, ob meine Logik da richtig ist, jedenfalls funktioniert es so:

 int OnInit()
  {
   char WebResult[];
   StringToCharArray("Hello World",WebResult,0,WHOLE_ARRAY,CP_UTF8);
   int filehandle=FileOpen("news-log.txt",FILE_WRITE|FILE_BIN);
   if(filehandle!=INVALID_HANDLE)
     {
      FileWriteArray(filehandle,WebResult,0,ArraySize(WebResult));  // alles ok
      FileClose(filehandle);                                        // alles ok

      filehandle=FileOpen("news-log.txt",FILE_READ|FILE_BIN|FILE_ANSI);
      if(filehandle!=INVALID_HANDLE)
        {
         string text=FileReadString(filehandle,ArraySize(WebResult));
         FileClose(filehandle);
         Print("text: ",text); // Ausgabe ohne FILE_ANSI: "text: 效汬潗汲d", mit FILE_ANSI korrekt "text: Hello World"
        }
     }
   else
      Print("Error in FileOpen. Error code =",GetLastError());
   return INIT_SUCCEEDED;
  }
Carl Schreiber
Moderator
8692
Carl Schreiber  

Ich denke, Du hast Recht, aber poste es doch bitte hier:

https://www.mql5.com/ru/forum/324536/page29 inkl. Code-Berispiel.

Die sind zZ heftig am Werkeln, es scheint, als ob alle 3-5 Tage eine neue Beta-Version erscheint.

Новая версия платформы MetaTrader 5 build 2190
Новая версия платформы MetaTrader 5 build 2190
  • 2019.11.16
  • www.mql5.com
В пятницу 18 октября 2019 года будет выпущена обновленная версия платформы MetaTrader 5...
Chris70
599
Chris70  

Alternativmöglichkeit für bin-Datei: gar nicht erst ein char-Array verwenden, sondern beim Schreiben der Datei (FILE_WRITE|FILE_BIN)

string text="Hello World";
FileWriteInteger(handle,StringLen(text),INT_VALUE)
FileWriteString(handle,text,StringLen(text));

und dann beim Lesen (FILE_READ|FILE_BIN)

int length=FileReadInteger(handle,INT_VALUE);
string text=FileReadString(handle,length);

so ist scheinbar sichergestellt, dass FileWriteString und FileReadString die gleiche Codepage verwenden, welche auch immer das sein mag (die Flagge FILE_ANSI ist daher dann überflüssig);

Alain Verleyen
38374
Alain Verleyen  
Otto Pauser :

Das ist leider auch nicht die Lösung.

Im Fall 1

erhalte ich den Text Zeilenweise da cr lf berücksichtigt wird. Und der String zusammengebastelt werden muss

Im Fall 2

erhalte ich den Text als Array. Ich will aber einen STRING!!!!!

In MQL4 funktioniert das problemlos . Wofür gibt es denn die option FILE_BIN wenn da was konvertiert wird.

DAS IST EIN SCHWERER BUG in MQL5

WARUM GLAUBT MIR DENN KEINER ?

Es gibt keinen Fehler, das ist alles normales Verhalten. Natürlich gibt es "CR LF" in der Datei, Sie haben sie geschrieben!

In Fall 2 erhalten Sie eine Zeichenfolge, nachdem Sie das char-Array in eine Zeichenfolge konvertiert haben. Woran liegt das Problem?

   return ( CharArrayToString (read));
Otto Pauser
1874
Otto Pauser  

Danke  @Chris, @Calli, @Alain für die sachdienlichen Hinweise.

@Chris Das schreiben der Datei funktioniert ja wunderbar.  Das CharArray ist das Ergebnis der Funktion WebRequest(), ist also erforderlich.

Sonderbarer Weise funktioniert

filehandle=FileOpen("news-log.txt",FILE_READ|FILE_BIN|FILE_ANSI);

und es kommt, wie erwartet, beim lesen ein String heraus.

Ich halte das nach wie vor für einen bug, denn was hat ein binärfile mit ansi zu tun.

Könnte ja auch ein jpg oder png oder was auch immer sein.

Alain Verleyen
38374
Alain Verleyen  
Chris70 :

Hallo Otto,

ich konnte das Problem bei mir reproduzieren, i.e. ich bekomme ebenfalls chinesische Zeichen ausgegeben.

Es sind allerdings auch die Flaggen FILE_BIN und FILE_ANSI kombinierbar. Eigentlich macht eine Codepage nach meinem Verständnis bei nackten Binärdaten ja keinen Sinn, jedoch scheint es eine Auswirkung auf FileReadString zu haben - das macht ja hingegen wieder Sinn, denn irgendwie muss dieses Funktion ja auch bei der Interpretation von Char-Arrays aus .bin-Dateien wissen, welche Codepage anzuwenden ist. Keine Ahnung, ob meine Logik da richtig ist, jedenfalls funktioniert es so:

Ja, das ist eine dritte Lösung, aber keine gute, weil sie nicht universell ist und nur funktioniert, weil Sie die Länge der Zeichenfolge kennen, bevor Sie sie lesen.

Dies funktioniert, da die ursprüngliche Codierung die Standardcodierung ist. Wenn sie sich unterscheidet, wird eine falsche Zeichenfolge ausgegeben, da die Codepage nicht mit FileReadString () angegeben werden kann.

Alain Verleyen
38374
Alain Verleyen  
Otto Pauser :

Danke  @Chris, @Calli, @Alain für die sachdienlichen Hinweise.

@Chris Das schreiben der Datei funktioniert ja wunderbar.  Das CharArray ist das Ergebnis der Funktion WebRequest(), ist also erforderlich.

Sonderbarer Weise funktioniert

und es kommt, wie erwartet, beim lesen ein String heraus.

Ich halte das nach wie vor für einen bug, denn was hat ein binärfile mit ansi zu tun.

Könnte ja auch ein jpg oder png oder was auch immer sein.

Siehe meine vorherige Antwort an Chris, verwende diese Lösung nicht, es kann nur "Zufall" sein.

Es gibt keinen Bug. Es ist alles normal, ich versuche zu erklären:

Also sollten die Zeichen 1:1 gelesen werden. Wieso dann chinesische (oder was auch immer) Zeichen?

Die Textdatei hab ich mit einem Hex-Editor überprüft, ist standard 1 byte Ascii-Datei.

Sie haben Recht, der Kontext ist ANSI, daher müssen Sie ihn beim Lesen der Daten berücksichtigen.

Wenn Sie öffnen, um als Binärdatei zu lesen, haben Sie ANSI-Codierung, daher müssen Sie in Zeichenfolge konvertieren, da Zeichenfolge in mql5 UNICODE ist.

Wenn Sie als Text öffnen (was die bessere Möglichkeit ist), müssen Sie den ANSI-Modus verwenden und haben CR LF, wie es in der Datei vorhanden ist.

Chris70
599
Chris70  
Otto Pauser:

Ich halte das nach wie vor für einen bug, denn was hat ein binärfile mit ansi zu tun.

Könnte ja auch ein jpg oder png oder was auch immer sein.

Ja, fürs Schreiben ist es irrelevant, denn letztlich handelt es sich ja nur um eine Abfolge von Bits, die auch beim Lesen im Falle von Zahlen nicht weiter interpretiert werden müssen, abgesehen von der nötigen Information ob die Bits/Bytes gerade für int/double/long... stehen sollen.

Aber FileReadString erfordert ja zwangsläufig eine Interpretation. Wie soll die Funktion selbst im Falle einer 1Byte-Kodierung wissen, welche 8 bit für genau welches Zeichen stehen? Irgendeine Referenztabelle ist ja nötig, bzw. kann z.B. als selbstverständlich(!) vorausgesetzt werden, dass es sich gerade um Standard-ASCII handelt?

12
Einloggen oder registrieren, um einen Kommentar zu schreiben