iTelnet是最近开发的一个telnet Server, 实现BBS系统的telnet方式访问.

目前支持的系统是基于MySQL的Discuz! BBS. 系统设计中考虑的多数据库系统和多种内模式, 将来计划支持所有主流开源BBS的telnet访问.

系统支持模板机制, 能够通过简单的模板配置实时动态修改显示方式(位置, 颜色等)和内容.

Telnet客户端界面:
image

目录结构:
image

Server界面
image

C#控制台程序还是很常用的, 尤其是开发Server程序的时候, 对于Server出现的各种提示信息使用不同颜色输出, 对用户将是一个很好的提示. 比如错误使用红色输出, 警告使用黄色输出, 而绿色则表示正常等等. 下面是我实现的一个简单的带颜色控制台类.

ColorConsole.cs:
[code=’c#’]
public enum Color
{
Black = 0x00000000,
DarkBlue = 0x00000001,
DarkGreen = 0x00000002,
DarkCyan = 0x00000003,
DarkRed = 0x00000004,
DarkPink = 0x00000005,
DarkYellow = 0x00000006,
DarkWhite = 0x00000007,
Gray = 0x00000008,
Blue = 0x00000009,
Green = 0x000000A,
Cyan = 0x0000000B,
Red = 0x0000000C,
Pink = 0x0000000D,
Yellow = 0x0000000E,
White = 0x0000000F
}

class ColorConsole
{
private int hConsoleHandle;
private COORD ConsoleOutputLocation;
private CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
private int OriginalColors;

private const int STD_OUTPUT_HANDLE = -11;

[DllImport(“kernel32.dll”, EntryPoint = “GetStdHandle”, SetLastError = true,
CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
private static extern int GetStdHandle(int nStdHandle);

[DllImport(“kernel32.dll”, EntryPoint = “GetConsoleScreenBufferInfo”,
SetLastError = true, CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
private static extern int GetConsoleScreenBufferInfo(int hConsoleOutput,
ref CONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo);

[DllImport(“kernel32.dll”, EntryPoint = “SetConsoleTextAttribute”,
SetLastError = true, CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
private static extern int SetConsoleTextAttribute(int hConsoleOutput, int wAttributes);

[StructLayout(LayoutKind.Sequential)]
private struct COORD
{
short X;
short Y;
}

[StructLayout(LayoutKind.Sequential)]
private struct SMALL_RECT
{
short Left;
short Top;
short Right;
short Bottom;
}

[StructLayout(LayoutKind.Sequential)]
private struct CONSOLE_SCREEN_BUFFER_INFO
{
public COORD dwSize;
public COORD dwCursorPosition;
public int wAttributes;
public SMALL_RECT srWindow;
public COORD dwMaximumWindowSize;
}

// Constructor.
public ColorConsole()
{
ConsoleInfo = new CONSOLE_SCREEN_BUFFER_INFO();
ConsoleOutputLocation = new COORD();
hConsoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hConsoleHandle, ref ConsoleInfo);
OriginalColors = ConsoleInfo.wAttributes;
}

public void TextColor(Color color)
{
SetConsoleTextAttribute(hConsoleHandle, (int)color);
}

public void TextColor(Color textColor, Color backColor)
{
SetConsoleTextAttribute(hConsoleHandle, (int)textColor + (int)backColor * 16);
}

public void ResetColor()
{
SetConsoleTextAttribute(hConsoleHandle, OriginalColors);
}
}
[/code]

TestCase:
[code=’c#’]
class Program
{
static void Main(string[] args)
{
ColorConsole cc = new ColorConsole();
cc.TextColor(Color.Red, Color.Gray);
Console.WriteLine(“Server Stopped.”);
}
}
[/code]

参考资料:

[Microsoft Support] 如何通过使用 VisualC # 更改前景颜色和背景颜色控制台窗口中的文本:
http://support.microsoft.com/kb/319883/zh-cn

如下代码,回车不会自动提交输入框内容 ,查看代码确实生成了“submit”类型的按钮,死活不提交

<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="go" /><br />

但是加入一个看不见的输入框就可以正确执行了。

<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<input style="display:none" />
<asp:Button ID="Button1" runat="server" OnClick="Button1_Click" Text="go" /><br />

C#窗口程序开发中,很样式上的问题都是通过控件的Style属性来解决的。比如:

  1. 如何让窗口大小固定?
  2. 我对这个问题一直有误区,解决这个问题我用的原来的笨办法是把窗口的最大最小的Size设置和窗口大小一致,这样虽然可以保持窗口大小不变,但是窗口右下角还是会出现可以拖拽的标志。其实只要将FormBorderStyle从Sizable改为FixedDialog,就可以达到效果了。

  3. 如何让ComboBox只读?
  4. 将ComboBox的DropDownStyle从默认的DropDown改为DropDownList即可。

其实这都是一些很简单的问题,解决方法一旦掌握会很方便,但是如果不知道的话就会一头雾水…说起来用C#也有一段时间了,但这些小东西还是需要摸索才能掌握,算是属于“经验”的知识吧。如果你在控件样式上的要求不能实现,不妨找找Style类的属性,说不定答案就在那里等着你。

下面是我实现的一个数据文件随机读取类,可以随机读取大型文本文件的某一行。在我机器上对一个130MB的文本文件,读取第200000的速度从传统做法的400ms提高到了3ms。
一般对文本文件进行读取时,一般采用ReadLine()进行逐行读取。在这种情况下,C#内的FileStream和BufferedStream类处理绰绰有余了。它不会将整个文件全部读入,而是有缓冲的读。但是,要想随机读取某一行,在行数据长度不统一的情况下,如果每次这样遍历到指定行,其效率显然是很低下的。
当然,代价也是有的,引入了第一次打开文件的打开时间,且占用了少部分内存(占用多少是可以设置的,当然占得越小速度也越慢,但最大值也比全部读入要小很多)。

FileConfig.cs;
[code=’c#’]
using System;
using System.Collections.Generic;
using System.Text;

namespace DataBuffer
{
public static class FileConfig
{
public static int STREAM_BUFFER_SIZE = 1024000;
public static int MAP_DISTANCE = 10;
}
}
[/code]

DataFile.cs:
[code=’c#’]
using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;

namespace DataBuffer
{
public class DataFile
{
///

/// 数据文件名
///
public string fileName = “”;
///

/// 初始化读取完标志
///
public bool done = false;
///

/// 当前流位置
///
public long Position = 0;

private Hashtable head=new Hashtable();
///

/// 文件头部信息
///
public Hashtable Head
{
get
{
return head;
}
set
{
head=value;
}
}

private ArrayList map = new ArrayList();
///

/// 文件地图
///
public ArrayList Map
{
get
{
return map;
}
set
{
map = value;
}
}

private long lines = 0;
///

/// 文件数据行行数
///
public long Lines
{
get
{
return lines;
}
set
{
lines = value;
}
}
}
}
[/code]

DataBuffer.cs:
[code=’c#’]
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Collections;
using System.Threading;

namespace DataBuffer
{
public class DataBuffer
{
private FileStream fs = null;
private BufferedStream bs = null;
private StreamReader sr = null;
private StreamWriter sw = null;
///

/// 文件信息数据结构
///
public DataFile dataFile = new DataFile();
///

/// 构造函数
///
/// 数据文件名

public DataBuffer(string name)
{
dataFile.fileName = name;
}

///

/// 打开文件
///
/// 成功标志
public bool Open()
{
try
{
//初始化各流
fs = new FileStream(dataFile.fileName, FileMode.Open, FileAccess.ReadWrite);
bs = new BufferedStream(fs, FileConfig.STREAM_BUFFER_SIZE);
sr = new StreamReader(fs);
sw = new StreamWriter(fs);
Thread initFile = new Thread(new ThreadStart(InitDataFile));
initFile.Start();

return true;
}
catch (Exception ee)
{
ErrorHandler.ErrorHandler eh = new ErrorHandler.ErrorHandler(ee, “文件打开”);
return false;
}
}

private void InitDataFile()
{
//另开一个读取流
BufferedStream bs = new BufferedStream(fs);
StreamReader sr = new StreamReader(bs);

//读入数据文件头信息。共14行
string thisLine = NextLine(ref sr);
dataFile.Head.Add(“Subject”, thisLine.Substring(11));
thisLine = NextLine(ref sr);
dataFile.Head.Add(“Date”, thisLine.Substring(8));
thisLine = NextLine(ref sr);
dataFile.Head.Add(“Time”, thisLine.Substring(8));
thisLine = NextLine(ref sr);
dataFile.Head.Add(“Channels”, thisLine.Substring(12));
thisLine = NextLine(ref sr);
dataFile.Head.Add(“Rate”, thisLine.Substring(8));
thisLine = NextLine(ref sr);
dataFile.Head.Add(“Type”, thisLine.Substring(8));
thisLine = NextLine(ref sr);
dataFile.Head.Add(“Rows”, thisLine.Substring(8));
thisLine = NextLine(ref sr);
thisLine = NextLine(ref sr);
dataFile.Head.Add(“Electrode Labels”, thisLine);
thisLine = NextLine(ref sr);
thisLine = NextLine(ref sr);
thisLine = NextLine(ref sr);
thisLine = NextLine(ref sr);
thisLine = NextLine(ref sr);
//降低自己的优先级
//Thread.CurrentThread.Priority = ThreadPriority.BelowNormal;

//数行数,建立地图
long lines = 1;
//在地图中加入首条数据的位置信息
dataFile.Map.Add(dataFile.Position);
//顺序建立文件地图
while (!sr.EndOfStream)
{
thisLine = NextLine(ref sr);
if ((++lines) % FileConfig.MAP_DISTANCE == 0)
{
dataFile.Map.Add(dataFile.Position);
}
}
dataFile.Lines = lines;
dataFile.done = true;
}

///

/// 文件关闭
///
/// 成功标志
public bool Close()
{
try
{
//顺序关闭各流
sw.Close();
sr.Close();
bs.Close();
fs.Close();
return true;
}
catch (Exception ee)
{
ErrorHandler.ErrorHandler eh = new ErrorHandler.ErrorHandler(ee, “文件关闭”);
return false;
}
}

///

/// 顺序读取下一行。效率低不建议大规模使用,只在打开文件的时候使用一次
///
/// 流读取器引用

/// 下一行内容
public string NextLine(ref StreamReader sr)
{
string next = sr.ReadLine();
//+2是指Windows换行回车。Linux下要改为+1
dataFile.Position += next.Length+2;
return next;
}

///

/// 快速随机读取一行数据文件内容
///
/// 指定的行数

/// 目标行内容
public string ReadLine(long line)
{
try
{
//如果载入完毕
if (dataFile.done)
{
//确定数据块索引号
int index = (int)line / FileConfig.MAP_DISTANCE;
//移动到指定位置
bs.Seek(long.Parse(dataFile.Map[index].ToString()),SeekOrigin.Begin);
//创建流读取器
sr = new StreamReader(bs);
//移动到指定行
for (int i = 1; i <= (line - index * FileConfig.MAP_DISTANCE); i++) { sr.ReadLine(); } //返回指定行的值 return sr.ReadLine(); } else { return ""; } } catch (Exception ee) { ErrorHandler.ErrorHandler eh = new ErrorHandler.ErrorHandler(ee, "文件读取"); return ""; } } } } [/code]

shupi.gifC++ Primer的第三版结合了Stanley Lippman的实践经验和Josée Lajoie对于ANSI/ISO标准C++的深入理解。这本指导书的第三版已经被重新改写过,以便更加精确地讲述标准C++的特性和用法。在本书中,对于C++初学者特别有价值的是一些来自真实世界中的程序例子,它们说明了泛型程序(generic program)的设计、面向对象程序的设计、模板的用法,以及使用标准C++进行程序设计的方方面面。而且,本书也在适当的地方讲到了一些习惯用法以及效率指导。