onsen code monkey

個人的な日記とプログラミング備忘録です

【Java】カレントディレクトリのパス等、システム設定値を取得する

System.getPropertyでシステム設定値の一覧を取得する

Properties props = System.getProperties();
props.list(System.out);

システムプロパティを指定して値を取得する
(例)カレントディレクトリのパスを取得する場合

String dir = System.getProperty("user.dir");
System.out.println( dir);

環境に応じたパスが取れるので定数でいちいち書き換えずに済む。


参考サイト様
テックノート – Javaのシステム値を取得する(System.getProperty)

自分好みのソリティアアプリを自作したい

タイムアタックや最高スコアを出すのではなく、ただ無心でソリティアをするのが好きだ。

App Store には多くのソリティアアプリが存在しているが、どれも私の理想のタイプではなく結局最もシンプルなソリティアアプリだけを毎日プレイしている。

特に不満は無いのだが、欲を言えばソリティアをクリアした時に訪れる虚しさをどうにかしたい。
せめてなにかご褒美が貰えるとか、物語が進むとか。

理想例としては、Nintendo 3DSダウンロード販売されている「ソリティ馬」というゲーム。
ソリティアの結果に応じて競馬の試合結果や馬の育成に影響が出るゲームシステムで数年前までドハマりしていた。
今は3DSを知人に譲ってしまったためプレイできない(また買えばいいだけだが...)し、なによりスマホで気軽に遊びたい。
ソリティ馬Iphoneアプリ版を以前配信していたらしいが現在は配信していない模様。

f:id:hitoto28:20190412160924j:plain

この絶対神ソリティ馬」の中毒性の再現を最終目標とし、まずは基盤となるソリティア+育成要素というテーマでIphoneアプリ開発に着手する。

【C#】シングルトンサンプル

using System;
using System.IO;
using System.IO.IsolatedStorage;
using System.Diagnostics;
using System.Collections.Generic;
using System.Threading;
using JWS.Com.Model;

namespace JWS.CWS.FW.App
{
    /// <summary>
    /// キー値クラス
    /// 内部クラス
    /// </summary>
    public class KeyValue
    {
        /// <summary>
        /// キーと値を指定してオブジェクトを生成する。
        /// </summary>
        /// <param name="key">キー</param>
        /// <param name="value"></param>
        public KeyValue(string key, string value)
        {
            this._key = key;
            this._value = value;
        }

        /// <summary>
        /// キー
        /// </summary>
        private string _key;

        /// <summary>
        /// キーを取得する。
        /// </summary>
        /// <returns>キー</returns>
        public string Getkey()
        {
            return _key;
        }

        /// <summary>
        /// 値
        /// </summary>
        private string _value;

        /// <summary>
        /// 値を取得する
        /// </summary>
        /// <returns></returns>
        public string GetValue()
        {
            return _value;
        }

