文章目录
本文比较杂乱,是本人在学习C#中的一些笔记,并不全面,只是一些随笔。
1. C# 程序简介:
一个C#程序主要包括以下部分:
命名空间声明(Namespace declaration)
一个 class
Class 方法
Class 属性
一个 Main 方法
语句(Statements)& 表达式(Expressions)
注释
// using 关键字用于在程序中包含 System 命名空间。 一个程序一般有多个 using 语句。
using System;
//声明一个命名空间,在这里HelloWorldApplication中只包含了一个HelloWorld类
namespace HelloWorldApplication
{
//类名
class HelloWorld
{
//一个Main方法,是所有 C# 程序的 入口点。
static void Main(string[] args)
{
/* 我的第一个 C# 程序*/
//在屏幕上打印出一行字
Console.WriteLine("Hello World");
//是针对 VS.NET 用户的。这使得程序会等待一个按键的动作,防止程序从 Visual Studio .NET 启动时屏幕会快速运行并关闭。
Console.ReadKey();
}
}
}
2.数据类型详解
2.1 值类型
如果在实际使用过程中不记得当前数据类型的大小时,可以使用sizeof函数获取。
Console.WriteLine("Size of int: {0}", sizeof(int));
运行结果为:
Size of int: 4
表示int类型能够容纳4个字节,也就是32位的有符号整数类型。
2.2 引用类型
引用类型不包含存储在变量中的实际数据,但它们包含对变量的引用。
换句话说,它们指的是一个内存位置。使用多个变量时,引用类型可以指向一个内存位置。如果内存位置的数据是由一个变量改变的,其他变量会自动反映这种值的变化。内置的 引用类型有:object、dynamic 和 string。
-
对象(Object)类型
对象(Object)类型 是 C# 通用类型系统(Common Type System - CTS)中所有数据类型的终极基类。Object 是 System.Object 类的别名。所以对象(Object)类型可以被分配任何其他类型(值类型、引用类型、预定义类型或用户自定义类型)的值。但是,在分配值之前,需要先进行类型转换。
当一个值类型转换为对象类型时,则被称为 装箱;另一方面,当一个对象类型转换为值类型时,则被称为 拆箱。
object obj;
obj = 100; // 这是装箱
-
动态(Dynamic)类型
您可以存储任何类型的值在动态数据类型变量中。这些变量的类型检查是在运行时发生的。
声明动态类型的语法:
dynamic <variable_name> = value;
例如:
dynamic d = 20;
动态类型与对象类型相似,但是对象类型变量的类型检查是在编译时发生的,而动态类型变量的类型检查是在运行时发生的。
- 字符串类型
同java字符串类型的声明方式:
String str = "runoob.com";
但是前面可以加上@代表转义字符:
在这里插入代码片
2.3 指针类型(Pointer types)
指针类型变量存储另一种类型的内存地址。C# 中的指针与 C 或 C++ 中的指针有相同的功能。
声明指针类型的语法:
type* identifier;
3. C#的类型转换
类型转换分为显式和隐式两种,隐式不必多说,显示也与java大致相同。
double d = 5673.74;
int i;
// 强制转换 double 为 int
i = (int)d;
C#提供了一些内置的数据类型转换方法:
| 方法 | 描述 |
|---|---|
| ToBoolean | 如果可能的话,把类型转换为布尔型。 |
| ToByte | 把类型转换为字节类型 |
| ToChar | 如果可能的话,把类型转换为单个 Unicode 字符类型。 |
| ToDateTime | 把类型(整数或字符串类型)转换为 日期-时间 结构。 |
| ToDecimal | 把浮点型或整数类型转换为十进制类型。 |
| ToDouble | 把类型转换为双精度浮点型。 |
| ToInt16 | 把类型转换为 16 位整数类型。 |
| ToInt32 | 把类型转换为 32 位整数类型。 |
| ToInt64 | 把类型转换为 64 位整数类型。 |
| ToSbyte | 把类型转换为有符号字节类型。 |
| ToSingle | 把类型转换为小浮点数类型。 |
| ToString | 把类型转换为字符串类型。 |
| ToType | 把类型转换为指定类型。 |
| ToUInt16 | 把类型转换为 16 位无符号整数类型。 |
| ToUInt32 | 把类型转换为 32 位无符号整数类型。 |
| ToUInt64 | 把类型转换为 64 位无符号整数类型。 |
例如:
bool b = true;
Console.WriteLine(b.ToString());
结果为:
True
4. 常量
4.1 整数常量
4.2 字符串常量
和java中的String一样
4.3 定义常量
const <data_type> <constant_name> = value;
例如:
const double pi = 3.14159;
5.运算符
5.1 算术运算符
5.2 关系运算符
5.3 逻辑运算符
5.4 位运算符
5.5 赋值运算符
5.6 其他运算符
5.7 运算符的优先级
6. C#的封装
- public:所有对象都可以访问;
- private:对象本身在对象内部可以访问;
- protected:只有该类对象及其子类对象可以访问(在继承的章节会详细了解)
- internal:同一个程序集的对象可以访问;
- protected internal:访问限于当前程序集或派生自包含类的类型。
6.1 Internal
Internal 访问说明符允许一个类将其成员变量和成员函数暴露给当前程序中的其他函数和对象。换句话说,带有 internal 访问修饰符的任何成员可以被定义在该成员所定义的应用程序内的任何类或方法访问。
6.2 Protected Internal
Protected Internal 访问修饰符允许在本类,派生类或者包含该类的程序集中访问。这也被用于实现继承。
7. 方法中参数的传递方式
7.1 值传递
实际参数的值会复制给形参,实参和形参使用的是两个不同内存中的值。所以,当形参的值发生改变时,不会影响实参的值,从而保证了实参数据的安全。
7.2 引用传递
引用参数是一个对变量的内存位置的引用。当按引用传递参数时,与值参数不同的是,它不会为这些参数创建一个新的存储位置。引用参数表示与提供给方法的实际参数具有相同的内存位置。
在 C# 中,使用 ref 关键字声明引用参数。
例如:
public void swap(ref int x, ref int y)
{
int temp;
temp = x; /* 保存 x 的值 */
x = y; /* 把 y 赋值给 x */
y = temp; /* 把 temp 赋值给 y */
}
7.3 按输出传递参数
return 语句可用于只从函数中返回一个值。但是,可以使用 输出参数 来从函数中返回两个值。输出参数会把方法输出的数据赋给自己,其他方面与引用参数相似。
提供给输出参数的变量不需要赋值。当需要从一个参数没有指定初始值的方法中返回值时,输出参数特别有用。请看下面的实例,来理解这一点:
using System;
namespace CalculatorApplication
{
class NumberManipulator
{
public void getValues(out int x, out int y )
{
Console.WriteLine("请输入第一个值: ");
x = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("请输入第二个值: ");
y = Convert.ToInt32(Console.ReadLine());
}
static void Main(string[] args)
{
NumberManipulator n = new NumberManipulator();
/* 局部变量定义 */
int a , b;
/* 调用函数来获取值 */
n.getValues(out a, out b);
Console.WriteLine("在方法调用之后,a 的值: {0}", a);
Console.WriteLine("在方法调用之后,b 的值: {0}", b);
Console.ReadLine();
}
}
}
结果是:
请输入第一个值:
7
请输入第二个值:
8
在方法调用之后,a 的值: 7
在方法调用之后,b 的值: 8
8. 可空类型(Nullable)
8.1 单问号?
语法如下:
< data_type> ? <variable_name> = null;
8.2 双问号??
如果第一个操作数的值为 null,则运算符返回第二个操作数的值,否则返回第一个操作数的值。
double? num1 = null;
double num3;
num3 = num1 ?? 5.34; // num1 如果为空值则返回 5.34
Console.WriteLine("num3 的值: {0}", num3);
num3 = num2 ?? 5.34;
Console.WriteLine("num3 的值: {0}", num3);
结果为:
num3 的值: 5.34
num3 的值: 3.14157
9. C#中的数组
9.1 数组入门
数组的语法:
datatype[] arrayName;
给数组赋值、访问数组元素和使用foreach遍历数组同java。
9.2 多维数组
一般为二维数组和三维数组。
- 二维数组
/* 初始化一个带有 5 行 2 列的数组 */
int[,] a = new int[5, 2] {{0,0}, {1,2}, {2,4}, {3,6}, {4,8} };
int i, j;
/* 输出数组中每个元素的值 */
for (i = 0; i < 5; i++)
{
for (j = 0; j < 2; j++)
{
Console.WriteLine("a[{0},{1}] = {2}", i, j, a[i,j]);
}
}
- 三维数组
int [ , , ] m;
//需要使用三个for循环进行数组的遍历;
9.3 交错数组
就是在数组中再创建一个数组。
int[][] scores = new int[2][]{new int[]{92,93,94},new int[]{85,66,87,88}};
其中,scores 是一个由两个整型数组组成的数组 – scores[0] 是一个带有 3 个整数的数组,scores[1] 是一个带有 4 个整数的数组。
例如:
/* 一个由 5 个整型数组组成的交错数组 */
int[][] a = new int[][]{new int[]{0,0},new int[]{1,2},
new int[]{2,4},new int[]{ 3, 6 }, new int[]{ 4, 8 } };
int i, j;
/* 输出数组中每个元素的值 */
for (i = 0; i < 5; i++)
{
for (j = 0; j < 2; j++)
{
Console.WriteLine("a[{0}][{1}] = {2}", i, j, a[i][j]);
}
}
9.4 参数数组
当你不确定要传多少参数给一个函数的时候,就可以使用参数数组。
使用格式如下:
public 返回类型 方法名称( params 类型名称[] 数组名称 )
例子:
namespace ArrayApplication
{
class ParamArray
{
public int AddElements(params int[] arr)
{
int sum = 0;
foreach (int i in arr)
{
sum += i;
}
return sum;
}
}
class TestClass
{
static void Main(string[] args)
{
ParamArray app = new ParamArray();
int sum = app.AddElements(512, 720, 250, 567, 889);
Console.WriteLine("总和是: {0}", sum);
Console.ReadKey();
}
}
}
9.5 Array类
9.5.1 常用属性:
9.5.2 常用方法
- Clear
根据元素的类型,设置数组中某个范围的元素为零、为 false 或者为 null。 - Copy(Array, Array, Int32)
从数组的第一个元素开始复制某个范围的元素到另一个数组的第一个元素位置。长度由一个 32 位整数指定。 - CopyTo(Array, Int32)
从当前的一维数组中复制所有的元素到一个指定的一维数组的指定索引位置。索引由一个 32 位整数指定。 - GetLength
获取一个 32 位整数,该值表示指定维度的数组中的元素总数 - GetLowerBound
获取数组中指定维度的下界。 - GetUpperBound
获取数组中指定维度的上界。 - GetType
获取当前实例的类型。从对象(Object)继承。 - GetValue(Int32)
获取一维数组中指定位置的值。索引由一个 32 位整数指定。 - IndexOf(Array, Object)
搜索指定的对象,返回整个一维数组中第一次出现的索引。 - Reverse(Array)
逆转整个一维数组中元素的顺序。 - Sort(Array)
使用数组的每个元素的 IComparable 实现来排序整个一维数组中的元素。 - SetValue(Object, Int32)
给一维数组中指定位置的元素设置值。索引由一个 32 位整数指定。 - ToString
返回一个表示当前对象的字符串。从对象(Object)继承。
10. 字符串
字符串中的常用方法:
10.1 格式化日期
DateTime dt = new DateTime(2017,4,1,13,16,32,108);
string.Format("{0:y yy yyy yyyy}",dt); //17 17 2017 2017
string.Format("{0:M MM MMM MMMM}", dt);//4 04 四月 四月
string.Format("{0:d dd ddd dddd}", dt);//1 01 周六 星期六
string.Format("{0:t tt}", dt);//下 下午
string.Format("{0:H HH}", dt);//13 13
string.Format("{0:h hh}", dt);//1 01
string.Format("{0:m mm}", dt);//16 16
string.Format("{0:s ss}", dt);//32 32
string.Format("{0:F FF FFF FFFF FFFFF FFFFFF FFFFFFF}", dt);//1 1 108 108 108 108 108
string.Format("{0:f ff fff ffff fffff ffffff fffffff}", dt);//1 10 108 1080 10800 108000 1080000
string.Format("{0:z zz zzz}", dt);//+8 +08 +08:00
string.Format("{0:yyyy/MM/dd HH:mm:ss.fff}",dt); //2017/04/01 13:16:32.108
string.Format("{0:yyyy/MM/dd dddd}", dt); //2017/04/01 星期六
string.Format("{0:yyyy/MM/dd dddd tt hh:mm}", dt); //2017/04/01 星期六 下午 01:16
string.Format("{0:yyyyMMdd}", dt); //20170401
string.Format("{0:yyyy-MM-dd HH:mm:ss.fff}", dt); //2017-04-01 13:16:32.108
*.ToString()也可以实现相同的效果:
DateTime dt = new DateTime(2017,4,1,13,16,32,108);
dt.ToString("y yy yyy yyyy");//17 17 2017 2017
dt.ToString("M MM MMM MMMM");//4 04 四月 四月
dt.ToString("d dd ddd dddd");//1 01 周六 星期六
dt.ToString("t tt");//下 下午
dt.ToString("H HH");//13 13
dt.ToString("h hh");//1 01
dt.ToString("m mm");//16 16
dt.ToString("s ss");//32 32
dt.ToString("F FF FFF FFFF FFFFF FFFFFF FFFFFFF");//1 1 108 108 108 108 108
dt.ToString("f ff fff ffff fffff ffffff fffffff");//1 10 108 1080 10800 108000 1080000
dt.ToString("z zz zzz");//+8 +08 +08:00
dt.ToString("yyyy/MM/dd HH:mm:ss.fff"); //2017/04/01 13:16:32.108
dt.ToString("yyyy/MM/dd dddd"); //2017/04/01 星期六
dt.ToString("yyyy/MM/dd dddd tt hh:mm"); //2017/04/01 星期六 下午 01:16
dt.ToString("yyyyMMdd"); //20170401
dt.ToString("yyyy-MM-dd HH:mm:ss.fff"); //2017-04-01 13:16:32.108
11. 结构体
结构体是值类型数据结构。它使得一个单一变量可以存储各种数据类型的相关数据。struct 关键字用于创建结构体。
例如:
struct Books
{
private string title;
private string author;
private string subject;
private int book_id;
public void getValues(string t, string a, string s, int id)
{
title = t;
author = a;
subject = s;
book_id =id;
}
public void display()
{
Console.WriteLine("Title : {0}", title);
Console.WriteLine("Author : {0}", author);
Console.WriteLine("Subject : {0}", subject);
Console.WriteLine("Book_id :{0}", book_id);
}
};
11.1 结构体和类的区别
- 类是引用类型,结构是值类型。
- 结构不支持继承。
- 结构不能声明默认的构造函数。
- 结构体中声明的字段无法赋予初值,类可以:
struct test001
{
private int aa = 1;
}
执行以上代码将出现“结构中不能实例属性或字段初始值设定”的报错,而类中无此限制,代码如下:
class test002
{
private int aa = 1;
}
- 结构体的构造函数中,必须为结构体所有字段赋值,类的构造函数无此限制:
11.2 什么时候选择结构?
首先明确,类的对象是存储在堆空间中,结构存储在栈中。堆空间大,但访问速度较慢,栈空间小,访问速度相对更快。故而,当我们描述一个轻量级对象的时候,结构可提高效率,成本更低。当然,这也得从需求出发,假如我们在传值的时候希望传递的是对象的引用地址而不是对象的拷贝,就应该使用类了。
12 枚举(Enum)
语法:
enum <enum_name>
{
enumeration list
};
为什么要使用枚举?
例如下面这个例子:
enum len { Length, width, height};
static void Main(string[] args)
{
int[] parameter = new int[3] {1,5,8};
Console.WriteLine("Length: {0}", parameter[(int)len.Length]);
Console.WriteLine("width: {0}", parameter[(int)len.width]);
Console.WriteLine("height: {0}", parameter[(int)len.height]);
}
此时可以一眼看出打印值为参数的长宽高。
该方式在插入一个参时也更加的方便:
enum len {area, Length, width, height};
13. 类(Class)
- 访问标识符 指定了对类及其成员的访问规则。如果没有指定,则使用默认的访问标识符。类的默认访问标识符是 internal,成员的默认访问标识符是 private。
13.1 析构函数
类的 析构函数 是类的一个特殊的成员函数,当类的对象超出范围时执行。
析构函数的名称是在类的名称前加上一个波浪形(~)作为前缀,它不返回值,也不带任何参数。
析构函数用于在结束程序(比如关闭文件、释放内存等)之前释放资源。析构函数不能继承或重载。
class Line
{
private double length; // 线条的长度
public Line() // 构造函数
{
Console.WriteLine("对象已创建");
}
~Line() //析构函数
{
Console.WriteLine("对象已删除");
}
public void setLength( double len )
{
length = len;
}
public double getLength()
{
return length;
}
static void Main(string[] args)
{
Line line = new Line();
// 设置线条长度
line.setLength(6.0);
Console.WriteLine("线条的长度: {0}", line.getLength());
}
}
结果为:
对象已创建
线条的长度: 6
对象已删除
将类成员函数声明为public static无需实例化即可调用类成员函数
反之,如果不声明为static,即使和Main方法从属于同一个类,也必须经过实例化
using System;
namespace ConsoleApp
{
class Program
{
static void Main(string[] args)
{
int num = Add(2, 3); //编译错误,即使改为Program.Add(2, 3);也无法通过编译
Console.WriteLine(num);
}
public int Add(int x, int y)
{
return x + y;
}
}
}
using System;
namespace ConsoleApp
{
class Program
{
static void Main(string[] args)
{
Program self = new Program();
int num = self.Add(2, 3); //编译通过
Console.WriteLine(num);
}
public int Add(int x, int y)
{
return x + y;
}
}
}
14. 继承
当创建一个类时,程序员不需要完全重新编写新的数据成员和成员函数,只需要设计一个新的类,继承了已有的类的成员即可。这个已有的类被称为的基类,这个新的类被称为派生类。
语法如下:
<访问修饰符符> class <基类>
{
...
}
class <派生类> : <基类>
{
...
}
14.1 多重继承
一个类别可以同时从多于一个父类继承行为与特征的功能。但是C#不支持多重继承,只能使用接口来实现多重继承。
15 多态
在静态多态性中,函数的响应是在编译时发生的。在动态多态性中,函数的响应是在运行时发生的。
15.1 静态多态
15.1.1 函数重载(overload)
您可以在同一个范围内对相同的函数名有多个定义。函数的定义必须彼此不同,可以是参数列表中的参数类型不同,也可以是参数个数不同。不能重载只有返回类型不同的函数声明
15.1.2 运算符重载
重载运算符是具有特殊名称的函数,是通过关键字 operator 后跟运算符的符号来定义的。与其他函数一样,重载运算符有返回类型和参数列表。
例如:
// 重载 + 运算符来把两个 Box 对象相加
public static Box operator+ (Box b, Box c)
{
Box box = new Box();
box.length = b.length + c.length;
box.breadth = b.breadth + c.breadth;
box.height = b.height + c.height;
return box;
}
可重载和不可重载运算符:
15.2 动态多态
使用关键字 abstract 创建抽象类,用于提供接口的部分类的实现。当一个派生类继承自该抽象类时,实现即完成。抽象类包含抽象方法,抽象方法可被派生类实现。派生类具有更专业的功能。
注:
- 不能创建一个抽象类的实例
- 不能在一个抽象类外部声明一个抽象方法
- 通过在类定义前面放置关键字 sealed,可以将类声明为密封类。当一个类被声明为 sealed 时,它不能被继承。抽象类不能被声明为 sealed。
abstract class Shape
{
public abstract int area();
}
使用class classname:Shape继承抽象类Shape;
当有一个定义在类中的函数需要在继承类中实现时,可以使用虚方法。虚方法是使用关键字 virtual 声明的。虚方法可以在不同的继承类中有不同的实现。对虚方法的调用是在运行时发生的。
动态多态性是通过 抽象类 和 虚方法 实现的。
class Shape
{
protected int width, height;
public Shape( int a=0, int b=0)
{
width = a;
height = b;
}
public virtual int area()
{
Console.WriteLine("父类的面积:");
return 0;
}
}
class Rectangle: Shape
{
public Rectangle( int a=0, int b=0): base(a, b)
{
}
//重写了父类的虚方法area
public override int area ()
{
Console.WriteLine("Rectangle 类的面积:");
return (width * height);
}
}
16 接口(Interface)
接口定义了语法合同 “是什么” 部分,派生类定义了语法合同 “怎么做” 部分。
接口使得实现接口的类或结构在形式上保持一致。
抽象类在某种程度上与接口类似,但是,它们大多只是用在当只有少数方法由基类声明由派生类实现时。
例如:
//通常接口命令以 I 字母开头
interface IMyInterface
{
void MethodToImplement();
}
使用语句class InterfaceImplementer : IMyInterface继承IMyInterface接口。
注意:
- 接口方法不能用public abstract等修饰。接口内不能有字段变量,构造函数。
- 接口内可以定义属性(有get和set的方法)。如string color { get ; set ; }这种。
- 实现接口时,必须和接口的格式一致。
- 必须实现接口的所有方法。
17 命名空间(Namespace)
命名空间的设计目的是提供一种让一组名称与其他名称分隔开的方式。在一个命名空间中声明的类的名称与另一个命名空间中声明的相同的类的名称不冲突。
namespace namespace_name
{
// 代码声明
}
调用命名空间中的类或模块时:
namespace_name.item_name;
17.1 using 关键字
以使用 using 命名空间指令,这样在使用的时候就不用在前面加上命名空间名称。有点类似于java中的import。
using namespace_name;
17.2 嵌套命名空间
命名空间可以被嵌套,即您可以在一个命名空间内定义另一个命名空间。
可以使用点(.)运算符访问嵌套的命名空间的成员。
18 预处理器指令
18.1 #define 预处理器
#define 允许您定义一个符号,这样,通过使用符号作为传递给 #if 指令的表达式,表达式将返回 true。
例如:
#define PI
...
#if (PI)
Console.WriteLine("PI is defined");
#else
Console.WriteLine("PI is not defined");
#endif
Console.ReadKey();
结果:
PI is defined
18.2 条件指令
您可以使用 #if 指令来创建一个条件指令。条件指令用于测试符号是否为真。如果为真,编译器会执行 #if 和下一个指令之间的代码。一个以 #if 指令开始的条件指令,必须显示地以一个 #endif 指令终止。
上个例子中有条件指令的使用方法。
19 正则表达式
正则表达式 是一种匹配输入文本的模式。.Net 框架提供了允许这种匹配的正则表达式引擎。模式由一个或多个字符、运算符和结构组成。
大佬的博客,以后可以看看:
https://www.cnblogs.com/zhangxiaoyong/p/6043283.html
20 异常处理
一些派生自 Sytem.SystemException 类的预定义的异常类:
20.1 创建用户自定义异常
using System;
namespace UserDefinedException
{
class TestTemperature
{
static void Main(string[] args)
{
Temperature temp = new Temperature();
try
{
temp.showTemp();
}
catch(TempIsZeroException e)
{
Console.WriteLine("TempIsZeroException: {0}", e.Message);
}
Console.ReadKey();
}
}
}
public class TempIsZeroException: ApplicationException
{
public TempIsZeroException(string message): base(message)
{
}
}
public class Temperature
{
int temperature = 0;
public void showTemp()
{
if(temperature == 0)
{
throw (new TempIsZeroException("Zero Temperature found"));
}
else
{
Console.WriteLine("Temperature: {0}", temperature);
}
}
}
以上就抛出了一个用户自定义的对象,也可以在异常语句中抛出异常。
Catch(Exception e)
{
...
Throw e
}
21 文件的输入和输出
输入流用于从文件读取数据(读操作),输出流用于向文件写入数据(写操作)。
21.1 I/O 类常用的非抽象类
21.2 FileStream 类
- 首先需要创建一个 FileStream 对象来创建一个新的文件,或打开一个已有的文件。
FileStream <object_name> = new FileStream( <file_name>,
<FileMode Enumerator>, <FileAccess Enumerator>, <FileShare Enumerator>);
例如:
static void Main(string[] args)
{
FileStream F = new FileStream("test.dat",
FileMode.OpenOrCreate, FileAccess.ReadWrite);
for (int i = 1; i <= 20; i++)
{
F.WriteByte((byte)i);
}
F.Position = 0;
for (int i = 0; i <= 20; i++)
{
Console.Write(F.ReadByte() + " ");
}
F.Close();
Console.ReadKey();
}
21.3 StreamReader 类
常用方法:
一个例子:
static void Main(string[] args)
{
try
{
// 创建一个 StreamReader 的实例来读取文件
// using 语句也能关闭 StreamReader
using (StreamReader sr = new StreamReader("c:/jamaica.txt"))
{
string line;
// 从文件读取并显示行,直到文件的末尾
while ((line = sr.ReadLine()) != null)
{
Console.WriteLine(line);
}
}
}
catch (Exception e)
{
// 向用户显示出错消息
Console.WriteLine("The file could not be read:");
Console.WriteLine(e.Message);
}
Console.ReadKey();
}
21.4 StreamWriter 类
常用方法:
例子:
static void Main(string[] args)
{
string[] names = new string[] {"Zara Ali", "Nuha Ali"};
using (StreamWriter sw = new StreamWriter("names.txt"))
{
foreach (string s in names)
{
sw.WriteLine(s);
}
}
// 从文件中读取并显示每行
string line = "";
using (StreamReader sr = new StreamReader("names.txt"))
{
while ((line = sr.ReadLine()) != null)
{
Console.WriteLine(line);
}
}
Console.ReadKey();
}
21.5 BinaryReader 类
static void Main(string[] args)
{
BinaryReader br ;
BinaryWriter bw ;
int i = 1;
bool flag = true;
double a = 3.12;
string h = "hhhhhh";
//创建文件
try
{
bw = new BinaryWriter(new FileStream("newtext.txt",FileMode.Create));
}
catch (Exception e){
Console.WriteLine("不能创建文件"+e.Message);
return;
}
//写入文件
try {
bw.Write(i);
bw.Write(flag);
bw.Write(a);
bw.Write(h);
}
catch (Exception e) {
Console.WriteLine("不能够写入文件"+e.Message);
}
bw.Close();
//读取文件内容
try
{
br = new BinaryReader(new FileStream("newtext.txt", FileMode.Open));
i = br.ReadInt32();
Console.WriteLine("int : " + i);
flag = br.ReadBoolean();
Console.WriteLine("boolean : " + flag);
a = br.ReadDouble();
Console.WriteLine("double : " + a);
h = br.ReadString();
Console.WriteLine("String : " + h);
br.Close();
}
catch (IOException e)
{
Console.WriteLine("读取文件错误" + e.Message);
}
Console.ReadKey();
}
21.6 DirectoryInfo 类
常用属性:
常用方法:
21.7 FileInfo 类
常用属性:
常用方法:
例子如下:
static void Main(string[] args)
{
//创建一个DirectoryInfo对象
DirectoryInfo mydir = new DirectoryInfo(@"c:\Windows");
//获取目录中的文件以及他们的名称和大小
FileInfo[] f = mydir.GetFiles();
foreach (FileInfo fi in f) {
Console.WriteLine("File Name {0},File size {1}",fi.FullName,fi.Length);
}
Console.ReadKey();
}
运行结果: