星期五, 12月 30, 2016

[DP] 裝飾者模式

寫個簡易範例來幫助了解裝飾者模式
Drink Class 相關
namespace Beverage
{
    public abstract class Drink
    {
        protected string DrinkName = string.Empty;
        protected decimal DrinkPrice = 0.0m;

        public virtual string GetDrinkName()
        {
            return DrinkName;
        }
        
        public abstract string GetDescript();
        public abstract decimal GetPrice();
    }

    public class GreeTea : Drink
    {
        public GreeTea()
        {
            this.DrinkName = "綠茶";
            this.DrinkPrice = 15m;
        }

        public override string GetDrinkName()
        {
            return DrinkName;
        }

        public override string GetDescript()
        {
            return $"{DrinkName} ( {DrinkPrice} )";
        }

        public override decimal GetPrice()
        {
            return DrinkPrice;
        }
    }
}
Decorator Class 相關
namespace Beverage
{
    public abstract class Decorator : Drink
    {
        protected Drink drink;
        protected string DecoratorName = string.Empty;
        protected decimal DecoratorPrice = 0.0m;

        public Decorator(Drink drink)
        {
            this.drink = drink;
        }

        public override string GetDrinkName()
        {
            return drink.GetDrinkName();
        }

        public override string GetDescript()
        {
            return drink.GetDescript() + $", {DecoratorName} ( {DecoratorPrice} )";
        }

        public override decimal GetPrice()
        {
            return drink.GetPrice() + DecoratorPrice;
        }
    }

    public class Bubble : Decorator
    {
        public Bubble(Drink drink) : base(drink)
        {
            this.DecoratorName = "珍珠";
            this.DecoratorPrice = 10m;
        }
    }

    public class Milk : Decorator
    {
        public Milk(Drink drink) : base(drink)
        {
            this.DecoratorName = "牛奶";
            this.DecoratorPrice = 21m;
        }
    }

    public class Yakult : Decorator
    {
        public Yakult(Drink drink) : base(drink)
        {
            this.DecoratorName = "養樂多";
            this.DecoratorPrice = 10m;
        }

        public override string GetDrinkName()
        {
            return $"{DecoratorName} - {drink.GetDrinkName()}";
        }
    }
}
執行
namespace Beverage
{
    class Program
    {
        static void Main(string[] args)
        {
            Drink d1 = new GreeTea();
            d1 = new Bubble(d1);
            d1 = new Yakult(d1);
            ShowData(d1);
        }

        private static void ShowData(Drink d)
        {
            Console.WriteLine($"品名:{d.GetDrinkName()}");
            Console.WriteLine($"價格:{d.GetPrice()}");
            Console.WriteLine($"說明:{d.GetDescript()}");
        }

    }
}
結果

星期五, 12月 23, 2016