        /// <summary>
        /// 文字列に変換する
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return string.Format("key = {0}, value = {1}", _key, _value);
        }
    }

    /// <summary>
    /// 環境定義ファイル
    /// </summary>
    public class EnvironmentFile
    {
        /// <summary>
        ///  環境変数
        /// </summary>
        private string _EnvFile = ComConst.stEnvDir + "\\COMENVFILE.ini";

        /// <summary>
        /// 最終更新時刻(ms)
        /// </summary>
        private DateTime _LastUpdateTime;

        /// <summary>
        /// ロック
        /// </summary>
        private ReaderWriterLock rwLock = new ReaderWriterLock();

        /// <summary>
        /// シングルトン・インスタンス
        /// </summary>
        private static EnvironmentFile _Instance;

        /// <summary>
        /// インスタンス取得
        /// </summary>
        /// <returns>シングルトン・インスタンス</returns>
        public static EnvironmentFile Instance
        {
            get
            {
                if (EnvironmentFile._Instance == null)
                {
                    EnvironmentFile instance = new EnvironmentFile();
                    instance.Init();
                    EnvironmentFile._Instance = instance;
                }
                return EnvironmentFile._Instance;
            }
        }

        /// <summary>
        /// 初期化処理
        /// </summary>
        public void Init()
        {
            try
            {
                // 環境ファイルの有無を確認
                IsolatedStorageFile storageFile = JWS.CWS.Storage.IsolatedStorage.GetUserStore();
                if (!storageFile.FileExists(_EnvFile))
                {
                    throw new IOException();
                }
                this._LastUpdateTime = storageFile.GetLastWriteTime(_EnvFile).DateTime;

                // 読み込み
                Load();

            }
            finally
            {

            }
        }

        /// <summary>
        /// データをクリアする
        /// </summary>
        public void Clear()
        {
            try
            {
                rwLock.AcquireWriterLock(Timeout.Infinite);

                if (_Items != null)
                {
                    _Items.Clear();
                }
                else
                {
                    _Items = new Dictionary<string, Dictionary<string, string>>();
                }
            }
            finally
            {
                rwLock.ReleaseWriterLock();
            }
        }

        /// <summary>
        /// ファイルの更新を確認する
        /// </summary>
        /// <returns>更新されている場合はtrue</returns>
        protected bool IsUpdate()
        {
            IsolatedStorageFile storageFile = JWS.CWS.Storage.IsolatedStorage.GetUserStore();
            if (!storageFile.FileExists(_EnvFile))
            {
                return false;
            }

            DateTime lastWriteTime = storageFile.GetLastWriteTime(_EnvFile).DateTime;
            return (this._LastUpdateTime < lastWriteTime);
        }

        /// <summary>
        /// アイテム
        /// </summary>
        protected Dictionary<string, Dictionary<string, string>> _Items;

        /// <summary>
        /// 環境作成
        /// </summary>
        protected void Load()
        {
            try
            {
                Clear();
                rwLock.AcquireWriterLock(Timeout.Infinite);

                // 分離ストレージより定義ファイルの読み出し
                using (IsolatedStorageFile file = JWS.CWS.Storage.IsolatedStorage.GetUserStore())
                {
                    // ストリーム取得
                    using (IsolatedStorageFileStream stream
                        = new IsolatedStorageFileStream(_EnvFile, FileMode.Open, file))
                    {
                        // 読み込み
                        using (StreamReader reader = new StreamReader(stream))
                        {
                            string stLine;
                            string line;
                            string section = null;
                            string currentSection = null;
                            KeyValue keyValue;
                            while ((stLine = reader.ReadLine()) != null)
                            {
                                line = stLine.Trim();
                                if (line.Length == 0)
                                {
                                    // 空行は無視
                                    continue;
                                }
                                if (IsComment(line))
                                {
                                    // コメント行は無視
                                    continue;
                                }
                                // セクション解析
                                section = ParseSection(line);
                                if (section != null)
                                {
                                    // セクションを更新
                                    currentSection = section;
                                    continue;
                                }
                                // キー解析
                                keyValue = ParseKeyValue(line);
                                if (keyValue != null)
                                {
                                    AddItem(currentSection, keyValue);
                                }
                            }
                        }
                    }
                    this._LastUpdateTime = file.GetLastWriteTime(_EnvFile).DateTime;
                }
            }
            finally
            {
                rwLock.ReleaseWriterLock();
            }
        }

        /// <summary>
        /// コメント判定
        /// </summary>
        /// <param name="line"></param>
        /// <returns>コメントであればtrue</returns>
        protected bool IsComment(string line)
        {
            bool result = false;
            if (line.StartsWith("#") || line.StartsWith("\\"))
            {
                result = true;
            }
            return result;
        }

        /// <summary>
        /// セクション解析
        /// </summary>
        /// <param name="line"></param>
        /// <returns>セクション</returns>
        protected string ParseSection(string line)
        {
            string section = null;
            if (line.Length > 2 && line.StartsWith("[") && line.EndsWith("]"))
            {
                section = line.Substring(1, line.Length - 2);
            }
            return section;
        }

        /// <summary>
        /// キー値解析
        /// </summary>
        /// <param name="line"></param>
        /// <returns>KeyValue</returns>
        protected KeyValue ParseKeyValue(string line)
        {
            int index = line.IndexOf("=");
            KeyValue result = null;
            if (index >= 0)
            {
                string key = line.Substring(0, index);
                string value = line.Substring(index + 1);
                if (key != null)
                {
                    result = new KeyValue(key, value);
                }
            }
            return result;
        }

        /// <summary>
        /// アイテムを追加する
        /// </summary>
        /// <param name="section">セクション</param>
        /// <param name="keyvalue">KeyValue</param>
        protected void AddItem(string section, KeyValue item)
        {
            try
            {
                rwLock.AcquireWriterLock(Timeout.Infinite);
                if (section == null)
                {
                    section = "";
                }
                Dictionary<string, string> keyValues = null;
                if (!this._Items.TryGetValue(section, out keyValues))
                {
                    keyValues = new Dictionary<string, string>();
                    keyValues.Add(item.Getkey().Trim(), item.GetValue().Trim());

                    this._Items.Add(section, keyValues);
                }
                keyValues[item.Getkey().Trim()] = item.GetValue().Trim();
            }
            finally
            {
                rwLock.ReleaseWriterLock();
            }
        }

        /// <summary>
        /// 環境設定ファイルの更新を確認する
        /// </summary>
        protected void ConfirmUpdate()
        {
            if (IsUpdate())
            {
                Load();
            }
        }

        /// <summary>
        /// プロパティを string 型で取得する
        /// </summary>
        /// <param name="section">セクション</param>
        /// <param name="key">キー</param>
        /// <param name="defaultValue">デフォルト値</param>
        /// <returns>プロパティを返却する。設定がない場合は、デフォルト値を返却する。</returns>
        public string GetString(string section, string key, string defaultValue)
        {
            try
            {
                ConfirmUpdate();
                rwLock.AcquireReaderLock(Timeout.Infinite);
                string value = defaultValue;
                do
                {
                    if (_Items == null)
                    {
                        break;
                    }
                    Dictionary<string, string> keyValues = null;
                    if (!this._Items.TryGetValue(section, out keyValues))
                    {
                        break;
                    }

                    if (keyValues.ContainsKey(key))
                    {
                        value = keyValues[key];
                    }
                } while (false); // 1回のみループ
                return value;
            }
            finally
            {
                rwLock.ReleaseReaderLock();
            }
        }

        public string GetString(string section, string key)
        {
            return GetString(section, key, null);
        }

        /// <summary>
        /// プロパティを int 型で取得する
        /// </summary>
        /// <param name="section">セクション</param>
        /// <param name="key">キー</param>
        /// <param name="defaultValue">デフォルト値</param>
        /// <returns>プロパティを返却する。設定がない場合は、デフォルト値を返却する。</returns>
        public Nullable<int> GetInt(string section, string key, Nullable<int> defaultValue)
        {
            try
            {
                Nullable<int> value = null;
                string valueString = GetString(section, key, null);
                if (valueString == null)
                {
                    value = defaultValue;
                }
                else
                {
                    value = int.Parse(valueString);
                }
                return value;
            }
            catch (FormatException)
            {
                return defaultValue;
            }
            finally
            {

            }
        }

        public Nullable<int> GetInt(string section, string key)
        {
            return GetInt(section, key, null);
        }

        /// <summary>
        /// プロパティを bool 型で取得する
        /// </summary>
        /// <param name="section">セクション</param>
        /// <param name="key">キー</param>
        /// <param name="defaultValue">デフォルト値</param>
        /// <returns>プロパティを返却する。設定がない場合は、デフォルト値を返却する。</returns>
        public Nullable<bool> GetBoolean(string section, string key, Nullable<bool> defaultValue)
        {
            try
            {
                Nullable<bool> value = null;
                string valueString = GetString(section, key, null);
                if (valueString == null)
                {
                    return defaultValue;
                }
                valueString = valueString.ToLower();
                if ("true".Equals(valueString))
                {
                    value = true;
                }
                else if ("false".Equals(valueString) || "0".Equals(valueString))
                {
                    value = false;
                }
                else
                {
                    if (int.Parse(valueString) > 0)
                    {
                        value = true;
                    }
                    else
                    {
                        value = defaultValue;
                    }
                }
                return value;
            }
            catch (FormatException)
            {
                return defaultValue;
            }
            finally
            {

            }
        }

        public Nullable<bool> GetBoolean(string section, string key)
        {
            return GetBoolean(section, key, null);
        }

        /// <summary>
        /// プロパティを long 型で取得する
        /// </summary>
        /// <param name="section">セクション</param>
        /// <param name="key">キー</param>
        /// <param name="defaultValue">デフォルト値</param>
        /// <returns>プロパティを返却する。設定がない場合は、デフォルト値を返却する。</returns>
        public Nullable<long> GetLong(string section, string key, Nullable<long> defaultValue)
        {
            try
            {
                Nullable<long> value = null;
                string valueString = GetString(section, key, null);
                if (valueString == null)
                {
                    value = defaultValue;
                }
                else
                {
                    value = long.Parse(valueString);
                }
                return value;
            }
            catch (FormatException)
            {
                return defaultValue;
            }
            finally
            {

            }
        }

        public Nullable<long> GetLong(string section, string key)
        {
            return GetLong(section, key, null);
        }

        /// <summary>
        /// プロパティを float 型で取得する
        /// </summary>
        /// <param name="section">セクション</param>
        /// <param name="key">キー</param>
        /// <param name="defaultValue">デフォルト値</param>
        /// <returns>プロパティを返却する。設定がない場合は、デフォルト値を返却する。</returns>
        public Nullable<float> GetFloat(string section, string key, Nullable<float> defaultValue)
        {
            try
            {
                Nullable<float> value = null;
                String valueString = GetString(section, key, null);
                if (valueString == null)
                {
                    value = defaultValue;
                }
                else
                {
                    value = float.Parse(valueString);
                }
                return value;
            }
            catch (FormatException)
            {
                return defaultValue;
            }
            finally
            {

            }
        }

        public Nullable<float> GetFloat(string section, string key)
        {
            return GetFloat(section, key, null);
        }

        /// <summary>
        /// プロパティを double 型で取得する
        /// </summary>
        /// <param name="section">セクション</param>
        /// <param name="key">キー</param>
        /// <param name="defaultValue">デフォルト値</param>
        /// <returns>プロパティを返却する。設定がない場合は、デフォルト値を返却する。</returns>
        public Nullable<double> GetDouble(string section, string key, Nullable<double> defaultValue)
        {
            try
            {
                Nullable<double> value = null;
                string valueString = GetString(section, key, null);
                if (valueString == null)
                {
                    value = defaultValue;
                }
                else
                {
                    value = double.Parse(valueString);
                }
                return value;
            }
            catch (FormatException)
            {
                return defaultValue;
            }
            finally
            {

            }
        }

        public Nullable<double> GetDouble(string section, string key)
        {
            return GetDouble(section, key, null);
        }
    }
}

