AndroidでデータFileをstringgridに表示

解決


Hiisan  2019-11-08 12:45:04  No: 148364  IP: 192.*.*.*

Androidで、データFile(CsvFile等)をStringGrid等にOpenとSaveの方法
Android.Content.contextにOpenFileOutput&Inputがあるそうですが、Delphi10.3.2/Delphi Comunity Editでは、見当たりませんでした。
Delphi/Androidで、同等の動作を、させる方法を、お教え願います。


/

編集 削除
KONNOYA  2019-11-13 08:11:14  No: 148372  IP: 192.*.*.*

> Android.Content.contextにOpenFileOutput&Inputがあるそうですが
それによる方法は知りませんが、出来たとしてもAndroidのみでの動作となってしまうので、
TStringListによる通常の読み込みではどうですか?


function TForm1.LoadCsvFileGrid( const ASG : TStringGrid; const AFilePath : String ) : Boolean;

var
  SL : TStringList;
  SS : TStringList;
  Row, Col : Integer;
  lc1 : Integer;

begin
  if Not FileExists( AFilePath ) then Exit( FALSE );

  SL := TStringList.Create;
  SS := TStringList.Create;
  try
    SL.LoadFromFile( AFilePath );
    if SL.Count = 0 then Exit( FALSE );

    for Row := 0 to SL.Count - 1 do
    begin
      SS.Delimiter := ',';
      SS.QuoteChar := '"';
      SS.CommaText := SL[ Row ];

      if SS.Count <> 0 then
      begin
        ASG.RowCount := SL.Count;
        if ASG.ColumnCount < SS.Count then
        begin
          for lc1 := 0 to SS.Count - ASG.ColumnCount - 1 do
          begin
            ASG.AddObject( TStringColumn.Create( ASG ) );
          end;
        end;
        for Col := 0 to SS.Count - 1 do
        begin
          ASG.Cells[ Col, Row ] := SS[ Col ];
        end;
      end;
    end;
  finally
    SS.DisposeOf;
    SL.DisposeOf;
  end;
  Result := TRUE;
end;

function TForm1.SaveCsvFileGrid( const ASG : TStringGrid; const AFilePath : String ) : Boolean;

var
  SL : TStringList;
  Data : TStringDynArray;
  Row, Col : Integer;

begin
  if ( ASG.RowCount = 0 ) or ( ASG.ColumnCount = 0 ) then Exit( FALSE );

  SL := TStringList.Create;
  try
    for Row := 0 to ASG.RowCount - 1 do
    begin
      SetLength( Data, ASG.ColumnCount );
      for Col := 0 to ASG.ColumnCount - 1 do
      begin
        Data[ Col ] := ASG.Cells[ Col, Row ].QuotedString( '"' );
      end;
      SL.Add( String.Join( ',', Data ) );
    end;
    SL.SaveToFile( AFilePath, TEncoding.Unicode );
  finally
    SL.DisposeOf;
  end;
  Result := TRUE;
end;

CSVデータに半角ダブルクオーテーションが含まれている場合、""という風になっていなければ正しく切り取れません。
そこら辺は工夫してみて下さい。
TStringGridのセル幅は、TStringColumn.Widthでコード内から変更できます。

編集 削除
Hiisan  2019-11-13 14:57:50  No: 148375  IP: 192.*.*.*