[C#] 利用 DES 加解密

利用 DES 來加解密 txt 檔案,藉此了解檔案加解密是如何進行的

using System.IO;
using System.Security.Cryptography;

namespace DESPractice
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private string Dir = @"D:\CryptographyTemp";
        private string Content = string.Empty;
        private string DefaultTxtName = "Source.txt";

        private void Form1_Load(object sender, EventArgs e)
        {
            // 預設檔案路徑
            txtSourceFile.Text = Path.Combine(Dir, DefaultTxtName);
            txtEncryptSourceFile.Text = Path.Combine(Dir, "加密", DefaultTxtName);
            txtDecryptFile.Text = Path.Combine(new string[] { Dir, "解密", DefaultTxtName });

            // DESCrypto 所需的 Key 和 IV
            txtKey.Text = "12345678";
            txtIV.Text = "12345678";

            // 選擇來源檔案時,會一併建立 txt 測試檔案,此為 txt 檔案內容
            Content += "參考資料                                " + Environment.NewLine;
            Content += "* Encoding 類別                       " + Environment.NewLine;
            Content += "* ASCIIEncoding 類別                  " + Environment.NewLine;
            Content += "* Convert.ToBase64String 方法 (Byte[])" + Environment.NewLine;
            Content += "* StreamReader.ReadToEnd 方法()       " + Environment.NewLine;
            Content += "* Stream.CopyTo 方法                  " + Environment.NewLine;
            Content += "* 如何使用 Visual C# 加密和解密檔案     " + Environment.NewLine;

            btnSourceFile.Click += BtnClick;
            btnEncryptSourceFile.Click += BtnClick;
            btnDecryptFile.Click += BtnClick;
        }

        private void BtnClick(object sender, EventArgs e)
        {
            SaveFileDialog fd = new SaveFileDialog();
            fd.Filter = "(*.txt) | *.txt | All files(*.*) | *.*";
            fd.InitialDirectory = @"D:\CryptographyTemp";
            if (fd.ShowDialog() != DialogResult.OK) return;

            Button btn = sender as Button;
            string btnName = btn.Name;
            switch (btnName)
            {
                case "btnSourceFile":
                    txtSourceFile.Text = fd.FileName;
                    // 利用 File.WriteAllText() 把資料寫進去 txt 檔案
                    File.WriteAllText(fd.FileName, Content, Encoding.Default);
                    break;
                case "btnEncryptSourceFile":
                    txtEncryptSourceFile.Text = fd.FileName;
                    break;
                case "btnDecryptFile":
                    txtDecryptFile.Text = fd.FileName;
                    break;
                default:
                    break;
            }
        }

        private Tuple<byte[], byte[]> KeyIV(string key, string iv)
        {
            return new Tuple<byte[], byte[]>
                (
                    Encoding.ASCII.GetBytes(key),
                    Encoding.ASCII.GetBytes(iv)
                );
        }

        private void btnRunEncrypt_Click(object sender, EventArgs e)
        {
            DESCryptoServiceProvider des =
                new DESCryptoServiceProvider();

            Tuple<byte[], byte[]> result = KeyIV(txtKey.Text.Trim(), txtIV.Text.Trim());
            byte[] key = result.Item1;
            byte[] iv = result.Item2;

            // 來源檔案
            using (FileStream fsSource = new FileStream(
                  txtSourceFile.Text.Trim(),
                  FileMode.Open,
                  FileAccess.Read))
            // 加密檔案
            using (FileStream fsEncrypt = new FileStream(
                txtEncryptSourceFile.Text.Trim(),
                FileMode.Create,
                FileAccess.Write))
            // 進行加密
            using (CryptoStream cs = new CryptoStream(
               fsEncrypt,
               des.CreateEncryptor(key, iv),
               CryptoStreamMode.Write))
            {
                // CopyTo 是從 Stream 現在 Position 讀取到尾,避免 Position 不是在頭,要先設 Position = 0
                fsSource.Position = 0;
                fsSource.CopyTo(cs);
            }

            ReadTextFile();
        }

        private void btnRunDecrypt_Click(object sender, EventArgs e)
        {
            DESCryptoServiceProvider des =
                new DESCryptoServiceProvider();

            Tuple<byte[], byte[]> result = KeyIV(txtKey.Text.Trim(), txtIV.Text.Trim());
            byte[] key = result.Item1;
            byte[] iv = result.Item2;

            // 已加密檔案
            using (FileStream fsDecrypt = new FileStream(
                txtEncryptSourceFile.Text.Trim(),
                FileMode.Open,
                FileAccess.Read))
            // 進行解密
            using (CryptoStream cs = new CryptoStream(
                 fsDecrypt,
                 des.CreateDecryptor(key, iv),
                 CryptoStreamMode.Read))
            // 把解密後資料讀出來
            using (StreamReader sr = new StreamReader(cs, Encoding.Default))
            // 把解密後資料送進 txt 檔案內
            using (StreamWriter sw = new StreamWriter(txtDecryptFile.Text.Trim(), false, Encoding.Default))
            {
                string Content = sr.ReadToEnd();
                // 利用 StreamWriter() 把資料寫進檔案內,要把 Stream 關閉,資料才會寫進檔案內喔
                sw.Write(Content);
            }

            ReadTextFile();
        }

        private void ReadTextFile()
        {
            // 把資料送進 txtSource、txtEncrypt、txtDecrypt
            string Source = txtSourceFile.Text.Trim();
            if (File.Exists(Source))
            {
                using (StreamReader srSource = new StreamReader(Source, Encoding.Default))
                {
                    txtSource.Text = srSource.ReadToEnd();
                }
            }

            string Encrypt = txtEncryptSourceFile.Text.Trim();
            if (File.Exists(Encrypt))
            {
                using (StreamReader srEncrypt = new StreamReader(Encrypt, Encoding.Default))
                {
                    txtEncrypt.Text = srEncrypt.ReadToEnd();
                }
            }

            string Decrypt = txtDecryptFile.Text.Trim();
            if (File.Exists(Decrypt))
            {
                using (StreamReader srDecrypt = new StreamReader(Decrypt, Encoding.Default))
                {
                    string Content = srDecrypt.ReadToEnd();
                    txtDecrypt.Text = Content;
                }
            }
        }
    }
}
[C#] 加解密

星期一, 12月 12, 2016

[C#] 利用 GZipStram 進行壓縮與解壓縮

根據 如何:壓縮與解壓縮檔案 這篇文章來學習 GZipStream 壓縮、解壓縮檔案

WinFomr Layout

[C#] 壓縮與解壓縮-1

星期五, 12月 02, 2016

Lenovo Ideapad 310 進入 BIOS

公司新買筆電,發現開機時按 F2、F12 鍵,都沒有辦法進入 BIOS、設定啟動裝置,查使用手冊才知道,要進入 BIOS 要在關機狀態下,按 Novo 鍵,該按鍵就是下圖紅框框的 8 號裝置,要用迴紋針才按的到喔

Lenovo Ideapad 310 進入 BIOS

星期四, 12月 01, 2016

[Win10] Windows 相片檢視器

之前公司電腦都是升級到 Win10,把圖片預設程式改為 Windows 相片檢視器很輕易就可以做到,最近買了一台 PC 內載 Win10,才發現到,為什麼沒有辦法改,找不到 Windows 相片檢視器選項,Orz
Google 後發現,原來 Win10 Windows 相片檢視器,regedit 路徑為 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Photo Viewer\Capabilities\FileAssociations 內預設副檔名只有 .tif 和 .tiff

升級為 Win10 系統 regedit 內副檔名
原生 Win10 系統 regedit 內副檔名
所以只要把要用 Windows 相片檢視器顯示的相關副檔名都加進去就好啦,弄成 reg 檔案 - Win10_WindowsPhotoViewer 方便新增
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Photo Viewer\Capabilities\FileAssociations]
".tif"="PhotoViewer.FileAssoc.Tiff"
".tiff"="PhotoViewer.FileAssoc.Tiff"
".png"="PhotoViewer.FileAssoc.Tiff"
".jpg"="PhotoViewer.FileAssoc.Tiff"
".jpeg"="PhotoViewer.FileAssoc.Tiff"
".gif"="PhotoViewer.FileAssoc.Tiff"
".bmp"="PhotoViewer.FileAssoc.Tiff"
".ico"="PhotoViewer.FileAssoc.Tiff"
執行 Win10_WindowsPhotoViewer.reg 會出現下面提示訊息
執行完成後
完成後 regedit 內的副檔名清單
再去修改預設程式就可以看見 Windows 相片檢視器啦
相片程式在實務上遇到的缺點

  • 透過內部 ERP 去開啟,不知道為什麼,直向圖片,常常會變成橫向圖片
  • 人員常常會需要開開關關圖片,OS 很容易在那邊轉圈圈,轉圈圈當下,左下角的 Windows 功能左鍵功能就掛掉,按不出來,通常都是重開機讓 OS 恢復正常,要不就是耐心等待下面的錯誤訊息跳出來,不過真的要挺有耐心的,Orz
[Win10] Windows 10 相片檢視器-4

20240606 更新

該筆記作法在 Win11 23H2 (OS 組建 22631.3672) 上也是可以使用的