【Java】try-with-resourcesを使ってファイルの読み書き

try-with-resourcesを使えばいちいちCloseやDisposeしなくてもリソースを自動で解放してくれる

C#のusing的なやつ

条件
・JavaSE7以降
・クラスがAutoCloseableインターフェースおよびCloseableインターフェースを実装していること

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class TryWithResources {
    public static void main(String[] args) {

        String inFilePath = "D:\\A.txt";
        String outFilePath = "D:\\C.txt";

        try (FileInputStream in = new FileInputStream(inFilePath);
                FileOutputStream out = new FileOutputStream(outFilePath);) {
            int c;

            // データをコピーする
            while ((c = in.read()) != -1) {
                out.write(c);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

参考サイト様
try-with-resources文の基本 - Qiita

【C#】分離ストレージにXMLファイルを作成する

昔書いたプログラム漁ってたら何かに使えそうなものが出てきたので記録しておく。
Button1で分離ストレージにXMLファイルを作成し、Button2でそれを読み込んだ後消している模様。
System.Xml.Linqを使っている。

using System;
using System.IO;
using System.IO.IsolatedStorage;
using System.Windows;
using System.Xml.Linq;

namespace XMLtoISF
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        string fileName = "";

        private void Button1_Click(object sender, RoutedEventArgs e)
        {
            Guid g = System.Guid.NewGuid();
            fileName = g.ToString("N").Substring(0, 8) + ".xml";
            double val = 0.01;
            string str = val.ToString();

            XDocument xml = new XDocument(
            new XDeclaration("1.0", "utf-8", "yes"),
            new XElement("Employee",
            new XElement("FirstName", "田中"),
            new XElement("LastName", "太郎"),
            new XElement("ID", "999")
            ));

            using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForAssembly())
            {
                using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(fileName, FileMode.CreateNew, isf))
                {
                    xml.Save(stream);
                }
            }
        }
        private void Button2_Click(object sender, RoutedEventArgs e)
        {
            XDocument xdoc = null;
            
            using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForAssembly())
            {
                if (isf.FileExists(fileName))
                {
                    using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(fileName, FileMode.Open, isf))
                    {
                        xdoc = XDocument.Load(stream);
                    }

                    Console.WriteLine(xdoc.Element("Employee").Element("FirstName").Value);
                    Console.WriteLine(xdoc.Element("Employee").Element("ID").Value);
                }
                isf.DeleteFile(fileName);
            }
        }
    }
}

