1、IO操作相关的类

  1. //静态类
  2. -->File //操作文件,对文件整体进行操作,拷贝、删除、剪切等。
  3. -->Directory //对目录(文件夹)进行操作。
  4. -->Path //对文件或目录的路径进行操作。
  5. //抽象类
  6. -->Stream //流 下面是继承的子类
  7. ~FileStream //文件流
  8. ~StreamReader //快速读取文本文件
  9. ~streamWriter //快速写入文本文件
  10. ~MemoryStream //内存流
  11. ~NetworkStream //网络流
  12. //实例类
  13. -->DirectoryInfo //文件夹的“类”,用来描述一个文件夹对象(获取指定目录下的所有目录时返回一个DirectoryInfo数组)
  14. -->FileInfo //文件类,用来描述一个文件对象。获取指定目录下的所有文件时,返回一个FileInfo数组。

其实IO操作就是操作一些API对文件进行读写,主要是对流的理解,下面分别对路径类(Path)、文件类(File)、目录类(Directory)和对应API进行使用操作。

1)Path类

//这里以文件C:\Users\liudengyan\Desktop\new.txt为例
//获得文件名(这里的文件指文件本身)
     //1、获得包括扩展名的文件名(输出:new.txt)
         Path.GetFileName(@"C:\Users\liudengyan\Desktop\new.txt");
     //2、获取不包括扩展名的文件名(输出:new)
         Path.GetFileNameWithoutExtension(@"C:\Users\liudengyan\Desktop\new.txt");
     //获取扩展名(输出:.txt)
         Path.GetExtension(@"C:\Users\liudengyan\Desktop\new.txt");
     //获取文件所在文件夹路径(输出:C:\Users\liudengyan\Desktop)
         Path.GetDirectoryName(@"C:\Users\liudengyan\Desktop\new.txt");
     //获取文件夹的绝对路径(输出:C:\Users\liudengyan\Desktop\new.txt)
Path.GetFullPath();

//为了不重名 可以使用Guid==

其实上述Path类其实就是对一个已经知道文件进行查询操作,以便获取其路径和文件名称等文件信息,并不能去真正的去操作一个文件进行增删改查、复制、剪切、读写等操作,下面就是真正的运用这些操作来进行文件的读写等等功能。

2)File类

想进行文件的增删改查就必须使用另一个类:File类,这也是在System.IO中,是一个静态类

/// <summary>
/// 封装了对文件的操作
/// </summary>
class FileOperation
{
    public void FO()
    {
        //判断文件是否存在
        if (!File.Exists(""))
        {
            Directory.CreateDirectory("");
            //在创建文件前要先创建文件夹
            using (FileStream fileStream = File.Create(""))//创建文件
            {
                //二进制流文件写入
                string name = "41684135416541";
                byte[] bys = Encoding.Default.GetBytes(name);
                fileStream.Write(bys, 0, bys.Length);
                //将流中数据推入持久化
                fileStream.Flush();
            }
            //第二种文件写入方法
            using (FileStream fileStream = File.Create(""))//创建文件
            {
                //文件写入,数据会覆盖
                StreamWriter sw = new StreamWriter(fileStream);
                sw.WriteLine("163543");
                sw.Flush();
            }
            using (StreamWriter sw = File.AppendText(""))//创建打开文件
            {
                sw.WriteLine("");
                //写入文件的数据会追加,不会覆盖
                sw.Flush();
            }
            using (StreamWriter sw = File.AppendText(""))//创建打开文件
            {
                byte[] bys = Encoding.Default.GetBytes("54351351");
                sw.BaseStream.Write(bys, 0, bys.Length);
                sw.Flush();

            }
            File.Copy("", "");
            File.Move("", "");
            //尽量不要使用删除,在web文件上传中断的时候。
            File.Delete("");
            // 文件的读取
            foreach (var item in File.ReadAllLines(""))
            {
                Console.WriteLine(item);
            }
            string v = File.ReadAllText("");
            byte[] v1 = File.ReadAllBytes("");
            string v2 = Encoding.UTF8.GetString(v1);



            // 当读大文件的时候,通常用分批读取的方式
            using (FileStream stream = File.OpenRead(""))//分批读取
            {
                int length = 5;
                int result = 0;
                do
                {
                    byte[] bytes = new byte[length];
                    result = stream.Read(bytes, 0, 5);
                    for (int i = 0; i < result; i++)
                    {
                        Console.WriteLine(bytes[i].ToString());
                    }
                } while (length == result);
            }
        }
    }
}