KONNOYAさま、説明不足で申し訳ございません。Delphi10.3のマルチデバイス・アプリケーションで動作させますので、
PC--->Androidで作成します。Windowとマルチデバイスでの、Syntaxが、相当違うのと、私は、Delphi6から10.3(無料のCommunity Edit版)に変更して
1か月余りで、超初心者です。現在は、例えばListBox.LoadFrom(Path+'X.Dat')で表示できないか、考えているのですが、Pathの表記でとまどつている状態です。今考えている方針は、
[1]PC側から¥internal\assetsにX.Datをコピー
[2]Android側(SmartFon)配置デバイスでX.Datを登録
[3]Path.Combine(TPath.GetDocumentsPath,'XDat');  Uses System.utilsは、追加済みです
[4]コンパイル--->実行
[5]ListBox.LoadFrom(Folder+’X.Dat')--->ここがFolderが上手くいかず。Not Such Directory:エラーが発生し困っています。
 Windowであれば
AssignFile(F)
Rewrite(F)
repeat
  Write(F,S)
ListBox.Items.Add(S); 
until Eof(F);
CloseFile
Android では、このコマンドが、現在見当たりません。
現在のFolderの設定は、[\internal\Assets](//+’¥X.dat’)
[6]AssetsにX.Datがあるので、上記[1-3]をセットせず、ListBox.LoadFromFile(Path+'X.Dat')のみで、動作しない、でしょうか
よろしくご指導願います。
以上

編集 削除
KONNOYA  2019-11-13 23:48:39  No: 148377  IP: 192.*.*.*

下記の様にできます。

(1) 配置にx.datを追加
(2) x.datの「リモートパス」を「.\assets\internal\」に変更
(3) 下記のコードを実行

uses
  ・・・
  System.IOUtils;

procedure TForm1.Button1Click( Sender : TObject );

var
  FilePath : String;

begin
  FilePath := TPath.Combine( TPath.GetDocumentsPath, 'X.dat' );
  ListBox1.Items.LoadFromFile( FilePath );
end;

これで私のAndroidでは、ListBoxにファイル内容が表示されました。

編集 削除
Hiisan  2019-11-14 10:22:50  No: 148382  IP: 192.*.*.*

KONNOYAさま、ご指導どうも有難う御座いました。下記項目について宜しく御願いいたします。
  (リストボックスへの書き込みが、出来ません)
[1]配置プロジェクトにX.Datを登録して、[リモートパス]を変更したのですが、登録Itemが、グレイ表示されます。
 すべての構成、Debug,Releaseのwindow32bitとandroidの選択は、:この組み合わせを変えて試しましたが、グレイ表示のままです。
[2] [1]以外に、考えられること
以上 宜しくお願い致します。

  

編集 削除
Hiisan  2019-11-14 22:15:33  No: 148383  IP: 192.*.*.*

追記です。下記エラーが、出て
FilePathが、[\data\data\com.Embarcadero.project7\file\x.dat]データをOpen出来ない。
このフォルダーの変更方法ません。

編集 削除
KONNOYA  2019-11-15 03:30:03  No: 148384  IP: 192.*.*.*

> [1]配置プロジェクトにX.Datを登録して、[リモートパス]を変更したのですが、登録Itemが、グレイ表示されます。

その登録した x.datファイルをWindows上で 削除 or 移動 or リネーム とか行っていないですか?

> FilePathが、[\data\data\com.Embarcadero.project7\file\x.dat]データをOpen出来ない。
> このフォルダーの変更方法ません。

x.datファイルの 削除 or 移動 or リネーム をしてしまっていたら、x.datの行を削除して、もう一度登録を行えばOKです。

> [2] [1]以外に、考えられること

x.datファイルの内容が変わらないという前提なら、リソースファイルにする方法があります。

(1)「Delphiメニュー」→「プロジェクト」→「リソースと画像」をクリック
(2)「追加」ボタンを押下
(3) ファイル拡張子の欄で「すべてのファイル(*.*)」を選択
(4) x.datを選択して「開く」ボタンを押下
(5) するとリソースファイルのリストに1件追加され、リソース識別子が「Resource_1」となっている
(6) リソース識別子は自分が分かりやすい任意の文字列で指定 ( 後にプログラムコードで指定する文字列となる )
(7) リソースタイプは「RCDATA」とする
(8) 下記のコードを実行

procedure TForm1.Button1Click( Sender : TObject );

var
  RS : TResourceStream;

begin
  RS := TResourceStream.Create( hInstance, 'Resource_1', RT_RCDATA );  // ← 第2引数にリソース識別子、第3引数にリソースタイプ
  try
    ListBox1.Items.LoadFromStream( RS );
  finally
    FreeAndNil( RS );
  end;
end;

この方法でも、x.datファイル の 削除 or 移動 or リネーム を行うとグレー表示 ( 有効ではない ) になります。
また、brcc32.exe によるリソースファイルの作成でも上のコードで読み出せます。

私がこのスレで投稿したコードは全てFMXのコードです。Androidと仰られていたので…。
その他の要因でグレー表示になるのなら、ちょっと私にはわかりません。

編集 削除
Hiisan  2019-11-17 11:28:47  No: 148387  IP: 192.*.*.*

KONNOYAさま、ご指導本当に有難うございました。
結論から
「1」Steam(no.148383)、配置式(no.148377)両方ともデータをセット出来ました。
   [原因]データのセットアップは、PC側のDataのフォルダーをsetする。
    Assets\Internalと、他のforumに記載されていましたので、疑いませんもしませんでした。
[2]配置Manegerの「gray」表示の件も、解決しました。
[3]両方式とも、読み取り速度が、非常に遅いです。
[4]データは、ユニコード(UTF-8)に変更しました。(Delphi6.0で作成のため)
[5]テスト機器:Lenovo 501LV  Ver:5.0.2 PC:Window10
以上
  KONNOYAさま、本当に有難う御座いました。今後とも宜しく御願い致します。

編集 削除
KONNOYA  2019-11-19 08:23:26  No: 148388  IP: 192.*.*.*

> 3]両方式とも、読み取り速度が、非常に遅いです。
読み込み速度が遅いというよりも、更新が遅いのかも?
TListBoxよりも単純に表示させるだけで良いのなら、TListViewやTMemoではどうですか?

procedure TForm1.Button1Click( Sender : TObject );

var
  FilePath : String;
  SL : TStringList;
  LVI : TListViewItem;
  lc1 : Integer;

begin
  ListView1.BeginUpdate;
  try
    SL := TStringList.Create;
    try
      FilePath := TPath.Combine( TPath.GetDocumentsPath, 'X.dat' );
      SL.LoadFromFile( FilePath );

      if SL.Count > 0 then
      begin
        for lc1 := 0 to SL.Count - 1 do
        begin
          LVI := ListView1.Items.Add;
          LVI.Text := SL[ lc1 ];
        end;
      end;
    finally
      SL.DisposeOf;
    end;
  finally
    ListView1.EndUpdate;
  end;
end;

Android実機での速度検証の結果、
「x.datファイル」:ランダムなキャラクタ256文字 × 10000行
を読み込むのに
TListBoxだと、大まかですが約40000~45000msでした。
TListViewだと、上記のコードで約223msでした。
※ System.DateUtils.MilliSecondOfTheDayで計測

リストに追加の際は、BeginUpdate ~ EndUpdateで括ると良いです。

編集 削除