stackoverflow 日本語版(ベータ)が公開されました!

プログラマーのためのQ&Aサイト「stackoverflow」日本語版がついに公開されました。

まだベータ版ではありますが、既に300を超える質問が登録されています。


スタック・オーバーフロー

ただやはり日本語圏のエンジニアは英語圏のエンジニアより数が相当少ないはずなので、将来的にも英語版ほどの情報量にはならないと思います。

なので個人的には英語版のQ&Aを翻訳して日本語版に表示してくれる機能を希望します!

VMware vSphere について勉強中

VMware vSphere について勉強中です。

下記の本を読んでいます。

 

1冊目、VMware 徹底入門

VMware徹底入門 第3版 VMware vSphere 5.1対応

VMware徹底入門 第3版 VMware vSphere 5.1対応

 

 VMware 社が出版している本です。

やはり公式で出版されているだけあって分かりやすいですし、広範囲の情報が網羅されているため、VMware 初心者の方は一度目を通しておくことをおすすめします。

 

2冊目、VMware vSphereクラスタ構築/運用の技法

VMware vSphereクラスタ構築/運用の技法

VMware vSphereクラスタ構築/運用の技法

  • 作者: Duncan Epping,Frank Denneman,ダンカン・エッピング,フランク・デンネマン,小川大地,後藤僚哉,清水亮夫,三田泰正
  • 出版社/メーカー: 翔泳社
  • 発売日: 2013/07/24
  • メディア: 大型本
  • この商品を含むブログ (3件) を見る
 

VMware 全体の技術についてではなく、vSphere HA、DRS、Storage DRS に特化して解説されています。

これは、初心者向けではなく、中級者以上向けです。

一応各用語については説明がありますが、わかりやすいとは言えません。

私も理解できない部分が多々あります。

ただその代わり、各技術について、かなり詳細に挙動の説明までされています。

個人的には vSphere HA のリトライの仕組みが勉強になりました。

著者のダンカンさんは VMware 関係者の中ではかなりの有名人みたいです。

 

最後3冊目、 Mastering VMware vSphere 5.5

Mastering VMware vSphere 5.5

Mastering VMware vSphere 5.5

 

 分量が多くてあまり読めていませんが、これ1冊読めば十分な知識を得られそうです。ただ、VMware vSphereクラスタ構築/運用の技法 ほど詳細な説明はなさそうですので、vSphere HA などについてより勉強したい場合は別途購入した方がよさそうです。

Stack Overflow の日本語版が開設されるらしいです

私もよくお世話になっているエンジニアのためのQ&Aサイト「Stack Overflow」の

日本語版が開設に向けて動き出しているそうです。

http://www.publickey1.jp/blog/14/stack_overflow.html

 

たしかに Stack Overflow の日本語版ができてくれると嬉しいですが、

やはり日本語圏の人口からすると情報量は限られそうですね。

Stack Overflow の真の価値はその情報量だと思うので、日本語版の

情報量が増えることに期待します。

日本はどうしても情報が少ない&遅いですしね。

 

私も是非 Stack Overflow で貢献したいので、もっと知識を蓄えないと!

MSDNフォーラムで回答者として活動していたのを

 数か月でやめてしまった過去があるとは言えない)

 

エンべデッドシステムスペシャリストのおすすめ書籍

平成26年度のエンべデッドシステムスペシャリストに合格しました!

 

結果

午前Ⅱ 72点

午後Ⅰ 60点

午後Ⅱ 81点

 

...午後Ⅰは見なかったことにしましょう

こんな有様なので、組込みの何たるかをお話しすることはできませんが、

おすすめの書籍をご紹介します。

 

お勧め度:高