3)Directory类

对文件夹进行创建、删除、移动等操作API

//文件夹操作
class DirectoryOperition
{
    public void DO()
    {
        //查看当前文件路径是否有文件夹
        if (!Directory.Exists(""))
        {
            //创建文件夹
            DirectoryInfo directoryInfo = Directory.CreateDirectory("");
            //移动文件夹
            Directory.Move("", "");
            //删除文件夹
            Directory.Delete("");
        }   
        //这里不要用实例化的方式检查文件夹是否存在,如果路径不存在,不会报错。
        DirectoryInfo directoryInfo1 = new DirectoryInfo("");
    }
}

4)Driver类

对磁盘进行操作,主要是查看信息。

//对硬盘文件信息获取
class DriverOpreation
{
    // 获取所有硬盘信息(服务器的)
    DriveInfo[] driveInfos = DriveInfo.GetDrives();
    public void DO()
    {
        foreach (var item in driveInfos)
        {
            if (item.IsReady)
            {
                Console.WriteLine($"类型:{item.DriveType}-卷标:{item.VolumeLabel}-名称:{item.Name}-总空间:{item.TotalSize}-剩余空间:{item.AvailableFreeSpace}");
            }
            else
            {
                Console.WriteLine($"{item.Name} is not Ready");
            }
        }
    }

}

2、序列化操作

1)二进制序列化

/// <summary>
/// 二进制序列化
/// </summary>
public void BinarySerialize()
{
    // 使用二进制序列化对象(将对象转为二进制写入文件中)
    string fileName = Path.Combine(@"D:\project\VS_pro\LearningProject\08_IOOpreation\Ser", "Binary.txt");
    // 序列化
    using (Stream stream = new FileStream(fileName,FileMode.Create,FileAccess.ReadWrite))
    {
        List<int> vs = new List<int>() {1,2,3,4};
        BinaryFormatter binaryFormatter = new BinaryFormatter();//创建二进制序列化器
        binaryFormatter.Serialize(stream, vs);//将对象序列化对象中
    }
    // 反序列化
    using (Stream stream = new FileStream(fileName, FileMode.Open, FileAccess.ReadWrite))
    {
        BinaryFormatter binaryFormatter = new BinaryFormatter();
        stream.Position = 0;//重置流的位置
        List<int> vs = (List<int>)binaryFormatter.Deserialize(stream);
    }
}

2)soap序列化

/// <summary>
/// soap序列化器
/// </summary>
public void SoapSerialize()
{
    string fileName = Path.Combine(@"D:\project\VS_pro\LearningProject\08_IOOpreation\Ser", "Soap.txt");
    // 序列化
    using (Stream stream = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite))
    {
        List<Student> vs = new List<Student>() 
        {
            new Student{id=1,name="ls"},
            new Student{id=2,name="ww"}
        };

        SoapFormatter soapFormatter = new SoapFormatter();
        soapFormatter.Serialize(stream, vs.ToArray());
    }
    // 反序列化
    using (Stream stream = new FileStream(fileName, FileMode.Open, FileAccess.ReadWrite))
    {
        SoapFormatter soapFormatter = new SoapFormatter();
        stream.Position = 0;
        List<Student> vs = ((Student[])soapFormatter.Deserialize(stream)).ToList();
    }
}

3)xml序列化

/// <summary>
/// xml序列化器
/// </summary>
public void XmlSerialize()
{
    string fileName = Path.Combine(@"D:\project\VS_pro\LearningProject\08_IOOpreation\Ser", "Xml.xml");
    // xml序列化
    using (Stream stream = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite))
    {
        List<Student> vs = new List<Student>()
        {
            new Student{id=1,name="ls"},
            new Student{id=2,name="ww"}
        };
        XmlSerializer xml = new XmlSerializer(typeof(List<Student>));
        xml.Serialize(stream, vs);
    }
    // xml反序列化
    using (Stream stream = new FileStream(fileName, FileMode.Open, FileAccess.ReadWrite))
    {
        XmlSerializer xml = new XmlSerializer(typeof(List<Student>));
        stream.Position = 0;
        List<Student> students = (List<Student>)xml.Deserialize(stream);
    }
}

4)json序列化

