會練習到這個,也是誤打誤撞
練習的內容是把前一陣子 dropbox 被駭的帳密轉到 db 中
讀取方式是透過 BinaryReader.ReadChar 的方式讀出
同時以換行字元(\r\n)做為各行的區隔
會寫成三個檔案是因為整個方案共有三個專案
把共用的部份取到 Common Class 中
再把 行處理 & 寫入 db 獨立至另一個 Class 中
主程式
using Data;
using System;
using System.Collections.Generic;
namespace DapperToDb
{
class Program
{
static void Main(string[] args)
{
#region 宣告
var watch = new System.Diagnostics.Stopwatch();
char c; // 用來抓字元,抓完後,游標會移至下一個位置
List<char> chars = new List<char>(); // 用來放整個 char 的
AccountDapper ad = new AccountDapper();
#endregion
try
{
watch.Restart();
#region 逐個 char 讀取
while (Common.reader.PeekChar() != -1)
{
if ((c = Common.reader.ReadChar()) == '\r') // (int)'\r' = 13
{
if ((char)Common.reader.PeekChar() == '\n') // (int)'\n' = 10
{
// 讓游標移至 \n 上
Common.reader.ReadChar();
#region 逐行處理
ad.lineToAccount(string.Join("", chars), false);
chars.Clear();
#endregion
continue;
}
}
chars.Add(c);
}
Common.readerClose();
#endregion
//讀取結束,把未寫入的處理
ad.lineToAccount(string.Join("", chars), true);
Console.WriteLine("全部讀取完畢");
watch.Stop();
var elapsedMs = watch.ElapsedMilliseconds;
Console.WriteLine("Time Cost:{0}", elapsedMs);
}
catch (Exception e)
{
Console.WriteLine("檔案處理失敗");
Common.errorToFile(e.Message);
Common.errorToFile(e.StackTrace);
}
Console.ReadLine();
}
}
}
Common Class
using System;
using System.IO;
namespace Data
{
public class Common
{
public static string connectionString = @"Data Source=.\mssql2014;Initial Catalog=dropbox;Integrated Security=True";
public static int maxCountToDb = 1000000;
public static string file = @"../../../txt/bf_1.txt";
private static FileStream _fileStream;
private static BinaryReader _reader;
public static BinaryReader reader
{
get
{
if (_reader != null) return _reader;
_fileStream = File.Open(file, FileMode.Open, FileAccess.ReadWrite);
_reader = new BinaryReader(_fileStream);
return _reader;
}
}
public static bool readerClose()
{
try
{
_fileStream.Close();
_reader.Close();
return true;
}
catch (Exception e)
{
Common.errorToFile(e.Message);
Common.errorToFile(e.StackTrace);
Console.ReadLine();
return false;
}
}
public static void errorToFile(string str)
{
TextWriter writer = new StreamWriter("error.txt", true);
writer.Write(str + "\r\n");
writer.Flush();
writer.Close();
}
}
}
AccountDapper Class
using Dapper;
using Data;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
namespace DapperToDb
{
class AccountDapper
{
private Account _acc;
private List<Account> _accounts = new List<Account>();
public void lineToAccount(string line, bool end)
{
try
{
_acc = new Account(line);
_accounts.Add(_acc);
Console.Write('.');
if (_accounts.Count >= Common.maxCountToDb || end)
{
dapperWriteToDb(_accounts);
_accounts.Clear();
}
}
catch (Exception e)
{
Common.errorToFile(line);
Common.errorToFile(e.Message);
Common.errorToFile(e.StackTrace);
Console.ReadLine();
}
}
public void dapperWriteToDb(List<Account> accounts)
{
using (SqlConnection conn = new SqlConnection(Common.connectionString))
{
conn.Open();
using (var trans = conn.BeginTransaction())
{
var result = conn.Execute(@"INSERT INTO account(id,pw) VALUES(@id,@pw)", accounts, trans);
trans.Commit();
}
}
}
}
}
Account Class
using System;
namespace DapperToDb
{
public class Account
{
public string id { get; set; }
public string pw { get; set; }
public Account(string line)
{
string[] lineArray = line.Split(':');
if (lineArray[0].Trim().Length > 300) throw new Exception("id 太長");
if (lineArray[1].Trim().Length > 70) throw new Exception("pw 太長");
id = lineArray[0].Trim();
pw = lineArray[1].Trim();
}
}
}
SQL Table
CREATE TABLE [dbo].[account](
[id] [nvarchar](300) NULL,
[pw] [nvarchar](70) NULL,
[no] [int] IDENTITY(1,1) NOT NULL,
CONSTRAINT [PK_account] PRIMARY KEY CLUSTERED
(
[no] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO