前提
プログラミング初心者です。
できれば細かく丁寧に解説していただけると非常に助かります。
C# でVisual Studio2022 で Windowsフォームアプリ作成しています。
string型の多次元配列(今回の例では30×12×31 要素)の文字列データを作成した外部ファイルに記録し、ソフト再起動時に配列に読み込みできるようにしたいです。
その方法を教えていただけると助かります。
現状、保存する部分のコードがかけていないのでソフトを落とせば配列に格納されたデータは消えてしまいます。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2022/12/13 10:51
退会済みユーザー
2022/12/14 23:29
退会済みユーザー
2022/12/29 01:01
回答4件
0
【訂正&追記】
下に「多次元配列は JSON 文字列にシリアライズできない」と書きましたが、それは System.Text.Json 名前空間のシリアライザ/デシリアライザの場合で Newtonsoft.Json のシリアライザ/デシリアライザは多次元配列にも対応していました。(TN8001 さんのコメントの通り)
Newtonsoft.Json を NuGet からインストールして以下のようにして使えます。
C#
1using System; 2using System.Windows.Forms; 3using Newtonsoft.Json; 4 5namespace WindowsFormsApp1 6{ 7 public partial class Form15 : Form 8 { 9 private string[,,] multidimensionalArray; // 多次元配列 10 private string[][][] jaggedArray; // ジャグ配列 11 private string json1; 12 private string json2; 13 14 public Form15() 15 { 16 InitializeComponent(); 17 } 18 19 // Load イベントで配列の初期化 20 private void Form15_Load(object sender, EventArgs e) 21 { 22 this.multidimensionalArray = new string[30, 12, 31]; 23 for (int i = 0; i < 30; i++) 24 { 25 for (int j = 0; j < 12; j++) 26 { 27 for (int k = 0; k < 31; k++) 28 { 29 this.multidimensionalArray[i, j, k] = 30 $"elem-{i}-{j}-{k}"; 31 } 32 } 33 } 34 35 this.jaggedArray = new string[30][][]; 36 for (int i = 0; i < 30; i++) 37 { 38 this.jaggedArray[i] = new string[12][]; 39 for (int j = 0; j < 12; j++) 40 { 41 this.jaggedArray[i][j] = new string[31]; 42 for (int k = 0; k < 31; k++) 43 { 44 this.jaggedArray[i][j][k] = 45 $"elem-{i}-{j}-{k}"; 46 } 47 } 48 } 49 } 50 51 // Newtonsoft.Json でシリアライズ 52 private void Serialize_Click(object sender, EventArgs e) 53 { 54 // 多次元配列を JSON 文字列にシリアライズ 55 this.json1 = JsonConvert.SerializeObject(this.multidimensionalArray); 56 57 // ジャグ配列を JSON 文字列にシリアライズ 58 this.json2 = JsonConvert.SerializeObject(this.jaggedArray); 59 60 // comp は true になる 61 bool comp = this.json1 == this.json2; 62 } 63 64 // Newtonsoft.Json でデシリアライズ 65 private void Deserialize_Click(object sender, EventArgs e) 66 { 67 // JSON 文字列を多次元配列にデシリアライズ 68 var array1 = JsonConvert.DeserializeObject<string[,,]>(this.json1); 69 70 // JSON 文字列をジャグ配列にデシリアライズ 71 var array2 = JsonConvert.DeserializeObject<string[][][]>(this.json2); 72 } 73 } 74}
配列を JSON 文字列にシリアライズしてファイルに保存し、使うときはファイルから JSON 文字列を取得して元の配列にデシリアライズして使うようにしてはいかがですか?
ただし、多次元配列は JSON 文字列にシリアライズできないので、ジャグ配列を使ってください。
ジャグ配列 (C# プログラミング ガイド)
https://learn.microsoft.com/ja-jp/dotnet/csharp/programming-guide/arrays/jagged-arrays
.NET Framework 4.7.2 以降のバージョンであれば、System.Text.Json 名前空間のシリアライザ/デシリアライザを利用できますので、NuGet から System.Text.Json をインストールしてください。.NET Framework 4.7.2 より前のアプリの場合は Newtonsoft.Json を使ってください。
.NET 内で JSON のシリアル化と逆シリアル化を行う方法
https://learn.microsoft.com/ja-jp/dotnet/standard/serialization/system-text-json/how-to?pivots=dotnet-7-0
サンプルコードを以下に載せておきます。
C#
1using System; 2using System.Windows.Forms; 3using System.Text.Json; 4 5namespace WindowsFormsApp1 6{ 7 public partial class Form15 : Form 8 { 9 private string[,,] multidimensionalArray; // 多次元配列 10 private string[][][] jaggedArray; // ジャグ配列 11 private string json; 12 13 public Form15() 14 { 15 InitializeComponent(); 16 } 17 18 // Load イベントで配列の初期化 19 private void Form15_Load(object sender, EventArgs e) 20 { 21 this.multidimensionalArray = new string[30, 12, 31]; 22 for (int i = 0; i < 30; i++) 23 { 24 for (int j = 0; j < 12; j++) 25 { 26 for (int k = 0; k < 31; k++) 27 { 28 this.multidimensionalArray[i, j, k] = $"elem-{i}-{j}-{k}"; 29 } 30 } 31 } 32 33 this.jaggedArray = new string[30][][]; 34 for (int i = 0; i < 30; i++) 35 { 36 this.jaggedArray[i] = new string[12][]; 37 for (int j = 0; j < 12; j++) 38 { 39 this.jaggedArray[i][j] = new string[31]; 40 for (int k = 0; k < 31; k++) 41 { 42 this.jaggedArray[i][j][k] = $"elem-{i}-{j}-{k}"; 43 } 44 } 45 } 46 } 47 48 // 配列を JSON 文字列にシリアライズ 49 private void Serialize_Click(object sender, EventArgs e) 50 { 51 // 多次元配列の JSON シリアル化はサポートされてない。以下の例がスローされる 52 // System.NotSupportedException The type 'System.String[,,]' is not supported. 53 //string json = JsonSerializer.Serialize(this.multidimensionalArray); 54 55 this.json = JsonSerializer.Serialize(this.jaggedArray); 56 } 57 58 // JSON 文字列からジャグ配列にデシリアライズ 59 private void Deserialize_Click(object sender, EventArgs e) 60 { 61 var array = JsonSerializer.Deserialize<string[][][]>(this.json); 62 } 63 } 64}
シリアライズ/デシリアライズの結果は以下のようになります。
投稿2022/12/14 03:24
編集2022/12/14 06:07退会済みユーザー
総合スコア0
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2022/12/14 11:30 編集
退会済みユーザー
2022/12/14 05:46
0
私自身 C# はあまり触れた経験が無いため,超初心者目線での話になりますが…
- 自分で必要十分と思える「てきとーフォーマット」を定めて読み書きするのが(学習コスト的な意味で/ブラックボックスが少ない的な意味で気分的に?)楽なんじゃないかな?
- とりあえず最初は1次元のデータあたりで,軽く練習してみては?
…とか思います.
例えば,以下のコードは 初心者丸出し 且つ いろいろといい加減な所が多い ですが,ファイル保存/読込の最初の練習としては,こんな感じのところからやってみるのが良いのではないかな? みたいな.
C#
1//コンソールアプリで書いた. 2//読み書き対象のデータは1次元配列. 3//ググったら StreamReader, StreamWriter というやつでやれるぞ,って感じの話が見つかったのでこいつらを使用した. 4 5class Program 6{ 7 /// <summary> 8 /// Dataの内容をファイルに保存する. 9 /// <remarks> 10 /// ※とりあえず話を簡単にするために,各stringは改行を含まない想定. 11 /// </remarks> 12 /// </summary> 13 /// <param name="FilePath">保存ファイルパス名</param> 14 /// <param name="Data">保存対象データ</param> 15 /// <returns>成否</returns> 16 static bool Save( string FilePath, string[] Data ) 17 { 18 try 19 { 20 using( var SW = new StreamWriter( FilePath ) ) 21 { 22 //最初の行にはデータ数を出力 23 SW.WriteLine( Data.Length.ToString() ); 24 //以降は1行に1データをダブルクォートで囲んだ状態で出力 25 foreach( var s in Data ){ SW.WriteLine( "\"" + s + "\"" ); } 26 } 27 return true; 28 } 29 catch( Exception ex ) //←ココを真面目に書くのは面倒そうだなぁ 30 {//ココでいきなりコンソールにメッセージ吐いちゃう 31 Console.WriteLine( "In Save() : " + ex.Message ); 32 return false; 33 } 34 } 35 36 /// <summary> 37 /// Save()で保存したファイルを読込む. 38 /// </summary> 39 /// <param name="FilePath"></param> 40 /// <returns> 41 /// 結果データ. 42 /// ただしエラー時にはnullを返す. 43 /// </returns> 44 static string[] Load( string FilePath ) 45 { 46 try 47 { 48 using( var SR = new StreamReader( FilePath ) ) 49 { 50 int nStrs = int.Parse( SR.ReadLine() ); 51 if( nStrs <= 0 ) 52 { throw new Exception( "Invalid Data Count : " + nStrs.ToString() ); } 53 54 var Data = new string[nStrs]; 55 for( int i=0; i<nStrs; ++i ) 56 { 57 string LineStr = SR.ReadLine().Trim(); 58 if( !LineStr.StartsWith( "\"" ) || !LineStr.EndsWith( "\"" ) ) 59 { throw new Exception( "FormatErr : " + LineStr ); } 60 61 Data[i] = LineStr.Trim( '\"' ); 62 } 63 return Data; 64 } 65 } 66 catch( Exception ex ) 67 { 68 Console.WriteLine( "In Load() : " + ex.Message ); 69 return null; 70 } 71 } 72 73 //Main 74 static void Main() 75 {//ファイルに保存して→それを即読込む,というのをやってみる 76 string FilePath = "Test.txt"; 77 78 {//Test Save() 79 var Strs = new string[] 80 { 81 "Hello World", 82 " Cat ", 83 " Kitten " 84 }; 85 86 if( !Save( FilePath, Strs ) )return; 87 } 88 89 {//Test Load() 90 var Strs = Load( FilePath ); 91 if( Strs != null ) 92 { 93 Console.WriteLine( Strs.Length.ToString() + " strs :" ); 94 foreach( var s in Strs ){ Console.WriteLine( "[" + s + "]" ); } 95 } 96 } 97 98 Console.Read(); 99 } 100}
投稿2022/12/14 01:57
編集2022/12/14 01:58総合スコア11660
0
JSONで記録しておくのはいかがでしょうか
投稿2022/12/13 10:35
総合スコア1453
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2022/12/13 10:43
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。