这里使用了Newtonsoft这个包库,序列化性能较好。

/// <summary>
/// json序列化器
/// </summary>
public void JsonSerialize()
{
    List<Student> vs = new List<Student>()
    {
        new Student{id=1,name="ls"},
        new Student{id=2,name="ww"}
    };
    // 序列化
    string x = JsonConvert.SerializeObject(vs);
    // 反序列化
    List<Student> v = (List<Student>)JsonConvert.DeserializeObject(x,typeof(List<Student>));
}

3、对配置文件读取

通常对配置文件读取需要用一个单独的工具类,字段为静态类读取,集中管理配置文件的读取。

// 用这样一个类来集中读取配置文件需要的字段,这样可以集中管理,以便更改,大多数的字段包括:图片路径,日志路径,数据库连接等路径信息与连接等需要的字符串配置。当然需要根据需求更改。
class PathManager
{
    public static string ImagPath = ConfigurationManager.AppSettings["ImagePath"];

}

4、日志的读写

这里主要用Nlog,比较好用,因为log4不会用-__-!
配置文件:使用的时候注意,配置文件需要在启动项目的根目录配置。

<?xml version="1.0" encoding="utf-8" ?>
<nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.nlog-project.org/schemas/NLog.xsd NLog.xsd"
      autoReload="true"
      throwExceptions="false"
      internalLogLevel="Off" internalLogFile="c:\temp\nlog-internal.log">

  <!-- optional, add some variables
  https://github.com/nlog/NLog/wiki/Configuration-file#variables
  -->
  <variable name="myvar" value="myvalue"/>
<!--
注意:配置文件必须在运行项目的根目录中,不能在封装的Help中使用
-->
  <targets>
    <!-- 写入日志文件 -->
    <!--fileName配置文件路径-->
    <target name="error_file" xsi:type="File" maxArchiveFiles="30"
                        fileName="${basedir}/Logs/${shortdate}/error.txt"
                        layout="${longdate} | ${level:uppercase=false:padding=-5} | ${message} ${onexception:${exception:format=tostring} ${newline} ${stacktrace} ${newline}" />
    <!-- 写入数据库 -->
    <!--<target name="db" xsi:type="AsyncWrapper" queueLimit="5000" overflowAction="Discard">
      <target type="Database" dbProvider="mssql" connectionString="Data Source=.\SQLEXPRESS;Initial Catalog=EFinance;Persist Security Info=True;User ID=sa;Password=123456;">

        <commandText>
          INSERT INTO Log(Timestamp,Level,Message,Action,Amount,StackTrace) VALUES(@time_stamp, @level, @message, @action, @amount, @stacktrace);
        </commandText>
        -->
    <!-- database connection parameters -->
    <!--
        <parameter name="@time_stamp" layout="${date}" />
        <parameter name="@level" layout="${level:uppercase=true}" />
        <parameter name="@message" layout="${message}" />
        <parameter name="@action" layout="${event-context:item=Action}" />
        <parameter name="@amount" layout="${event-context:item=Amount}" />
        <parameter name="@stacktrace" layout="${stacktrace}" />
      </target>
    </target>-->

    <!--控制台输出-->
    <target name="console" xsi:type="ColoredConsole"
                        layout="${date:format=HH\:mm\:ss}> ${message}"/>

    <!--VS输出窗口-->
    <target name="debugger" xsi:type="Debugger"
                        layout="${date:format=HH\:mm\:ss} | ${level:padding=-5} | ${message}" />
  </targets>

  <rules>
    <!--TRACE<DEBUG<INFO<WARN<ERROR<FATAL-->
    <!--向debug输出-->
    <logger name="*" minlevel="Trace" writeTo="debugger" />
    <!--向控制台输出-->
    <logger name="*" writeTo="console" />
    <!--INFO,WARN,ERROR,FATAL-->
    <!--向数据库输出-->
    <!--<logger name="*" minlevel="Info" writeTo="db" />-->
    <!--ERROR,FATAL-->
    <!--向文件输出error级别的日志消息-->
    <logger name="*" minlevel="DEBUG" writeTo="error_file" />
  </rules>
</nlog>

