ファイルを操作する - ページ 5

 
Yedelkin:

質問1:ドキュメントに誤字があり、"Last Read Date "の代わりに "Last Open Date "のような表記が必要だと思いませんか?

そう、これがその逐語的なものだ。

lpLastAccessTime[out、オプション]。

ファイルまたはディレクトリが最後にアクセスされた日時を受け取るためのFILETIME 構造体へのポインタを指定します。最終アクセス時刻には、そのファイルやディレクトリに最後に書き込まれた時刻、読み込まれた時刻、実行可能ファイルの場合は実行時刻が含まれる。

緩やかな翻訳 -- 最終アクセスには、ファイルが最後に読み書きされた時刻、または(実行可能な場合は)実行された時刻が含まれます。

ハンドルのオーバーライドについては、たぶん間違っていると思いますが、こんな面白い文章もあります。

すべてのファイルシステムが作成時刻と最終アクセス時刻を記録できるわけではなく、また、すべてのファイルシステムが同じ方法で記録するわけでもありません。例えば、FATの場合、作成時間は10ミリ秒、書き込み時間は2秒、アクセス時間は1日(本当はアクセス日)の分解能を持つ。そのため、GetFileTime 関数は、SetFileTime 関数で設定したファイル時刻情報と同じものを返さない場合があります。

NTFSは、ファイルの最終アクセス時刻の更新を、最終アクセスから最大1時間遅らせることができます。NTFSでは、最終アクセス時刻の更新を無効にすることも可能です。NTFSボリュームでは、デフォルトでラストアクセスタイムが更新されません。

現状では、ハンドルを「開き直す」ことなく、ファイルのプロパティを取得した場合に、幸福が期待できる。

どうやら、少なくとも秒単位では運がないようだ。
 
TheXpert:

そう、これがその逐語的なものだ。

緩やかな翻訳 -- 最終アクセスには、ファイルが最後に読み書きされた時刻、または(実行可能な場合は)実行された時刻が含まれます。

ハンドルのオーバーライドについては私の勘違いでしょうが、こんな面白い文章もあります。

どうやら、少なくとも秒単位ではそんな運はないようだ。

心の広がりをありがとうございましたああ...ガッカリだ。

このスクリプトでは、識別子FILE_ACCESS_DATEの 代わりに、最後にファイルを閉じた 時刻を返すとしています。

int handle_file;
void OnStart()
  {
   Print("===============================================");
   handle_file=FileOpen("Ye_file2.bin",FILE_READ|FILE_WRITE|FILE_BIN);
   switch(handle_file)
     {
      case  INVALID_HANDLE: break;
      default:
         Print("Дата создания файла Ye_file2.bin: ",(datetime)FileGetInteger(handle_file,FILE_CREATE_DATE));
         for(int i=0;i<3;i++)
           {
            Sleep(2000);
            FileReadInteger(handle_file,CHAR_VALUE);
            Print("Дата последнего чтения Ye_file2.bin: ",(datetime)FileGetInteger(handle_file,FILE_ACCESS_DATE));
           }
         Sleep(3000);
         Print("Время обращения к FileClose(handle_file): ",TimeTradeServer());
         FileClose(handle_file);
     }
  }
 
TheXpert:

しかし、乱暴な結論ではありますが、テストでは明らかになっているので、変化がない場合の機能の動作については、開発者のコメントを待ちたいと思います。

ちなみに、この3ヶ月はコメントをいただいていないので、当面はFileFlush()の 使用は避けています。
 

FileCloseの代わりにFileFlushを使用しても、プログラムの速度が低下/加速することはないように思われます。

ただ、レコードごとにループで使うのは意味がない。もしWordが文書を変更するたびに再保存していたら、どんなに遅くなるか想像してみてください(特にその文書にたくさんのテキストや画像がある場合)。FileFLushは、ファイルを閉じる ことなく保存することのみを容易にします。

開発者は、(例えば)こんな意味で言ったのでしょう。

OnInit - FileOpen

オンティック - FileWrite FileFlush

(ここで、データはループ内で -FileFlash - 保存されます。ループの各パスではなく、ループが終了した後に保存されます)

OnDeinit FileClose.

FileFlash のポイントは、Expert Advisor が実行されている間、常にそこに書き込むことで、ファイルハンドルと神秘的なファイルバッファを常に再初期化しないようにすることです。

...................................)

 
Yedelkin:
ちなみに、ここ3ヶ月ほどはコメントをいただいていないので、当面はFileFlush()の使用は控えています。
とにかくすぐに保存できることを保証するものではありません。ですから、ハンドルを閉じることなく、現在の状態を保存するために使用するのが唯一の理にかなっています。
 
イェデルキン
ちなみに、ここ3ヶ月ほどはコメントをいただいていないので、当面はFileFlush()の使用は避けています。

