.NET 技术FAQ(十一)-----类库

来源:互联网 发布:公需课大数据考试答案 编辑:程序博客网 时间:2024/06/05 02:08

11. 类库
11.1 文件 I/O
11.1.1 如何读文本文件?
首先,使用 System.IO.FileStream 对象打开文件:
FileStream fs = new FileStream( @"c:/test.txt", FileMode.Open, FileAccess.Read );
FileStream 继承于 Stream,所以你可以用一个 StreamReader 对象把 FileStream 对象包装起来。这样为一行一行地进行流处理提供了一个良好的界面:
StreamReader sr = new StreamReader( fs );
string curLine;
while( (curLine = sr.ReadLine()) != null )
 Console.WriteLine( curLine );
最后关闭 StreamReader 对象:
sr.Close();
注意这样将自动地在底层 Stream 对象上调用 Close (),所以不必显示地执行 fs.Close()。
 
11.1.2 如何写文本文件?
和读文件的例子相似,只是把 StreamReader 换成 StreamWriter。
 
11.1.3 如何读写二进制文件?
和文本文件类似,只是要用 BinaryReader/Writer 对象而不是 StreamReader/Writer 来包装 FileStream 对象。
 
11.1.4 如何删除文件?
在 System.IO.File 对象上使用静态方法 Delete ():
File.Delete( @"c:/test.txt" );
 
11.2 文本处理
11.2.1 是否支持正规表达式?
是的。使用 System.Text.RegularExpressions.Regex 类。例如,以下代码更新 HTML 文件的标题:
FileStream fs = new FileStream( "test.htm", FileMode.Open, FileAccess.Read );
StreamReader sr = new StreamReader( fs );

Regex r = new Regex( "<TITLE>(.*)</TITLE>" );
string s;
while( (s = sr.ReadLine()) != null )
{
 if( r.IsMatch( s ) )
  s = r.Replace( s, "<TITLE>New and improved ${1}</TITLE>" );
 Console.WriteLine( s );
}
 