使用封装类:其中可以应对大多数场景需求,当然可以根据需求更改。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Tools.Log
{
    public class NLogHelp
    {
        //public static readonly ILog Log = LogManager.GetLogger("RollingLogFileAppender");
        static NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger();
        //  log定义了8个级别的log(除去OFF和ALL,可以说分为6个级别),优先级从高到低依次为:OFF、FATAL、ERROR、WARN、INFO、DEBUG、TRACE、 ALL。 
        //ALL 最低等级的,用于打开所有日志记录。
        //DEBUG 指出细粒度信息事件对调试应用程序是非常有帮助的,主要用于开发过程中打印一些运行信息。 
        //INFO 消息在粗粒度级别上突出强调应用程序的运行过程。打印一些你感兴趣的或者重要的信息,这个可以用于生产环境中输出程序运行的一些重要信息,
        //WARN 表明会出现潜在错误的情形,有些信息不是错误信息,但是也要给程序员的一些提示。
        //ERROR 指出虽然发生错误事件,但仍然不影响系统的继续运行。打印错误和异常信息,如果不想输出太多的日志,可以使用这个级别。
        //FATAL 指出每个严重的错误事件将会导致应用程序的退出。这个级别比较高了。重大错误,这种级别你可以直接停止程序了。

        //TRACE designates finer-grained informational events than the DEBUG.Since:1.2.12,很低的日志级别,一般不会使用。 
        //OFF 最高等级的,用于关闭所有日志记录。
        //如果将log level设置在某一个级别上,那么比此级别优先级高的log都能打印出来。例如,如果设置优先级为WARN,那么OFF、FATAL、ERROR、WARN 4个级别的log能正常输出,而INFO、DEBUG、TRACE、 ALL级别的log则会被忽略。Log建议只使用四个级别,优先级从高到低分别是ERROR、WARN、INFO、DEBUG。

        #region DEBUG 指出细粒度信息事件对调试应用程序是非常有帮助的,主要用于开发过程中打印一些运行信息。 
            public static void debug(string write)
        {

            Log.Debug("日志记录:" + write);
        }
        public static void debug(string write, Exception ex)
        {
            Log.Debug("日志记录:" + write + "。错误记载:" + ex.ToString());
        }
        #endregion
            #region INFO 消息在粗粒度级别上突出强调应用程序的运行过程。打印一些你感兴趣的或者重要的信息,这个可以用于生产环境中输出程序运行的一些重要信息,
            /// <summary>
            /// 1
            /// </summary>
            /// <param name="write"></param>
            public static void Info(string write)
        {
            Log.Info("日志记录:" + write);
        }
        public static void Info(string write, Exception ex)
        {
            Log.Info("日志记录:" + write + "。错误记载:" + ex.ToString());
        }
        #endregion
            #region WARN 表明会出现潜在错误的情形,有些信息不是错误信息,但是也要给程序员的一些提示。,可以使用这个级别。
            public static void warn(string write)
        {
            Log.Warn("日志记录:" + write);
        }
        public static void warn(string write, Exception ex)
        {
            Log.Warn("日志记录:" + write + "。错误记载:" + ex.ToString());
        }
        #endregion

            #region ERROR 指出虽然发生错误事件,但仍然不影响系统的继续运行。打印错误和异常信息,如果不想输出太多的日志,可以使用这个级别。
            public static void error(string write)
        {
            Log.Error("日志记录:" + write);
        }
        public static void error(string write, Exception ex)
        {
            Log.Error("日志记录:" + write + "。错误记载:" + ex.ToString());
        }
        #endregion
            #region FATAL 指出每个严重的错误事件将会导致应用程序的退出。这个级别比较高了。重大错误,这种级别你可以直接停止程序了。
            public static void fatal(string write)
        {
            Log.Fatal("日志记录:" + write);
        }
        public static void fatal(string write, Exception ex)
        {
            Log.Fatal("日志记录:" + write + "。错误记载:" + ex.ToString());
        }
        #endregion



            ////定义输出的日志内容
            //public static string logMessage(SysLogMsg logMessage)
            //{
            //    StringBuilder strInfo = new StringBuilder();
            //    strInfo.Append("\r\n1. 错误: >> 操作时间: " + logMessage.OperationTime + " 操作人: " + logMessage.UserName + " \r\n");
            //    strInfo.Append("2. 类名: " + logMessage.Class + " \r\n");
            //    strInfo.Append("3. 内容: " + logMessage.Content + "\r\n");
            //    strInfo.Append("-----------------------------------------------------------------------------------------------------------------------------\r\n");
            //    return strInfo.ToString();
            //}
    }
}