開発環境 Microsoft Visual C# 2010 Express (SP1)
実行環境 Microsoft Windows XP Home Edition (SP3)
プロジェクトの種類 空のプロジェクト
プロジェクト名 Jien2ch

Jien2chプロジェクトにクラスを追加。
テンプレート:クラス
名前:ListViewEx

textBox1を削除。

Jien2ch コンポーネント/ListViewExをPanel2上にドロップ。
名前:listViewEx1
Dock:Fill

Lib2ch.DataをDataクラスにまとめた。

+Jien2ch
 +Form1.cs
  +Form1.Designer.cs
 +ListViewEx.cs
 +Program.cs
+Lib2ch
 +Data
  +Data.cs
 +IO
  +File.cs
  +FileManager.cs
 +Model
  +BbsMenu.cs
  +Subject.cs


namespace Jien2ch


Program.cs
using System.Windows.Forms;
 
namespace Jien2ch
{
	class Program
	{
		static void Main()
		{
			Application.Run(new Form1());
		}
	}
}
 

Form1.cs
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using Lib2ch.Data;
using Lib2ch.Model;
 
namespace Jien2ch
{
	public partial class Form1 : Form
	{
		Subject _Subject = new Subject();
 
		public Form1()
		{
			InitializeComponent();
		}
 
		private void Form1_Load(object sender, EventArgs e)
		{
			#region 板一覧
			BbsMenu bbsMenu = new BbsMenu();
			List<BbsMenuItem> bbsMenuList = bbsMenu.GetMenuList();
			foreach (BbsMenuItem item in bbsMenuList)
			{
				TreeNode childNode = new TreeNode();
				//childNode.Name = item.Name;
				childNode.Text = item.Name;
				childNode.Tag = item;
				// 親ノード検索
				TreeNode[] node = treeView1.Nodes.Find(item.CategoryName, false);
				if (node.Length == 0)
				{
					TreeNode parent = new TreeNode();
					parent.Name = item.CategoryName;	// 検索用
					parent.Text = parent.Name;	// 表示用
					parent.Nodes.Add(childNode);
					treeView1.Nodes.Add(parent);
				}
				else
				{
					node[0].Nodes.Add(childNode);
				}
			}
			#endregion
		}
 
		#region 板一覧アイテム選択時
		private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
		{
			if (e.Node.Tag != null)
			{
				ThreadListAdd((BbsMenuItem)e.Node.Tag);
			}
		}
 
		// スレッド一覧
		void ThreadListAdd(BbsMenuItem bbsMenuItem)
		{
			SubjectList subjectList = _Subject.Get(bbsMenuItem);
			listViewEx1.ItemSet(subjectList);
		}
		#endregion
	}
}
 

ListViewEx.cs
using System.Windows.Forms;
using Lib2ch.Data;
 
namespace Jien2ch
{
	class ListViewEx : ListView
	{
		public ListViewEx()
		{
			// プロパティ
			View = View.Details;
			FullRowSelect = true;
			GridLines = true;
 
			// 列ヘッダ
			Columns.Add("!", 20);	// 1列目は右寄せできないのでダミー
			Columns.Add("番号", 40, HorizontalAlignment.Right);
			Columns.Add("タイトル", 450);
			Columns.Add("レス", 40, HorizontalAlignment.Right);
		}
 
		public void ItemSet(SubjectList subjectList)
		{
			ListViewItem[] item = new ListViewItem[subjectList.List.Count];
			int num = 0;	// 番号
			foreach (SubjectData data in subjectList.List)
			{
				string[] line = new string[4];
				//line[0] = ;
				line[1] = (num + 1).ToString();
				line[2] = data.Title;
				line[3] = data.Count.ToString();
				item[num] = new ListViewItem(line);
				item[num].Tag = data;
				num++;
			}
			Items.AddRange(item);
			Tag = subjectList;
		}
	}
}
 


