C# 字节流 与 StreamReader 读取 Json 格式文件内容并处理的函数
读取并处理Json格式数据文件的两种读取方法:
方法一:以字节流的方式读取并处理
public static bool WriteByToken(string fileName, string token, string val, Encoding coder)
{
if (!File.Exists(fileName))
return false;
//string jsonText = File.ReadAllText(fileName); // 若不是频繁操作同一文件,则用此函数直接读取即可
FileStream stream = null;
JObject jsObj = null;
try
{
stream = File.Open(fileName, FileMode.Open,FileAccess.ReadWrite, FileShare.ReadWrite);
byte[] buffer = new byte[stream.Length];
stream.Read(buffer, 0, (int)stream.Length);
string jsonText = coder.GetString(buffer);
jsObj = JObject.Parse(jsonText);
JToken tokenNode = jsObj.SelectToken(token);
tokenNode.Replace(val);
byte[] writeBuffer = coder.GetBytes(JsonConvert.SerializeObject(jsObj, Formatting.Indented));
stream.Seek(0, SeekOrigin.Begin);
stream.SetLength(0); // 在写入新的内容之前,用 SetLength(0) 清空文件内容,防止由于 stream 的长度不等于writeBuffer.Length 导致后续保存后文件中出现额外字符
stream.Write(writeBuffer, 0, writeBuffer.Length);
stream.Flush();
stream.Close();
stream = null;
GC.Collect(); // 强制对资源进行回收,主要是防止由于频繁调用此函数操作同一文件,导致句柄来不及释放
//File.WriteAllText(fileName, JsonConvert.SerializeObject(jsObj, Formatting.Indented));// 若不是频繁操作同一文件,则用此函数直接写入即可
}
catch (JsonReaderException ex)
{
return false;
}
catch (Exception ex)
{
return false;
}
finally
{
if (stream != null)
{
stream.Close();
stream = null;
}
}
return true;
}
方法二:以 StreamReader
读取并处理
public static bool WriteByToken(string fileName, string token, float val, Encoding coder)
{
if (!File.Exists(fileName))
return false;
string jsonText = string.Empty;
FileStream fs = null;
StreamReader sr = null;
StreamWriter writer = null;
try
{
fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
sr = new StreamReader(fs, coder);
jsonText = sr.ReadToEnd();
sr.Close();
fs.Close();
JObject jsObj = JObject.Parse(jsonText);
JToken tokenNode = jsObj.SelectToken(token);
tokenNode.Replace(val);
fs = new FileStream(fileName, FileMode.Truncate, FileAccess.Write, FileShare.ReadWrite);
writer = new StreamWriter(fs);
writer.Write(JsonConvert.SerializeObject(jsObj, Formatting.Indented));
writer.Flush();
writer.Close();
fs.Close();
}
catch (JsonReaderException)
{
return false;
}
catch (Exception ex)
{
return false;
}
finally
{
if (sr != null)
{
sr.Close();
sr = null;
}
if (fs != null)
{
fs.Close();
fs = null;
}
if (writer != null)
{
writer.Close();
writer = null;
}
}
return true;
}
对比:
- 文件读取方式:
- 第一种方法:手动处理字节流,可能需要额外处理编码和字符集,适合于需要字节级操作或特殊编码需求的情况。
- 第二种方法:使用 StreamReader 是一种更高层次的读取方式,它简化了字符编码和流的处理,通常更适用于文本文件的读取。它可以自动处理字符集,更方便。
- 文件写入方式:
- 第一种方法:直接操作文件流的字节内容,灵活性较高,但是相对而言稍微复杂一些,需要手动管理文件位置和写入字节数组。没有清晰的字符流管理,可能在字符集编码方面稍显麻烦。
- 第二种方法:使用 StreamWriter 进行写入,它是字符流的包装类,适合处理文本文件,简化了写入过程,尤其是字符编码和字符转换等问题。
- 资源管理:
- 第一种方法:资源管理比较粗糙,虽然它会在 finally 块中关闭流,但强制垃圾回收(GC.Collect())是比较危险的做法,可能导致性能下降。通常不建议手动调用垃圾回收器。
- 第二种方法:通过 Dispose() 释放资源,符合 .NET 的标准做法,并且它处理了流和其他对象的资源管理。这样可以确保资源得到及时释放,避免资源泄漏。
- 代码可读性和维护性:
- 第一种方法:代码较为复杂且不容易维护,因为需要手动管理字节流、文件位置、字符编码等细节,增加了出错的风险。
- 第二种方法:代码更清晰,使用 StreamReader 和 StreamWriter 简化了读取和写入操作,维护起来相对容易。
- 性能考虑:
- 第一种方法:对于较大的文件,字节流的处理可能更高效,因为它避免了中间的字符转换操作。
- 第二种方法:对大文件的处理可能稍慢,特别是如果涉及字符编码转换等操作,但对于一般文本文件来说性能足够好。