这是我关于读文件的第三个帖子了。现在问题更清楚了一点,主要还是借鉴了第一次发帖时,人家的解答来做的。
现在我要读一个超大的二进制文件大概1G左右,读取了之后要把里面的数据处理一下,并且保存到txt文件中,数据处理没问题,主要是读文件的问题。
1。这么大的文件,肯定不能全部一次读入到内存中去,所以,只能读一部分,处理完了,接下去读取。也就要分快读取数据。
关键代码如下
StatusLabel.Text = "正在读取原始数据";
FileStream fs = new FileStream(openADFile, FileMode.Open,FileAccess.Read);
BinaryReader br = new BinaryReader(fs); int bufferSize = 10240; //每次读取的字节数 每次读取1MB
byte[] buffer = new byte[bufferSize]; long fileLength = fs.Length;//文件流的长度 StreadReader对象没有length方法
int readCount = (int)Math.Ceiling((double)(fileLength / bufferSize)); //需要对文件读取的次数
progressBar.Maximum = readCount;
progressBar.Visible = true;
int readIndex = 0;//当前已经读取的次数
statusStrip.Update();
do
{
buffer = br.ReadBytes(bufferSize);
list.AddRange(buffer);
buffer = null;
///deltData()为处理数据list的递归调用方法,处理过的list会remove一点,只到长度不能符合要求位置,再继续读取一些进去。
deleData();
readIndex++;
progressBar.PerformStep();
progressBar.Invalidate();
GC.Collect();
} while (readIndex < readCount);
br.Close();
fs.Close();
list.Clear();
progressBar.Visible = false;
progressBar.Value = 0;
progressBar.Maximum = 0;
StatusLabel.Text = "读取完成";
statusStrip.Invalidate();
deleData()方法/// <summary>
/// 处理list数据
/// </summary>
/// <param name="list"></param>
private void deleData()
{
if (list.Count >= 86)
{
if (list[0] == 255 && list[85] == 255) ///头尾是否为数据头0XFF
{
if (0 < list[1] && list[1] < 5 && list[2] < 25 && list[2] >= 0)
{
if (list[3] == 80)
{
//判断数据为正确的,保存下来。
createFile(list[1], index, line);
list.RemoveRange(0, 86);
}
else
{
list.RemoveAt(0);
}
}
else
{
list.RemoveAt(0);
}
}
else
{
list.RemoveAt(0);
}
deleData();
}
else
{
return;
}
}createFile()方法 写数据到文本文件中去 /// <summary>
/// 按照设备号,节号创建文件
/// </summary>
/// <param name="group"></param>
/// <param name="index"></param>
private void createFile(int group, int index, float[] line)
{
if (folderName != null)
{
string filename = folderName + "\\" + group + "\\" + (index + 1) + ".log";
try
{
FileStream fi;
if (File.Exists(filename))
{
fi = new FileStream(@filename, FileMode.Append);
}
else
{
fi = new FileStream(@filename, FileMode.Create);
} using (StreamWriter w = new StreamWriter(fi))
每次都是这个地方报错,如果buffersize设置的太大的话会爆一个StackOverflowException,如果设置小了,运行了一段时间又会爆一个ContextSwtichDeadlock错误,
{
for (int i = 0; i < line.Length; i++)
{
w.Write(line[i] + ",");
}
w.WriteLine();
w.Flush();
w.Close();
fi.Close();
}
PlusNum(group, index);
}
catch (Exception ex)
{
port.errorData(ex.Message);
MessageBox.Show(ex.Message);
}
counter++;
}
}这里的buffersize表示一次读取的字节数,我如果设置成1024的话,那就是每次读取1KB,要是这样读的话,1G的文件处理起来非常慢。我都等不下去了,如果把buffersize改大一点,我想每次读取1MB,本来1MB,我想应该不算大的,deleData()方法里面会调用createFile()里面写文件的StreamWrite会报错。StackOverflowException。
现在我要读一个超大的二进制文件大概1G左右,读取了之后要把里面的数据处理一下,并且保存到txt文件中,数据处理没问题,主要是读文件的问题。
1。这么大的文件,肯定不能全部一次读入到内存中去,所以,只能读一部分,处理完了,接下去读取。也就要分快读取数据。
关键代码如下
StatusLabel.Text = "正在读取原始数据";
FileStream fs = new FileStream(openADFile, FileMode.Open,FileAccess.Read);
BinaryReader br = new BinaryReader(fs); int bufferSize = 10240; //每次读取的字节数 每次读取1MB
byte[] buffer = new byte[bufferSize]; long fileLength = fs.Length;//文件流的长度 StreadReader对象没有length方法
int readCount = (int)Math.Ceiling((double)(fileLength / bufferSize)); //需要对文件读取的次数
progressBar.Maximum = readCount;
progressBar.Visible = true;
int readIndex = 0;//当前已经读取的次数
statusStrip.Update();
do
{
buffer = br.ReadBytes(bufferSize);
list.AddRange(buffer);
buffer = null;
///deltData()为处理数据list的递归调用方法,处理过的list会remove一点,只到长度不能符合要求位置,再继续读取一些进去。
deleData();
readIndex++;
progressBar.PerformStep();
progressBar.Invalidate();
GC.Collect();
} while (readIndex < readCount);
br.Close();
fs.Close();
list.Clear();
progressBar.Visible = false;
progressBar.Value = 0;
progressBar.Maximum = 0;
StatusLabel.Text = "读取完成";
statusStrip.Invalidate();
deleData()方法/// <summary>
/// 处理list数据
/// </summary>
/// <param name="list"></param>
private void deleData()
{
if (list.Count >= 86)
{
if (list[0] == 255 && list[85] == 255) ///头尾是否为数据头0XFF
{
if (0 < list[1] && list[1] < 5 && list[2] < 25 && list[2] >= 0)
{
if (list[3] == 80)
{
//判断数据为正确的,保存下来。
createFile(list[1], index, line);
list.RemoveRange(0, 86);
}
else
{
list.RemoveAt(0);
}
}
else
{
list.RemoveAt(0);
}
}
else
{
list.RemoveAt(0);
}
deleData();
}
else
{
return;
}
}createFile()方法 写数据到文本文件中去 /// <summary>
/// 按照设备号,节号创建文件
/// </summary>
/// <param name="group"></param>
/// <param name="index"></param>
private void createFile(int group, int index, float[] line)
{
if (folderName != null)
{
string filename = folderName + "\\" + group + "\\" + (index + 1) + ".log";
try
{
FileStream fi;
if (File.Exists(filename))
{
fi = new FileStream(@filename, FileMode.Append);
}
else
{
fi = new FileStream(@filename, FileMode.Create);
} using (StreamWriter w = new StreamWriter(fi))
每次都是这个地方报错,如果buffersize设置的太大的话会爆一个StackOverflowException,如果设置小了,运行了一段时间又会爆一个ContextSwtichDeadlock错误,
{
for (int i = 0; i < line.Length; i++)
{
w.Write(line[i] + ",");
}
w.WriteLine();
w.Flush();
w.Close();
fi.Close();
}
PlusNum(group, index);
}
catch (Exception ex)
{
port.errorData(ex.Message);
MessageBox.Show(ex.Message);
}
counter++;
}
}这里的buffersize表示一次读取的字节数,我如果设置成1024的话,那就是每次读取1KB,要是这样读的话,1G的文件处理起来非常慢。我都等不下去了,如果把buffersize改大一点,我想每次读取1MB,本来1MB,我想应该不算大的,deleData()方法里面会调用createFile()里面写文件的StreamWrite会报错。StackOverflowException。
解决方案 »
- 结构体如何循环赋值?
- C# 死循环问题
- windows installer问题
- 怎么枚举接口的成员(如:属性)???
- C#,dataset
- 高手看看微软的这段关于TabControl的帮助,个人觉得TabControl写得很垃圾
- 如何让DataGridBoolColumn 在每个单元格中只包含两个状态的复选框即:已选中(true)、未选中(false),而没有和 DBNull.Value?
- 如何使用程序设置IIS虚拟目录的权限,不允许anonymous访问
- 高分请教能用c#做一个承载窗口,然后里面运行别的程序嘛?
- 数据库查询返回值
- windows usercontrol
- BS程序中怎么即时监听用户是不是在线?
C# 读取超大文本文件(2G左右),求解决办法!
http://topic.csdn.net/u/20101217/13/c2396c5a-4cc1-4a17-8b3d-7db317f39c58.html
关于C#读取二进制文件,以及怎么处理数据,给点意见。
http://topic.csdn.net/u/20110104/14/1554dc50-adf2-45a0-a79b-71dad9754ac1.html?seed=1951352104&r=71020225#r_71020225
你试下,不在调试状态下运行是否会出错....
你也可以尝试着把createFile中的FileStream放在全局变量里,在
do 上面Open一次
{
} while (readIndex < readCount);
下面Close一次
就是这样的啊,我读取文件的时候,firestream是放在do..while()外面的啊,只是在dowhile调用的方法里面有写文件的方法。。
BinaryReader br = new BinaryReader(fs); int bufferSize = 10240; //每次读取的字节数 每次读取1MB
byte[] buffer = new byte[bufferSize]; long fileLength = fs.Length;//文件流的长度 StreadReader对象没有length方法
int readCount = (int)Math.Ceiling((double)(fileLength / bufferSize)); //需要对文件读取的次数
progressBar.Maximum = readCount;
progressBar.Visible = true;
int readIndex = 0;//当前已经读取的次数
statusStrip.Update();
do
{
buffer = br.ReadBytes(bufferSize);
list.AddRange(buffer);
buffer = null;
///deltData()为处理数据list的递归调用方法,处理过的list会remove一点,只到长度不能符合要求位置,再继续读取一些进去。
deleData();
readIndex++;
progressBar.PerformStep();
progressBar.Invalidate();
GC.Collect();
} while (readIndex < readCount);
br.Close();
fs.Close();
我就是这样的额,deleData()里面还会调用方法去执行写文件的操作