【Java】ループの中で+を使用して文字列を連結してはいけない

ループの中で+を使用して文字列を連結するとループの度にStringを生成するので回数が増えるほどOutOfMemoryしたり処理が遅くなる可能性が高くなる。

public static void main(String[] args) {
    String hoge = "";
    for (int i=0; i<10; i++) {
        hoge += "(^q^)";
    }
    System.out.println(hoge);
}

以下のようにStringBuilderを使えば問題なし。

public static void main(String[] args) {
    StringBuilder hoge = new StringBuilder();
    for (int i=0; i<10; i++) {
        hoge.append("(^q^)");
    }
    System.out.println(hoge.toString());
}

C#でも同じだった気がする。
でもJavaScriptでは+=で連結したほうが速い。というかStringBuilder的なものがないっぽい。

転職した

ITベンチャーに転職した。
転職や引っ越しのドタバタとストレスでブログや開発がまったくできなかった(いいわけ)

本当はエンジニアらしく退職エントリを書こうとしていたけど、どうしてもネガティブな内容になってしまうのでやめた。
お世話になった上司・同僚にはただただ感謝しかない。

転職先のベンチャーでは20~30代の若手が多く非常に活気があり、会社も人材も成長する予感しかしない。
でもいまだに浮いてる。

転職して良かったことのほうが圧倒的に多いけどコミュ障にとって新しいコミュニティに溶け込む過程は非常につらい。
なんとか馴染めるよう頑張ろう。