C#文件的操作
在文件中,存储的是字节的方式即:byte
1、读文件,在读文件时,先用字节的方式读出来。然后转换成字符的形式:
Decoder d = Encoding.UTF8.GetDecoder();
d.GetChars(byData, 0, byData.Length, charData, 0);
这里先通过变量Decoder的这个方式。
以下是读文件的整体代码:
byte[] byData = new byte[200]; char[] charData = new char[200]; try { FileStream aFile = new FileStream("../../Program.cs", FileMode.Open); aFile.Seek(113, SeekOrigin.Begin); aFile.Read(byData, 0, 200); } catch (System.Exception ex) { Console.WriteLine("An IO exception has been thrown"); Console.WriteLine(ex.ToString()); Console.ReadKey(); return; } Decoder d = Encoding.UTF8.GetDecoder(); d.GetChars(byData, 0, byData.Length, charData, 0); Console.WriteLine(charData);
2、写文件,在写文件的时候,先将字符转换成字节的方式,然后再存进文件中。
Encoder e = Encoding.UTF8.GetEncoder();
e.GetBytes(charData, 0, charData.Length, byData, 0, true);
这里跟读文件的差不多,只是先通过Encoder的方式,而读文件是同多Decoder的方式。
以下是写文件的整体代码
byte[] byData; char[] charData; try { FileStream aFile = new FileStream("Temp.txt", FileMode.Create); charData = "xiaoln you are".ToCharArray(); byData = new byte[charData.Length]; Encoder e = Encoding.UTF8.GetEncoder(); e.GetBytes(charData, 0, charData.Length, byData, 0, true); aFile.Seek(0, SeekOrigin.Begin); aFile.Write(byData, 0, byData.Length); aFile.Close(); } catch (System.Exception ex) { Console.WriteLine("An IO Exception"); Console.WriteLine(ex.ToString()); Console.ReadKey(); return; }
3、读文件,通过StreamReader的方式进行读取。
首先,试用FileStream的方式打开一个文件,FileMode.Open的方式。
//string strLine; try { FileStream aFile = new FileStream("Log.txt", FileMode.Open); StreamReader st = new StreamReader(aFile); //strLine = st.ReadLine(); //while (strLine != null) //{ // Console.WriteLine(strLine); // strLine = st.ReadLine(); //} int nChar; nChar = st.Read(); while (nChar != -1) { Console.Write(Convert.ToChar(nChar)); nChar = st.Read(); } st.Close();
在读取文件有两种方式,一种是通过整行的读取(代码中的被注释掉)。另一种方式是通过一个字符一个字符的读取。当文件为空的时候,返回-1
4、写文件,通过StreamWriter的方式进行写入。
首先使用FileStream的方式打开一个文件,FileMode.OpenOrCreate的方式。
FileStream aFile = new FileStream("Log.txt", FileMode.OpenOrCreate); StreamWriter sw = new StreamWriter(aFile); bool truth = true; sw.WriteLine("Hello to you."); sw.WriteLine("It is now {0} and ", DateTime.Now.ToLongDateString()); sw.Write("More than that"); sw.Write("it's {0} that C# is fun", truth); sw.Close();
这里有一个地方用到了读取当前的时间,DateTime.Now.ToLongDateString()将时间转换成标准字符串的格式。
5、读取类似于CSV格式的数据,以逗号隔开的文件。
这里首先介绍GetData函数。
在每一行中,先将每个字段提取出来(都是以逗号为分隔符)。可以通过List<Dictionary<string, string>> data
columns = new List<string>();
将读取出来的文件,存放在stringArray中,通过stringArray = line.Split(charArray);这里的charArray是char[] charArray = new char[] { ',' };即逗号
然后将读取到的字符串数组放到out List<string> columns中。
for (int x = 0; x <= stringArray.GetUpperBound(0); ++x)
columns.Add(stringArray[x]);
这里的stringArray.GetUpperBound(0)是指一维的维度是多大。当为三个字符数组大小的时候,则stringArray.GetUpperBound(0) == 2.
同理,可进行其他的操作。
以下是完整的GetData函数的代码
private static List<Dictionary<string, string>> GetData(out List<string> columns) { string line; string[] stringArray; char[] charArray = new char[] { ',' }; List<Dictionary<string, string>> data = new List<Dictionary<string, string>>(); columns = new List<string>(); try { FileStream aFile = new FileStream(@"..\..\SomeData.txt", FileMode.Open); StreamReader sr = new StreamReader(aFile); line = sr.ReadLine(); stringArray = line.Split(charArray); for (int x = 0; x <= stringArray.GetUpperBound(0); ++x) columns.Add(stringArray[x]); line = sr.ReadLine(); while (line != null) { stringArray = line.Split(charArray); Dictionary<string, string> dataRow = new Dictionary<string, string>(); for (int x = 0; x <= stringArray.GetUpperBound(0); ++x) dataRow.Add(columns[x], stringArray[x]); data.Add(dataRow); line = sr.ReadLine(); } sr.Close(); return data; } catch (System.Exception ex) { Console.WriteLine("An IO Exception"); Console.WriteLine(ex.ToString()); Console.ReadLine(); return data; } }
接下去是对提取到的数据进行显示。以下是整个main函数的代码
List<string> columns; List<Dictionary<string, string>> myData = GetData(out columns); foreach (string column in columns) { Console.Write("{0, -20}", column); } Console.WriteLine(); foreach (Dictionary<string, string> row in myData) { foreach (string column in columns) { Console.Write("{0, -20}", row[column]); } Console.WriteLine(); }
在这里为了显示的方面,用了格式化{0, -20},即左对齐,每一项占20个空格。
下面是SomeData.txt的内容
Product ID,Name,Price 1,Spiky Pung,1000 2,Gloop Galloop Soup,25 4,Hat Sauce,12
6、在查找文件的位置的时候,可以用Seek的方式进行查找。
FileStream aFile = File.OpenRead("Data.txt"); aFile.Seek(8, SeekOrigin.Begin); aFile.Seek(2, SeekOrigin.Current); aFile.Seek(-5, SeekOrigin.End);
7、数据的压缩存储
1、对数据进行压缩存储。
首先创建一个FileStream对象,并通过fileStream对象创建GZipStream对象。然后使用CompressionMode.Compress没劲指定数据进行压缩操作。
同理对数据的解压也是一样。
static void SaveCompressedFile(string filename, string data) { FileStream fileStream = new FileStream(filename, FileMode.Create, FileAccess.Write); GZipStream compressionStream = new GZipStream(fileStream, CompressionMode.Compress); StreamWriter writer = new StreamWriter(compressionStream); writer.Write(data); writer.Close(); } static string LoadCompressedFile(string filename) { FileStream fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read); GZipStream compressionStream = new GZipStream(fileStream, CompressionMode.Decompress); StreamReader reader = new StreamReader(compressionStream); string data = reader.ReadToEnd(); reader.Close(); return data; }
对传入的sourceString进行添加数据等操作。
string filename = "compressedFile.txt"; Console.WriteLine("Enter a string to compress"); string sourceString = Console.ReadLine(); StringBuilder sourceStringMultiplier = new StringBuilder(sourceString.Length * 100); for (int i = 0; i < 100; ++i ) { sourceStringMultiplier.Append(sourceString); } sourceString = sourceStringMultiplier.ToString(); Console.WriteLine("Source data is {0} bytes long", sourceString.Length); SaveCompressedFile(filename, sourceString); Console.WriteLine("\nData saved to {0}", filename); FileInfo compressedFileData = new FileInfo(filename); Console.WriteLine("Compressed fie is {0} bytes long", compressedFileData.Length); string recoveredString = LoadCompressedFile(filename); recoveredString = recoveredString.Substring(0, recoveredString.Length / 100); Console.WriteLine("\n recovered data: {0}", recoveredString);
在这里会有一个疑问就是,使用了string的sourceString之后,为什么还要中间用StringBuilder进行Append之后,再进行对sourceString赋值。可以参考这里的链接http://www.cnblogs.com/tonysuen/archive/2010/03/04/1678447.html