S_a_k_Uの日記みたいなDB

~サクゥーと呼ばないで~

文字列に対して一定のバイト数で処理する

今日の課題です。
・文字列を一定のバイト数に分割する
・文字列に一定のバイト数毎に文字列を挿入する。

StringDivider

文字列分割処理クラス
文字列を1文字ずつ抽出してバイト数を検知する。
検知したらIStringDivideProcessを呼び出して、任意の処理を行う。
IStringDivideProcessでのコールバックのような呼び出しではなく、StringDividerを継承してProcessメソッドをオーバーライドするような設計もありだけどね。
というか、そっちが普通なんだろうけど、あくまで課題ということでw

IStringDivideProcess

バイト数毎に行う処理のインターフェース

StringDivideCreateList

バイト数で分割した文字列のリストを作成するクラス
IStringDivideProcessの実装。

StringDivideInsertText

バイト数毎に文字列を挿入するクラス
IStringDivideProcessを実装。

ソース

プロパティのsetを省略したり、privateを付けて、読み取り専用みたいなこととか。

using System;

namespace TrialProject.Jp.Saku
{


    /// <summary>
    /// 文字列分割処理クラス<br />
    /// </summary>
    public class StringDivider
    {

        [STAThread]
        public static void Main()
        {
            string text = "1234567890abcefghigjklmnopqrstuvwxyz";

            // 分割した文字列をListにする
            System.Diagnostics.Debug.WriteLine("【分割した文字列をListにする】");
            StringDivideCreateList list = new StringDivideCreateList();
            StringDivider divList = new StringDivider(text, 5, list);
            divList.Divide();
            foreach (string str in list.List)
            {
                // 分割された文字列のリストを出力
                System.Diagnostics.Debug.WriteLine(str + "[" + str.Length + "]");
            }

            // 分割した文字列に文字列を挿入する
            System.Diagnostics.Debug.WriteLine("【分割した文字列に<hoge>を挿入する】");
            StringDivideInsertText ins = new StringDivideInsertText("<hoge>");
            StringDivider divIns = new StringDivider(text, 3, ins);
            divIns.Divide();
            // 挿入された文字列を出力
            System.Diagnostics.Debug.WriteLine(ins.ResultText.ToString());

        }

        /// <summary>
        /// バイト列変換<br />
        /// </summary>
        private System.Text.Encoding SJIS_ENC = System.Text.Encoding.GetEncoding(932);

        /// <summary>
        /// 分割する文字列<br />
        /// </summary>
        private string _text;
        public string Text
        {
            get { return this._text; }
            private set { this._text = value; }
        }

        /// <summary>
        /// 分割するバイト数<br />
        /// </summary>
        private int _length;
        public int Length
        {
            get { return this._length; }
            private set { this._length = value; }
        }

        /// <summary>
        /// 文字列分割処理<br />
        /// </summary>
        private IStringDivideProcess _divideProcess;
        public IStringDivideProcess DivideProcess
        {
            get { return this._divideProcess; }
            private set { this._divideProcess = value; }
        }

        /// <summary>
        /// 分割中の文字列<br />
        /// </summary>
        private System.Text.StringBuilder _divideText = new System.Text.StringBuilder();
        public System.Text.StringBuilder DivideText
        {
            get { return this._divideText; }
        }

        /// <summary>
        /// コンストラクタ<br />
        /// </summary>
        /// <param name="text">
        /// 分割する文字列<br />
        /// </param>
        /// <param name="length">
        /// 分割するバイト数<br />
        /// </param>
        /// <param name="proc">
        /// 文字列分割処理<br />
        /// </param>
        public StringDivider(string text, int length, IStringDivideProcess proc)
        {
            this.Text = text;
            this.Length = length;
            this.DivideProcess = proc;
            this.DivideText.Clear();
        }

