オブジェクトの値をXMLファイルに保存する、開く

ある程度複雑なアプリケーションの場合は EXE 単体で動作することはなく、EXE と共にパラメータファイルが必要になる場合が多いです。

2022年現在のトレンドとしては、そういったパラメータファイルには json 形式が用いられる場合が多いです。その次に XML 形式でしょうか。さすがに ini ファイル形式を新規案件で採用することは無さそうです。

ここでは、オブジェクトのフィールドの値を XML 形式で保存したり、開いたりするコードを示します。

まずこちらがクラスオブジェクトの定義です。

using System;

namespace aaa
{

	public class TheParametersObject
	{

		public int       ValueI;
		public long      ValueL;
		public double    ValueD;
		public float     ValueF;
		public String    ValueS;
		public bool      ValueB;

		public TheParametersObject()
		{
			ValueI = 123;
			ValueL = 456;
			ValueD = 7.89;
			ValueF = 12.34f;
			ValueS = "hello";
			ValueB = true;
		}

		public void Nop()
		{
			// NOP.
		}

		public bool ReturnTrue()
		{
			return true;
		}

		public bool ReturnFalse()
		{
			return false;
		}

	}

}

XMLファイルのパスは const String で決め打ちにしてあります。
c:/tmp/parameters.xml
です。

下記の名前空間の追加をお忘れなく。
using System.Xml.Serialization;
using System.IO;

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

// この using 追加を忘れずに. Don't forget to add this sentence.
using System.Xml.Serialization;
using System.IO;

namespace aaa
{

	public partial class Form1 : Form
	{

		// 拡張子は XML である必要はない.
		// TXT のほうがテキストエディタでラクに開ける.
		const String FILEPATH_PRM = "c:/tmp/parameters.xml";

		// データをよみこむオブジェクト.
		TheParametersObject MyObj = new TheParametersObject();

		public Form1()
		{
			InitializeComponent();
		}

		// オブジェクトのフィールドの値をXMLファイル形式で保存する.
		private void menuFileSave_Click( object sender, EventArgs e )
		{

			// インスタンスが生成されているかいちおうチェックする.
			if ( MyObj == null )
			{
				MessageBox.Show( "MyObj is NULL." );
				return;
			}

			// XML読み書きクラスを生成する.
			XmlSerializer xmser = new XmlSerializer( typeof( TheParametersObject ) );

			try
			{
				// BOM無しUTF8エンコーディング.
				Encoding enc = new UTF8Encoding( false );

				// ファイルに書き込む.
				using ( StreamWriter sw = new StreamWriter( FILEPATH_PRM, false, enc ) )
				{
					xmser.Serialize( sw, MyObj );
					sw.Close();
				}

			}
			catch ( Exception excp )
			{
				MessageBox.Show( excp.Message );
				return;
			}

		}

		// XMLファイル形式で記述された値をオブジェクトのフィールドに読み込む.
		private void menuFileOpen_Click( object sender, EventArgs e )
		{

			// ファイルがあるか調べる.
			if ( File.Exists( FILEPATH_PRM ) == false )
			{
				String strerr = String.Format( "File.Exists( {0} ) is false.", FILEPATH_PRM );
				MessageBox.Show( strerr );
				return;
			}

			// インスタンスが生成されているかいちおうチェックする.
			if ( MyObj == null )
			{
				MessageBox.Show( "MyObj is NULL." );
				return;
			}

			// XML読み書きクラスを生成する.
			XmlSerializer xmser = new XmlSerializer( typeof( TheParametersObject ) );

			try
			{
				// BOM無しUTF8エンコーディング.
				Encoding enc = new UTF8Encoding( false );

				// ファイルから読み出す.
				using ( StreamReader sr = new StreamReader( FILEPATH_PRM, enc ) )
				{
					MyObj = ( TheParametersObject )( xmser.Deserialize( sr ) );
					sr.Close();
				}

			}
			catch ( Exception excp )
			{
				MessageBox.Show( excp.Message );
				return;
			}

			// 内容表示用のストリングビルダ.
			StringBuilder sb = new StringBuilder();

			sb.AppendLine( MyObj.ValueI.ToString() );
			sb.AppendLine( MyObj.ValueL.ToString() );
			sb.AppendLine( MyObj.ValueD.ToString() );
			sb.AppendLine( MyObj.ValueF.ToString() );
			sb.AppendLine( MyObj.ValueS.ToString() );
			sb.AppendLine( MyObj.ValueB.ToString() );

			// メッセージボックスに表示する.
			String strmsg = sb.ToString().Trim();
			String cap = "実行結果";
			MessageBox.Show( strmsg, cap );

		}

	}

}

50行目 と 93行目は、特に注意を払わなければならないところです。ここはテキストファイルの保存形式を決めるところです。UTF-8だとか、UTF-16だとか、BOMなしだとか、BOMありだとか、Shift-JISだとか、unicode だとか、ここは非常に重要なところです。

特に String 型のフィールドに日本語が格納されている場合に、ここの認識がおろそかだとドハマリします。2022年現在では、UTF-8 のBOMなしにしておけば問題ないでしょう。BOMありにしたかったら enc = new UTF8Encoding( true ); と引数に true を入れてください。

といってもこういうのはトレンドがどんどん変化していくので、プログラマ生活を続けているうちは流行に敏感でいてください。

最後にまったくの余談ですが、ini ファイルは本当に新規案件での採用はないのでしょうかね...
自分の周りではそういう事例がないだけで、実は現役だったりしたらどうしよう...