namespace Lib2ch.Data


Data.cs
using System;
using System.Collections.Generic;
 
namespace Lib2ch.Data
{
	// 板一覧アイテム
	public class BbsMenuItem
	{
		public string CategoryName;	// カテゴリ名
		public string Name;		// 板名
		public string Url;		// URL
 
		public string Directory
		{
			get
			{
				return "/" + CategoryName + "/" + Name;
			}
		}
	}
 
	// ファイル結果
	class FileResult
	{
		public List<string> Line = new List<string>();	// 行リスト
	}
 
	// スレッドデータ
	public class SubjectData : BbsMenuItem
	{
		string FileName;	// スレッドファイル名(.dat)
		public string Title;	// タイトル
		public int Count;	// レス数
 
		public SubjectData(string line)
		{
			if (line == "") return;
			FileName = line.Substring(0, 14);
			int start = line.LastIndexOf("(");
			int end = line.LastIndexOf(")");
			Count = Convert.ToInt32(line.Substring(start+1, end - (start+1)));
			Title = line.Substring(16, start - 16);
		}
	}
 
	// スレッド一覧
	public class SubjectList : BbsMenuItem
	{
		public List<SubjectData> List = new List<SubjectData>();
 
		public void Parsing(List<string> data)
		{
			foreach (string line in data)
			{
				SubjectData subjectData = new SubjectData(line);
				subjectData.CategoryName = CategoryName;
				subjectData.Name = Name;
				subjectData.Url = Url;
				List.Add(subjectData);
			}
		}
	}
}
 


namespace Lib2ch.IO


File.cs
using System.IO;
using System.Collections.Generic;
using System.Net;
using System.Text;
using Lib2ch.Data;
 
namespace Lib2ch.IO
{
	class File
	{
		Encoding _Type = Encoding.GetEncoding("Shift_JIS");
 
		protected FileResult LocalReader(string path)
		{
			try
			{
				FileResult fileResult = new FileResult();
				using (StreamReader sr = new StreamReader(path, _Type))
				{
					string line;
					while ((line = sr.ReadLine()) != null)
					{
						fileResult.Line.Add(line);
					}
				}
				return fileResult;
			}
			catch
			{
				return null;
			}
		}
 
		protected FileResult UrlReader(string url)
		{
			HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
			req.UserAgent = "Monazilla/1.00(Jien2ch/Lib2ch)";
			req.AddRange(0);
			req.KeepAlive = false;
			req.Headers.Add("Pragma", "no-cache");
			req.Headers.Add("Cache-Control", "no-cache");
			WebResponse res = null;
			FileResult fileResult = new FileResult();
			try
			{
				res = req.GetResponse();
			}
			catch (WebException)
			{
				return fileResult;
			}
			using (Stream stream = res.GetResponseStream())
			{
				using (StreamReader sr = new StreamReader(stream, _Type))
				{
					string line;
					while ((line = sr.ReadLine()) != null)
					{
						fileResult.Line.Add(line);
					}
				}
			}
			return fileResult;
		}
 
		protected bool LocalWriter(string dir, string file, List<string> writeData)
		{
			if (!Directory.Exists(dir))
			{
				Directory.CreateDirectory(dir);
			}
			try
			{
				using (StreamWriter sw = new StreamWriter(dir + file, false, _Type))
				{
					sw.NewLine = "\n";
					foreach (string line in writeData)
					{
						sw.WriteLine(line);
					}
				}
				return true;
			}
			catch
			{
				return false;
			}
		}
	}
}
 

FileManager.cs
using Lib2ch.Data;
 
namespace Lib2ch.IO
{
	class FileManager : File
	{
		public FileResult StandardCheck(string path, string host, string fileName)
		{
			FileResult fileResult = new FileResult();
			fileResult = LocalReader(path + fileName);
			if (fileResult == null)
			{
				// サーバーからダウンロード
				fileResult = UrlReader(host + fileName);
				if (fileResult == null) return null;
				// ファイルの書き込み
				if (!LocalWriter(path, fileName, fileResult.Line))
				{
					return null;
				}
			}
			return fileResult;
		}
	}
}
 