1.組込みシステムのハードウェア設計入門講座(電波新聞社

 私のような組込み未経験者は必須です。

 この試験のために書かれたのではないかと思うほど試験範囲を網羅しています。

 そして何よりわかりやすい!

 

2.エンべデッドシステムスペシャリスト 徹底解説本試験問題(iTEC)

 やはり対策は過去問です。

 解説がひととおり揃うよう、最新のものと過去3~4年前に発売されたものを

 購入することをおすすめします。

2014 徹底解説エンベデッドシステムスペシャリスト本試験問題 (本試験問題シリーズ)

2014 徹底解説エンベデッドシステムスペシャリスト本試験問題 (本試験問題シリーズ)

 

 

お勧め度:中

1.情報処理教科書エンべデッドシステムスペシャリスト(翔泳社

  教科書なので買っておいて損はありませんが、この分野の経験がないと

 理解するのが難しいとおもいます。

2.徹底図解パソコンのしくみ(新星出版社)

 ハードウェアの知識をつけるために購入しました。

 初心者向けですが、ここまで図解されている書籍は少ないのでおすすめです。

3.徹底図解パソコンが動くしくみ(新星出版社)

 同上

4.TAC通信教育

 DBやSCなら是非受講するのをお勧めしますが、ESはやっておいた方が良いくらいです。

 ただ模試は受験するのをお勧めします。

 

お勧め度:低

1.エンべデッドシステムスペシャリスト「専門知識+午後問題」の重点対策(iTEC)

 過去問中心なので、本試験問題があればOKだと思います。

2.プロセッサを支える技術(技術評論社

 CPU、メモリの挙動について非常に勉強になる本です。

 そもそも当試験の対策本ではないので、興味がある方は読んでみてください。

 

今後受験される方のご参考になればと思います。

 

 

 

文字化けの仕組み

前回のブログで作成したツールを作成して、文字化けの仕組みについて書いてみようと思います。

 

なぜ文字化けが起こるか端的に言いますと、ファイルに書き込んだ文字エンコードとファイルを読み込んだ文字エンコードが異なるからです。

 

文字コードとは?

 パソコンのディスクに保存されるあらゆるファイルは、バイナリ(2進数)で保存されています。テキストファイルも同様にバイナリのファイルとして保存されています。

そこで、保存されているバイナリの値を何の文字と対応させるかを決める必要があります。あるバイナリの値と、文字の対応を決めたものが文字エンコードです。

 

文章だけでは分かりづらいので、下図を見てください。

これは、保存したテキストファイルをShift_JISという文字エンコードで読み込んだ状態です。

1行目には「ABCDEFGHIJKLMN」という文字列が表示されています。

これがディスク上には「4142434445464748494A4B4C4E」(16進数)という値で保存されているのです。

f:id:azumal:20140426172657j:plain

次の図には「Hello World!」という文字列が表示されています。こちらは「48454C4C4F20574F524C4421」という値で保存されているのがわかります。

f:id:azumal:20140426173037j:plain

次の図には「こんにちは 世界!」という文字列が表示されています。

f:id:azumal:20140426173416j:plain

Shift_JIS では全角の日本語を2バイトで表します。

ですので、

「こ」→「82B1」

「ん」→「82F1」

「に」→「82C9」

「ち」→「82BF」

「は」→「82CD」

「 」→「8140」

「世」→「90A2」

「界」→「8A45」

「!」→「8149」

となります。

次の図はすべて文字化けしています。

これはなぜかと言いますと、このファイルはもともと「UTF-8」という文字エンコードで保存したためです。

f:id:azumal:20140426174210j:plain

UTF-8 で読み込むと正しく表示されます。

f:id:azumal:20140426174555j:plain

UTF-8 では

(※最初の「EFBBBF」は文字として認識されない特殊なバイナリです。)

「こ」→「E38193」

「ん」→「E38293」

「に」→「E381AB」

「ち」→「E381A1」

「は」→「E381AF」

「 」→「E38080」

「世」→「E4B896」

「界」→「E7958C」

「!」→「EFBC81」

となります。

 

同じ文章を保存してもエンコードが変わるとバイナリも変わってしまいます。

読み込み時に指定するエンコードを誤ると正しく文字にマッピングできません。これが文字化けの仕組みです。

 

ちなみに、4番目の図で文字化けしている「・ソ縺薙s縺縺。縺縲荳也阜・」という文字列は Shift_JIS で、

「EFBB」→「・(該当なし)」
「BF」    →「ソ」
「E381」→「縺」
「93E3」→「薙」
「8293」→「s」
「E381」→「縺」
「AB」    →「オ」
「E381」→「縺」
「A1」    →「。」
「E381」→「縺」
「AF」    →「ツ」
「E380」→「縲」
「80」     → 無視?
「E4B8」→「荳」
「96E7」→「也」
「958C」→「阜」
「EFBC81」→「・(該当なし)」

という文字にマッピングされるため、上記のように表示されます。

WPFで文字化け調査ツールを作成

文字化けしたテキストファイルなんかをすぐにバイナリで見れるツールが欲しいと思ったので、作ってみました。

といっても、ただ単に指定した文字エンコードでファイルを読んで表示し、隣にバイナリを表示しているだけです。(役に立つのかな?)

イメージ

f:id:azumal:20140425230739j:plain

MainWindow.xaml

 <Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="768" Width="1024">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<TextBox x:Name="FileTextBox" Width="450" Height="30" HorizontalAlignment="Left" Margin="10" Text="{Binding FilePath}"/>
<Button x:Name="OpenFileButton" Width="50" Height="30" HorizontalAlignment="Left" Margin="480 0 0 0" Content="参照" Command="{Binding OpenFileCommand}"/>
<ComboBox x:Name="EncodingComboBox" Width="200" Height="30" HorizontalAlignment="Right" Margin="0 0 100 0"
ItemsSource="{Binding EncodingList}" SelectedValue="{Binding FileEncoding}"
DisplayMemberPath="EncodingName"/>
<Button x:Name="ExecuteButton" Width="50" Height="30" Content="実行" HorizontalAlignment="Right" Margin="10" Command="{Binding ReadFileCommand}"
CommandParameter="{Binding ElementName=FileTextBox, Path=Text}"/>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="5"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<ListView x:Name="TextListView" ItemsSource="{Binding Text}" >
</ListView>
<GridSplitter x:Name="Splitter" Grid.Column="1" HorizontalAlignment="Stretch"/>
<ListView x:Name="HexTextListView" Grid.Column="2" ItemsSource="{Binding HexText}">
</ListView>
</Grid>
</Grid>
</Window>

MainWindow.xaml.cs

using System.Windows;
namespace WpfApplication1 {
    /// <summary>
    /// MainWindow.xaml の相互作用ロジック
    /// </summary>
    public partial class MainWindow : Window {
        public MainWindow() {
            InitializeComponent();
            this.DataContext = new MainWindowViewModel();
        }
    }
}

MainWindowViewModel.cs

using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using Microsoft.Win32;

namespace WpfApplication1 {
    public class MainWindowViewModel : INotifyPropertyChanged {
        public MainWindowViewModel() {
            OpenFileCommand = new RelayCommand(OpenFile);
            ReadFileCommand = new RelayCommand(ReadFile);
            EncodingList.Add(Encoding.ASCII);
            EncodingList.Add(Encoding.GetEncoding("Shift_JIS"));
            EncodingList.Add(Encoding.UTF8);
            EncodingList.Add(Encoding.Unicode);
            EncodingList.Add(Encoding.BigEndianUnicode);
            FileEncoding = EncodingList.First();
        }

        private string _filePath;
        public string FilePath {
            get { return _filePath; }
            set {
                if (_filePath == value)
                    return;
                _filePath = value;
                RaisePropertyChanged("FilePath");
            }
        }

        private ObservableCollection<string> _text = new ObservableCollection<string>();
        public ObservableCollection<string> Text {
            get { return _text; }
            set {
                if (_text == value)
                    return;
                _text = value;
                RaisePropertyChanged("Text");
            }
        }

        private ObservableCollection<string> _hexText = new ObservableCollection<string>();
        public ObservableCollection<string> HexText {
            get { return _hexText; }
            set {
                if (_hexText == value)
                    return;
                _hexText = value;
                RaisePropertyChanged("HexText");
            }
        }

        private Encoding _fileEncoding;
        public Encoding FileEncoding {
            get { return _fileEncoding; }
            set {
                if (_fileEncoding == value)
                    return;
                _fileEncoding = value;
                RaisePropertyChanged("FileEncoding");
            }
        }

        private ObservableCollection<Encoding> _encodingList = new ObservableCollection<Encoding>();
        public ObservableCollection<Encoding> EncodingList {
            get { return _encodingList; }
            set {
                if (_encodingList == value)
                    return;
                _encodingList = value;
                RaisePropertyChanged("EncodingList");
            }
        }

        public ICommand ReadFileCommand { get; set; }
        public ICommand OpenFileCommand { get; set; }

        private void ReadFile(object parameter) {
            string fileName = parameter.ToString();
            if (!File.Exists(fileName))
                return;
            Task.Factory.StartNew(() => {
                Text = GetPlainText(fileName);
            });

            Task.Factory.StartNew(() => {
                HexText = GetHexText(fileName);
            });
        }

        private ObservableCollection<string> GetPlainText(string fileName) {
            var oc = new ObservableCollection<string>();
            using (var sr = new StreamReader(fileName, FileEncoding, false)) {
                string line;
                while ((line = sr.ReadLine()) != null) {
                    oc.Add(line);
                }
            }
            return oc;
        }

        private ObservableCollection<string> GetHexText(string fileName) {
            var oc = new ObservableCollection<string>();
            var sb = new StringBuilder();
            using (var fs = new FileStream(fileName, FileMode.Open)) {
                int i = 0;
                int sc = 0;
                var b = FileEncoding.GetBytes(Environment.NewLine);
                while ((i = fs.ReadByte()) > -1) {
                    if (i == (int)b[sc])
                        sc++;
                    sb.Append(i.ToString("X2") + " ");
                    if (sc >= b.Length) {
                        oc.Add(sb.ToString());
                        sb.Clear();
                        sc = 0;
                    }
                }
                if (sb.Length > 0)
                    oc.Add(sb.ToString());
            }
            return oc;
        }

        private void OpenFile(object parameter) {
            var ofd = new OpenFileDialog();
            if (ofd.ShowDialog() == true)
                FilePath = ofd.FileName;
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void RaisePropertyChanged(string propertyName) {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

ICommandインターフェイスの実装を簡略化する

前回私のブログ(http://azumal.hatenablog.com/entry/2014/04/13/105502)で MVVM のサンプルプログラムを公開しました。

サンプルの中で ICommand インターフェイスを実装したクラスを定義していましたが、下記の記事を読んで、もっと簡単に実装できることがわかりました。

 

「Model-View-ViewModel デザイン パターンによる WPF アプリケーション」

http://msdn.microsoft.com/ja-jp/magazine/dd419663.aspx#id0090030

 

上記記事で紹介されている RelayCommand クラスを利用することで、

コマンドの定義を簡略化することができます。

 

「MainWindowViewModel」クラス(RelayCommand での実装)

public class MainWindowViewModel {
        public Person RegisteredPerson { get; set; }
        public ObservableCollection<Person> People { get; set; }
        public ICommand RegisterPersonCommand { get; set; }
        public ICommand CancelCommand { get; set; }
        public List<Sexes> Roles { get; set; }

        public MainWindowViewModel() {
            People = new ObservableCollection<Person>();
            RegisteredPerson = new Person();
            RegisterPersonCommand = new RelayCommand(param => this.RegisterPerson(param));
            CancelCommand = new RelayCommand(param => this.Cancel(param));
        }

        public void RegisterPerson(object parameter) {
            var p = (Person)parameter;
            People.Add(new Person(p.PersonID, p.FirstName, p.LastName, p.Sex, p.BirthDay));
            RegisteredPerson.PersonID++;
            RegisteredPerson.FirstName = string.Empty;
            RegisteredPerson.LastName = string.Empty;
            RegisteredPerson.Sex = Sexes.男性;
            RegisteredPerson.BirthDay = DateTime.Today;
        }

        public void Cancel(object parameter) {
            var p = (Person)parameter;
            p.PersonID = People.Max<Person>(u => u.PersonID) + 1;
            p.FirstName = string.Empty;
            p.LastName = string.Empty;
            p.Sex = Sexes.男性;
            p.BirthDay = DateTime.Today;
        }
    }

「MainWindowViewModel」クラス(前回ブログより ICommand での実装)

public class MainWindowViewModel {
        public Person RegisteredPerson { get; set; }
        public ObservableCollection<Person> People { get; set; }
        public ICommand RegisterPersonCommand { get; set; }
        public ICommand CancelCommand { get; set; }
        public List<Sexes> Roles { get; set; }

        public MainWindowViewModel() {
            People = new ObservableCollection<Person>();
            RegisteredPerson = new Person();
            RegisterPersonCommand = new RegisterPerson(this);
            CancelCommand = new Cancel(this);
        }
    }

    public class RegisterPerson : ICommand {
        private ObservableCollection<Person> _people;
        private Person _person;
        public RegisterPerson(MainWindowViewModel view) {
            _people = view.People;
            _person = view.RegisteredPerson;
        }

        public event EventHandler CanExecuteChanged;
        public bool CanExecute(object parameter) {
            return true;
        }

        public void Execute(object parameter) {
            var p = (Person)parameter;
            _people.Add(new Person(p.PersonID, p.FirstName, p.LastName, p.Sex, p.BirthDay));
            _person.PersonID++;
            _person.FirstName = string.Empty;
            _person.LastName = string.Empty;
            _person.Sex = Sexes.男性;
            _person.BirthDay = DateTime.Today;
        }
    }

    public class Cancel : ICommand {
        private ObservableCollection<Person> _people;
        public Cancel(MainWindowViewModel view) {
            _people = view.People;
        }

        public event EventHandler CanExecuteChanged;
        public bool CanExecute(object parameter) {
            return true;
        }

        public void Execute(object parameter) {
            var p = (Person)parameter;
            p.PersonID = _people.Max<Person>(u => u.PersonID) + 1;
            p.FirstName = string.Empty;
            p.LastName = string.Empty;
            p.Sex = Sexes.男性;
            p.BirthDay = DateTime.Today;
        }
    }

 いかがでしょうか。

RelayCommand クラスを定義しておくだけで、コマンドのために実装するコード量が削減されたと共に、MainWindowViewModel クラスにコマンドの実装が内包されています。MSDN マガジンに感謝です!