Androidで、データFile(CsvFile等)をStringGrid等にOpenとSaveの方法
Android.Content.contextにOpenFileOutput&Inputがあるそうですが、Delphi10.3.2/Delphi Comunity Editでは、見当たりませんでした。
Delphi/Androidで、同等の動作を、させる方法を、お教え願います。
/
> 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でコード内から変更できます。
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')のみで、動作しない、でしょうか
よろしくご指導願います。
以上
下記の様にできます。
(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にファイル内容が表示されました。
KONNOYAさま、ご指導どうも有難う御座いました。下記項目について宜しく御願いいたします。
(リストボックスへの書き込みが、出来ません)
[1]配置プロジェクトにX.Datを登録して、[リモートパス]を変更したのですが、登録Itemが、グレイ表示されます。
すべての構成、Debug,Releaseのwindow32bitとandroidの選択は、:この組み合わせを変えて試しましたが、グレイ表示のままです。
[2] [1]以外に、考えられること
以上 宜しくお願い致します。
追記です。下記エラーが、出て
FilePathが、[\data\data\com.Embarcadero.project7\file\x.dat]データをOpen出来ない。
このフォルダーの変更方法ません。
> [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と仰られていたので…。
その他の要因でグレー表示になるのなら、ちょっと私にはわかりません。
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さま、本当に有難う御座いました。今後とも宜しく御願い致します。
> 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で括ると良いです。