- 跟着上一篇关于C# 常用获取接口数据方式 - 在线操作与下载
- 这里讲一下其中用到的文件操作,首先读取与写入文件有多种方式,建议参考文章 C#文本文件(.txt)读写 写的很不错。
- 新建类 FileHelper.cs ,其中代码如下:
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace ConsoleApplication_Json
{
/// <summary>
/// 文件操作
/// </summary>
public class FileHelper
{
#region 读取文件
/// <summary>
/// 按字节读取本地文件,避免内存溢出问题
/// </summary>
/// <param name="tempFile">本地文件地址,如:c:\file\test.txt</param>
/// <returns>输出获取的json格式</returns>
public static string ReadLocalFielJson(string tempFile)
{
var result = string.Empty;
try
{
var stream = new System.IO.FileStream(tempFile, System.IO.FileMode.Open);
int buffersize = 128; //每次读取数据流的大小
byte[] buffer = new byte[buffersize];
int len = 0;
long length = stream.Length; //数据流的大小
int readsize = 0; //已经读取的数据的大小
var strList = new List<string>();
StringBuilder sb = new StringBuilder();
var str = "";
while ((len = stream.Read(buffer, 0, buffersize)) > 0)
{
str += Encoding.UTF8.GetString(buffer, 0, buffersize);
readsize += len;
if ((length - readsize) < buffersize) //如果数据流的总长度减去已经读取的数据流的长度值小于每次读取数据流的设定的大小,那么就重新为buffer字节数组设定大小
{ //这样可以避免最终得到的数据的结尾处多出多余的空值
buffersize = (int)length - readsize;
buffer = new byte[buffersize];
}
}
stream.Dispose();
stream.Close();
result = str;
}
catch (Exception ex)
{
return ex.Message;
}
return result;
}
/// <summary>
/// ReadAllText,内容少时
/// 它们都一次性将文本内容全部读完,并返回一个包含全部文本内容的字符串
/// </summary>
/// <param name="tempFile"></param>
/// <returns></returns>
public static string ReadAllText(string tempFile)
{
string str1 = File.ReadAllText(tempFile);
//也可以指定编码方式
string str2 = File.ReadAllText(tempFile, Encoding.ASCII);
return str2;
}
/// <summary>
/// File.ReadAllLines,该方法一次性读取文本内容的所有行,返回一个字符串数组,数组元素是每一行的内容
/// </summary>
/// <param name="tempFile"></param>
/// <returns></returns>
public static string[] ReadAllLines(string tempFile)
{
string[] strs1 = File.ReadAllLines(tempFile);
// 也可以指定编码方式
string[] strs2 = File.ReadAllLines(tempFile, Encoding.ASCII);
return strs2;
}
/// <summary>
/// 当文本的内容比较大时,我们就不要将文本内容一次性读完,而应该采用流(Stream)的方式来读取内容。
/// .Net为我们封装了StreamReader类,它旨在以一种特定的编码从字节流中读取字符。StreamReader类的方法不是静态方法,所以要使用该类读取文件首先要实例化该类,在实例化时,要提供读取文件的路径。
/// 实例化StreamReader类有很多种方式。
/// </summary>
/// <param name="tempFile"></param>
/// <returns></returns>
public static StreamReader StreamReader(string tempFile)
{
StreamReader result = null;
result = new StreamReader(tempFile);
同样也可以指定编码方式
//result = new StreamReader(tempFile, Encoding.UTF8);
//FileStream fS = new FileStream(tempFile, FileMode.Open, FileAccess.Read, FileShare.None);
//result = new StreamReader(fS);
//result = new StreamReader(fS, Encoding.UTF8);
//FileInfo myFile = new FileInfo(tempFile);
OpenText 创建一个UTF-8 编码的StreamReader对象
//result = myFile.OpenText();
OpenText 创建一个UTF-8 编码的StreamReader对象
//result = File.OpenText(tempFile);
return result;
}
/// <summary>
/// 初始化完成之后,你可以每次读一行,也可以每次读一个字符 ,还可以每次读几个字符,甚至也可以一次将所有内容全部读完
/// </summary>
/// <param name="SR"></param>
/// <returns></returns>
public static string ReadStream(StreamReader SR)
{
// 读一行
string nextLine = SR.ReadLine();
// 读一个字符
int nextChar = SR.Read();
// 读100个字符
int n = 100;
char[] charArray = new char[n];
int nCharsRead = SR.Read(charArray, 0, n);
// 全部读完
string restOfStream = SR.ReadToEnd();
SR.Dispose();
SR.Close();
return restOfStream;
}
#endregion
#region 写入文件
/// <summary>
/// 写文件和读文件一样,如果你要写入的内容不是很多,可以使用File.WriteAllText方法来一次将内容全部写如文件。
/// 如果你要将一个字符串的内容写入文件,可以用File.WriteAllText(FilePath) 或指定编码方式 File.WriteAllText(FilePath, Encoding)方法
/// 使用File.WriteAllText或File.WriteAllLines方法时,如果指定的文件路径不存在,会创建一个新文件;如果文件已经存在,则会覆盖原文件
/// </summary>
/// <param name="str">要写入的字符串</param>
/// <param name="filePath">c:\temp\test\a.txt</param>
/// <returns></returns>
public static bool WriteAllText(string str,string filePath)
{
try
{
//File.WriteAllText(filePath, str);
// 也可以指定编码方式
File.WriteAllText(filePath, str, Encoding.ASCII);
return true;
}
catch (Exception ex)
{
return false;
}
}
/// <summary>
/// 如果你有一个字符串数组,你要把数组的每一个元素作为一行写入文件中,可以用File.WriteAllLines 方法
/// 使用File.WriteAllText或File.WriteAllLines方法时,如果指定的文件路径不存在,会创建一个新文件;如果文件已经存在,则会覆盖原文件
/// </summary>
/// <param name="strs"></param>
/// <param name="filePath"></param>
/// <returns></returns>
public static bool WriteAllLines(string[] strs, string filePath)
{
try
{
File.WriteAllLines(filePath, strs);
// 也可以指定编码方式
File.WriteAllLines(filePath, strs, Encoding.ASCII);
return true;
}
catch (Exception ex)
{
return false;
}
}
/// <summary>
/// 初始化 StreamWriter
/// 当要写入的内容比较多时,同样也要使用流(Stream)的方式写入
/// .Net为我们封装了StreamWriter类,它以一种特定的编码向字节流中写入字符。StreamWriter类的方法同样也不是静态方法,所以要使用该类写入文件首先要实例化该类,实例化StreamWriter类同样有很多方式:
/// </summary>
/// <param name="filePath">文件地址</param>
/// <param name="append">是否追加</param>
/// <returns></returns>
public static StreamWriter StreamWriter(string filePath,bool append)
{
try
{
// 如果文件不存在,创建文件; 如果存在,覆盖文件
StreamWriter sW1 = new StreamWriter(filePath);
// 也可以指定编码方式, true 是 Appendtext, false 为覆盖原文件
StreamWriter sW2 = new StreamWriter(filePath, append, Encoding.UTF8);
// FileMode.CreateNew: 如果文件不存在,创建文件;如果文件已经存在,抛出异常
FileStream fS = new FileStream(filePath, FileMode.CreateNew, FileAccess.Write, FileShare.Read);
StreamWriter sW3 = new StreamWriter(fS);
StreamWriter sW4 = new StreamWriter(fS, Encoding.UTF8);
// 如果文件不存在,创建文件; 如果存在,覆盖文件
FileInfo myFile = new FileInfo(filePath);
StreamWriter sW5 = myFile.CreateText();
return sW2;
}
catch (Exception ex)
{
return null;
}
}
/// <summary>
/// 初始化完成后,可以用StreamWriter对象一次写入一行,一个字符,一个字符数组,甚至一个字符数组的一部分
/// </summary>
/// <param name="str"></param>
/// <param name="sw"></param>
/// <returns></returns>
public static bool SWWrite(string str, StreamWriter sw)
{
try
{
// 写一个字符
sw.Write(str);
// 写一个字符数组
char[] charArray = new char[100];
sw.Write(charArray);
// 写一个字符数组的一部分(10~15)
sw.Write(charArray, 10, 15);
return true;
}
catch (Exception ex)
{
return false;
}
}
#endregion
#region method for Services
/// <summary>
/// 当做操作日志来写
/// </summary>
/// <param name="msg"></param>
/// <returns></returns>
public static bool WriteLog(string msg)
{
var sw = new StreamWriter("C:\\Temp\\log" + DateTime.Now.ToString("yyyyMMdd") + ".txt", true);
sw.Write(DateTime.Now + "-----" + msg + "\r\n");
sw.Dispose();
sw.Close();
return true;
}
#endregion
}
}
- 其中一部分代码为自己的简单记录,主要有方法几个:
- WriteLog(string msg),简单理解为记录操作日志的方法,操作日志需要不断在在文本底下增加数据,因此需要使用到字节流,这样才能实现,使用过后需要及时Dispose,Close 。也可以使用using 进行操作。如:
using (var sw1 = new StreamWriter("C:\\Temp\\log" + DateTime.Now.ToString("yyyyMMdd") + ".txt", true))
{
sw1.Write(DateTime.Now + "-----" + msg + "\r\n");
}
- 方法:ReadLocalFielJson(string tempFile) 可进行每次一部分数据的读取,之前遇到的内存溢出问题就是用这个方法解决,将获取到的字符串通过截取的方式进行分割,或者正则之后将数据取出,并在一定规模后处理完并重新读取,这样可以大大降低内存溢出的风险。
- 先这样吧。