namespace Lib2ch.Model


BbsMenu.cs
using System.Collections.Generic;
using Lib2ch.Data;
using Lib2ch.IO;
 
namespace Lib2ch.Model
{
	// 板一覧
	public class BbsMenu
	{
		string _Path = "./Log";
		string _FileName = "/bbsmenu.html";
		string _Host = "http://menu.2ch.net";
 
		string _CateStart = "<BR><BR><B>";
		string _CateEnd = "</B>";
		string _BbsStart = "<A HREF=";
		string _UrlEnd1 = "/>";
		string _UrlEnd2 = "/ TARGET=_blank>";
		string _BbsEnd = "</A>";
 
		FileManager _File = new FileManager();
 
		public List<BbsMenuItem> GetMenuList()
		{
			// ファイルの有無
			FileResult fileResult = _File.StandardCheck(_Path, _Host, _FileName);
			if (fileResult == null) return null;
			// 解析処理
			return BbsMenuParsing(fileResult.Line);
		}
 
		List<BbsMenuItem> BbsMenuParsing(List<string> data)
		{
			List<BbsMenuItem> list = new List<BbsMenuItem>();
			string parent = null;
			foreach (string line in data)
			{
				// カテゴリ
				// <BR><BR><B>(parent)</B>
				int index1 = line.IndexOf(_CateStart);
				if (index1 != -1)
				{
					int index2 = line.IndexOf(_CateEnd);
					if (index2 != -1)
					{
						int start = index1 + _CateStart.Length;
						parent = line.Substring(start, index2 - start);
					}
				}
				if (parent == null) continue;
 
				BbsMenuItem item = BbsMenuFindLine(line, _BbsStart, _UrlEnd1, _BbsEnd);
				if (item == null)
				{
					item = BbsMenuFindLine(line, _BbsStart, _UrlEnd2, _BbsEnd);
				}
				if (item != null)
				{
					item.CategoryName = parent;
					list.Add(item);
				}
			}
			return list;
		}
 
		// 板のURLと名前を取得
		// <A HREF=(Url)/>(Name)</A>
		// <A HREF=(Url)/ TARGET=_blank>(Name)</A>
		BbsMenuItem BbsMenuFindLine(string line, string word1, string word2, string word3)
		{
			int index1 = line.IndexOf(word1);
			if (index1 == -1) return null;
			int index2 = line.IndexOf(word2);
			if (index2 == -1) return null;
			int index3 = line.IndexOf(word3);
			if (index3 == -1) return null;
 
			BbsMenuItem item = new BbsMenuItem();
			int start1 = index1 + word1.Length;
			int start2 = index2 + word2.Length;
			item.Url = line.Substring(start1, index2 - start1);
			item.Name = line.Substring(start2, index3 - start2);
			return item;
		}
	}
}
 

Subject.cs
using Lib2ch.Data;
using Lib2ch.IO;
 
namespace Lib2ch.Model
{
	// スレッド一覧
	public class Subject
	{
		FileManager _File = new FileManager();
 
		public SubjectList Get(BbsMenuItem bbsMenuItem)
		{
			SubjectList subjectList = new SubjectList();
			subjectList.Name = bbsMenuItem.Name;
			subjectList.Url = bbsMenuItem.Url;
			subjectList.CategoryName = bbsMenuItem.CategoryName;
			FileResult fileResult = _File.StandardCheck(
				"./Log" + subjectList.Directory, subjectList.Url, "/subject.txt");
			if (fileResult == null) return null;
			subjectList.Parsing(fileResult.Line);
			return subjectList;
		}
	}
}
 
最終更新:2012年11月12日 21:37