11.3 Internet
11.3.1 如何下载网页?
首先使用 System.Net.WebRequestFactory 类来获得一个 WebRequest 对象:
WebRequest request = WebRequestFactory.Create( "
http://localhost" );
然后请求应答:
WebResponse response = request.GetResponse();
GetResponse 方法被阻塞直到下载完成。然后你能像下面那样访问应答流:
Stream s = response.GetResponseStream();

// Output the downloaded stream to the console
StreamReader sr = new StreamReader( s );
string line;
while( (line = sr.ReadLine()) != null )
 Console.WriteLine( line );
注意 WebRequest 和 WebReponse 对象分别向下兼容 HttpWebRequest 和 HttpWebReponse 对象,它们被用来访问和 http 相关的功能。
 
11.3.2 如何使用代理服务器 (proxy)?
两种—这样做以便影响所有 Web 请求:
System.Net.GlobalProxySelection.Select = new DefaultControlObject( "proxyname", 80 );
另外一种,要想对特定的 Web 请求设置代理服务,这样做:
ProxyData proxyData = new ProxyData();
proxyData.HostName = "proxyname";
proxyData.Port = 80;
proxyData.OverrideSelectProxy = true;

HttpWebRequest request = (HttpWebRequest)WebRequestFactory.Create( "http://localhost" );
request.Proxy = proxyData;
 
11.4 XML
11.4.1 是否支持 DOM?
是的。看看以下示例 XML文档:
<PEOPLE>
 <PERSON>Fred</PERSON>
 <PERSON>Bill</PERSON> 
</PEOPLE> 
可以这样处理此文档:
XmlDocument doc = new XmlDocument();
doc.Load( "test.xml" );

XmlNode root = doc.DocumentElement;

foreach( XmlNode personElement in root.ChildNodes )
 Console.WriteLine( personElement.FirstChild.Value.ToString() );
输出为:
Fred
Bill
 
11.4.2 是否支持 SAX?
不。作为替换,提供了一个新的 XmlReader/XmlWriter API。像 SAX 一样,它是基于流的,但它使用“pull”模型而不是 SAX 的“push”模型。这是一个例子:
XmlTextReader reader = new XmlTextReader( "test.xml" );

while( reader.Read() )
{
 if( reader.NodeType == XmlNodeType.Element && reader.Name == "PERSON" )
 {
  reader.Read(); // Skip to the child text
  Console.WriteLine( reader.Value );
 }
}
 
11.4.3 是否支持 XPath?
是的,通过 XmlNavigator 类 (DocumentNavigator 是从 XmlNavigator 导出的):
XmlDocument doc = new XmlDocument();
doc.Load( "test.xml" );

DocumentNavigator nav = new DocumentNavigator(doc);
nav.MoveToDocument();

nav.Select( "descendant::PEOPLE/PERSON" );

while( nav.MoveToNextSelected() )
{
 nav.MoveToFirstChild();
 Console.WriteLine( "{0}", nav.Value );
}
 
11.5 线程
11.5.1 是否支持多线程?
是的,对多线程有广泛的支持。系统能产生新线程,并提供应用程序可以使用的线程池。
 
11.5.2 如何产生一个线程?
创建 System.Threading.Thread 对象的一个实例,把将要在新线程中执行的 ThreadStart 示例传递给它。例如:
class MyThread
{
 public MyThread( string initData )
 {
  m_data = initData;
  m_thread = new Thread( new ThreadStart(ThreadMain) );
  m_thread.Start();
 }

 // ThreadMain() is executed on the new thread.
 private void ThreadMain()
 {
  Console.WriteLine( m_data );
 }

 public void WaitUntilFinished()
 {
  m_thread.Join();
 }

 private Thread m_thread;
 private string m_data;
}
这里创建 MyThread 的一个实例就足以产生线程并执行 MyThread.ThreadMain () 方法:
MyThread t = new MyThread( "Hello, world." );
t.WaitUntilFinished();
 
11.5.3 如何停止一个线程?
有好几个办法。首先,你能使用自己的通讯机制告诉 ThreadStart 方法结束。另外 Thread 类有内置的支持来命令线程停止。基本的两个方法是 Thread.Interrupt () 和 Thread.Abort ()。前者导致抛出一个 ThreadInterruptedException 并随后进入 WaitJoinSleep 状态。换句话说,Thread.Interrupt 是一种礼貌的方式,它请求线程在不再进行任何有用的工作时自行停止的。与此相对应,Thread.Abort () 抛出一个 ThreadAbortException 而不管线程正在做什么。而且,ThreadAbortException 不能像通常的异常那样被捕获 (即使最终将执行 ThreadStart 的终止方法)。Thread.Abort () 是一般情况下不需要的非常手段。
 
11.5.4 怎样使用线程池?
通过向 ThreadPool.QueueUserWorkItem () 方法传递 WaitCallback 的一个实例:
class CApp
{
 static void Main()
 {
  string s = "Hello, World";
  ThreadPool.QueueUserWorkItem( new WaitCallback( DoWork ), s );

  Thread.Sleep( 1000 ); // Give time for work item to be executed
 }

 // DoWork is executed on a thread from the thread pool.
 static void DoWork( object state )
 {
  Console.WriteLine( state );
 }
}
 
11.5.5 怎样知道我的线程池工作项目是在何时完成的?
没有方法询问线程池这类信息。你必须在 WaitCallback 方法中放置代码来发出信号以表明它已经完成。这里事件也很有用处。
 
11.5.6 怎样防止对数据的并发访问?
每个对象有一个与之相联的并发锁 (受批评的部分)。System.Threading.Monitor.Enter/Exit 方法用来获得和释放锁。例如,下面类的实例只允许一个线程同时进入方法 f ():
class C
{
 public void f()
 {
  try
  {
   Monitor.Enter(this);
   ...
  }
  finally
  {
   Monitor.Exit(this);
  }
 }
}
C# 有一个关键字‘lock’提供了以上代码的简单形式:
class C
{
 public void f()
 {
  lock(this)
  {
   ...
  }
 }
}
注意,调用 Monitor.Enter (myObject) 并不意味着对 myObject 的所有访问都被串行化了。它意味着请求同 myObject 相联的同步锁,并且在调用 Monitor.Exit(o) 之前,没有任何其它线程可以请求该锁。换句话说,下面的类和以上给出的类在功能上是等同的:
class C
{
 public void f()
 {
  lock( m_object )
  {
   ...
  }
 }

 private m_object = new object();
}
 
11.6 跟踪
11.6.1 有内置的跟踪/日志支持吗?
是的,在 System.Diagnostics 命名空间中。有两个处理跟踪的主要的类—Debug 和 Trace。它们以相似的方式工作—不同之处是 Debug 类中的跟踪只能在用 DEBUG 标志生成的代码中工作,而 Trace 类中的跟踪只能在指明了 TRACE 标记生成的代码中工作。典型地,这意味着你应该在你希望能在 debug 和 release 版本中都能跟踪时使用 System.Diagnostics.Trace.WriteLine,而在你希望只能在 debug 版本中能跟踪时使用 System.Diagnostics.Debug.WriteLine。
 
11.6.2 能否将跟踪输出重定向到一个文件?
是的。Debug 类和 Trace 类都有一个 Listeners 属性,它们分别收集你用 Debug.WriteLine 或 Trace.WriteLine 产生的输出。默认情况下 Listeners 只有一个收集槽,它是 DefaultTraceListener 类的一个实例。它将输出发送到 Win32 的 OutputDebugString () 函数和 System.Diagnostics.Debugger.Log () 方法。调试时这很有用,但如果你试图从客户站点跟踪一个问题,将输出重定向到一个文件中就更为恰当。幸运的是,为此目的提供了 TextWriterTraceListener 类。
这里是 TextWriterTraceListener 如何将 Trace 输出重定向到一个文件:
Trace.Listeners.Clear();
FileStream fs = new FileStream( @"c:/log.txt", FileMode.Create, FileAccess.Write );
Trace.Listeners.Add( new TextWriterTraceListener( fs ) );

Trace.WriteLine( @"This will be writen to c:/log.txt!" );
注意使用 Trace.Listeners.Clear () 去掉了默认的 listener。如果不这样做,输出将在文件和 OutputDebugString () 中同时产生。一般情况下你不希望如此,因为 OutputDebugString () 导致很大的性能开销。
 
11.6.3 能否定制跟踪的输出?
是的。你能编写你自己的 TraceListener 导出类,并把所有的输出重定向到它上面。这里有一个简单的例子,它从 TextWriterTraceListener 导出 (并随后内建了对写文件的支持) 并在每个输出行上添加时间信息和线程 ID:
class MyListener : TextWriterTraceListener
{
 public MyListener( Stream s ) : base(s)
 {
 }

 public override void WriteLine( string s )
 {
  Writer.WriteLine( "{0:D8} [{1:D4}] {2}",
   Environment.TickCount - m_startTickCount,
   AppDomain.GetCurrentThreadId(),
   s );
 }

 protected int m_startTickCount = Environment.TickCount;
}
(
注意这个实现并不完整例如没有覆盖 TraceListener.Write 方法。)
这种方法的美妙之处在于,向 Trace.Listener 添加 MyListener 之后,所有对 Trace.WriteLine () 的调用都转向了 MyListener,包括从对 MyListener 一无所知的被引用元件发出的调用。
 
 
Microsoft
还发布了 .NET Framework FAQ,和本文很相似。可以在那里找到这里许多问题更权威的解答。
Robert Scoble
编辑了一个很容易理解的在线列表。
原创粉丝点击