FileFlush()関数を 使用する意味をより良く理解するために、ファイルの入出力バッファの概念について考える必要があります...ディスクの情報はバイト単位で保存されており、バイト単位で書き込むのは無駄の極みであることはご存じのとおりです。このプロセスを「ハードウェア」の側面から見ると、バイト書き込みの要求のたびに、OSはハードディスクドライブの「ライターの頭をくねらせる」必要があるのだ!そして、ハードディスクはキネマティック!?つまり、すべてのコンピュータ機器の中で最も遅いのである。では、その解決策は?とてもシンプルなソリューションです。コンピュータのメモリ内にデータのバッファ(通常数十キロバイト)を作り、そこにFileWriteなどのデータを送り、このバッファが完全に埋まり次第、連続したデータのブロックとしてハードディスクに書き込むため、不要なドライブヘッドの操作がなく、1台のマシンで簡単にデータを書き込むことができます。では、32キロバイトの情報を一度に書き込む場合、同じサイズのバイトを1つずつ書き込む場合と比較して、何倍速くなるか計算してみましょう ;)そして、その計算はいたってシンプル...。書き込み動作のたびに、まずドライブヘッドが位置決めされ、その後書き込み動作が行われます。しかも、それは読み書きの難しい操作には触れないままです :)バッファの場合は、ドライブヘッドを一度位置決めして、ブロック全体を1ストリームで書き込むのです

しかし、バッファが一杯になるまでは、データは物理的にファイルに現れない(!!)し、ファイル自体を閉じるまでは、バッファ(というかバッファに残っているもの)は直ちにディスクに書き込まれます。そこで登場するのがFileFlush関数です。ある情報をファイルに「書き込み」、その情報をファイルに表示する必要がある場合(例えば、この情報は他のプログラム、インジケータ、Expert Advisorなどで既に使用されている可能性があります)、FileFlush関数を呼び出し、バッファの内容をディスク(ファイル)に物理的にダンプします!この関数は、バッファの内容をファイルにダンプします。

結論:ファイル操作を高速化するためにFileFlush関数を頻繁に使用したり、ループで使用したりすると、逆の結果になります。なぜなら、呼び出しごとに、I/Oバッファに実際に含まれる情報量を計算し、オペレーティングシステムを呼び出し、このメモリ領域をファイルに書き込むコマンドを与える必要があるからです例えば、ループが1バイトをファイルに書き込み、すぐにFileFlush関数を呼び出すと、ディスクへの書き込みの最も遅い方法BACKGROUND!!!を得ることができます。;)

では、ファイルへの書き込みはどのように行うのが一番速いのでしょうか?とてもシンプルです ;)ごちゃごちゃ言わず、FileFlushを虐めてください :)この場合、FileWriteとクリップボードの間で高速なデータ交換が行われます(メモリ操作が最速です)。 システムはこのバッファのオーバーフローを監視し、必要に応じてデータをストリームし(ハードディスクのような不器用なデバイスでは最速の操作!)、新しいデータを受け取るためにバッファをクリアします!!!

そこで、「なぜFileFlush関数が必要なのか」という疑問が湧いてきます。そして、その答えは簡単で、バッファフィルに関係なく、物理的にデータをファイルに書き込む必要があるときに必要なのです。上記でそのような必要性の例を挙げました。

Документация по MQL5: Файловые операции / FileFlush
Документация по MQL5: Файловые операции / FileFlush
  • www.mql5.com
Файловые операции / FileFlush - Документация по MQL5
 

MQL5用にインジケータを書き直したところ、深刻な混乱に遭遇しました :(

以下はそのコードです。

  first_bar=ChartGetInteger(0,CHART_FIRST_VISIBLE_BAR,0);
  
  //--- установим доступ к массиву как к таймсерии
  ResetLastError();
  int copied=CopyTime(NULL,0,0,first_bar,TimeAsSeries);
  del();
  int handle=FileOpen("Price Label\\"+_Symbol+tpl_ext,FILE_READ|FILE_CSV,';',CP_ACP);
  int er=GetLastError();
  ResetLastError();
  
  string sTF="";
  int TF;
  string period_name;
  string price_label;
  string price1;
  string price2;
  
  if (handle>=1){
    while(FileIsEnding(handle)==false){
      sTF = FileReadString(handle);
      TF = ResolveTF(sTF);
      period_name=FileReadString(handle);
      price_label=FileReadString(handle);
      price1=FileReadString(handle);
      price2=FileReadString(handle);
      drawe_price(TF,handle,period_name,price_label,price1,price2);
    }
    FileClose(handle);
  }
  return(0);

デバッガで様子を見るために、これだけ大量の変数を入力したことを、すぐに説明したい。そして、私は見た...

このファイルにはたくさんの文字列が含まれており、各文字列は"; "で区切られた5つのセクションから構成されています。最初のコール

sTF = FileReadString(handle);

は、ファイル全体を訳の分からないエンコーディングでsTF変数に入れます。デバッガで見た感じでは(sTF変数ではファイルの内容をunicodeで読んでいる!?ファイルを開く ときに、利用可能なすべてのコードページを試しましたが、結果は同じです :( ファイル自体は、Windowsのエンコーディングで書かれています。

その犬がどこに埋められているか、誰か知っている人はいますか?

Документация по MQL5: Файловые операции / FileOpen
Документация по MQL5: Файловые операции / FileOpen
  • www.mql5.com
Файловые операции / FileOpen - Документация по MQL5
 

is_vale

皆さん、情報を教えてくれてありがとうございましたあらためてテーマに飛び込んでみます。

 
FILE_ANSI
 
is_vale:

どなたか、問題の所在をご存知の方はいらっしゃいますか?

長い間、ファイル操作をしていなかったので...。ほら、FileOpen() を使うときはCSVファイルが宣言されて いるでしょ。以前は、書き込まれた項目はすべてユニコードまたはアンシ文字列に変換されるように指定されていました。も しかして、ここが犬の居場所?