        /// <summary>
        /// 文字列を分割する<br />
        /// </summary>
        public void Divide()
        {
            // 1文字づつバイト数を検査
            int i = 0;
            while(i < this.Text.Length)
            {
                // 1文字ずつ抽出
                string c = this.Text.Substring(i, 1);
                // バイト数に一致するか?
                if (SJIS_ENC.GetByteCount(this.DivideText + c) == this.Length)
                {
                    // 抽出した文字を追加
                    this.DivideText.Append(c);
                    // 分割処理
                    this.DivideProcess.Process(this);
                    // 次の処理用にクリア
                    this.DivideText.Clear();
                }
                // バイト数を超えるか?
                else if (SJIS_ENC.GetByteCount(this.DivideText + c) > this.Length)
                {
                    // 分割処理
                    this.DivideProcess.Process(this);
                    // 次の処理用にクリア
                    this.DivideText.Clear();
                    // 抽出した文字を追加
                    this.DivideText.Append(c);
                }
                // バイト数未満
                else
                {
                    // 抽出した文字を追加
                    this.DivideText.Append(c);
                }
                // 次の文字の処理
                i++;
            }
            // 残りの文字列を処理
            if (this.DivideText.Length > 0)
            {
                this.DivideProcess.Process(this);
            }
        }

    }


    /// <summary>
    /// 文字列分割処理インターフェース<br />
    /// </summary>
    public interface IStringDivideProcess
    {
        /// <summary>
        /// 文字列を分割する。<br />
        /// </summary>
        /// <param name="divider">
        /// 文字列分割処理オブジェクト<br />
        /// </param>
        void Process(StringDivider divider);
    }


    /// <summary>
    /// 文字列分割処理(分割文字列のリストを作成)<br />
    /// </summary>
    public class StringDivideCreateList : IStringDivideProcess
    {

        /// <summary>
        /// 分割した文字列を格納したリスト<br />
        /// </summary>
        private System.Collections.Generic.IList<string> _list = new System.Collections.Generic.List<string>();
        public System.Collections.Generic.IList<string> List
        {
            get { return this._list; }
        }

        /// <summary>
        /// 文字列を分割する。<br />
        /// </summary>
        /// <param name="divider">
        /// 文字列分割処理オブジェクト<br />
        /// </param>
        public void Process(StringDivider divider)
        {
            this.List.Add(divider.DivideText.ToString());
        }

    }


    /// <summary>
    /// 文字列分割処理(文字列を挿入)<br />
    /// </summary>
    public class StringDivideInsertText : IStringDivideProcess
    {

        /// <summary>
        /// 挿入する文字列<br />
        /// </summary>
        private string _InsertText;
        public string InsertText
        {
            get { return this._InsertText; }
            private set { this._InsertText = value; }
        }

        /// <summary>
        /// 文字を挿入した文字列<br />
        /// </summary>
        private System.Text.StringBuilder _ResultText = new System.Text.StringBuilder();
        public System.Text.StringBuilder ResultText
        {
            get { return this._ResultText; }
        }

        /// <summary>
        /// コンストラクタ<br />
        /// </summary>
        /// <param name="insertText">
        /// 挿入する文字列<br />
        /// </param>
        public StringDivideInsertText(string insertText)
        {
            this.InsertText = insertText;
        }

        /// <summary>
        /// 文字列を分割する。<br />
        /// </summary>
        /// <param name="divider">
        /// 文字列分割処理オブジェクト<br />
        /// </param>
        public void Process(StringDivider divider)
        {
            // 分割された文字列の前に挿入(2つ目以降)
            if (this.ResultText.Length > 0)
            {
                this.ResultText.Append(this.InsertText);
            }
            // 分割された文字列を結合
            this.ResultText.Append(divider.DivideText.ToString());
        }

    }


}

処理結果(textの10文字目の0のみ全角文字)

【分割した文字列をListにする】
12345[5]
6789[4]
0abc[4]
efghi[5]
gjklm[5]
nopqr[5]
stuvw[5]
xyz[3]
【分割した文字列に<hoge>を挿入する】
123<hoge>456<hoge>789<hoge>0a<hoge>bce<hoge>fgh<hoge>igj<hoge>klm<hoge>nop<hoge>qrs<hoge>tuv<hoge>wxy<hoge>z