c#编程-C#中Parallel.For并行处理中读取文件时出现的错误

问题描述

C#中Parallel.For并行处理中读取文件时出现的错误

1、读取“d:/users/v-lingao/from_lei/wordsegmentation/testdata”目录下的所有txt文档,利用Parallel.For并行处理各个txt文档中的内容,每次读取一行存储到string line中,利用line = sr.ReadLine() (StreamReader sr); 没处理一行也入“d:/users/v-lingao/from_lei/wordsegmentation/testdata1”目录下新创建的对应的txt文件中。方法ComputeIDF()实现次功能。

2、读取在“d:/users/v-lingao/from_lei/wordsegmentation/testdata1”目录下创建的txt文件,利用Parallel.For并行处理每个txt文档中的内容,类似于ComputeIDF()方法,利用line = sr.ReadLine().。法ComputingTfIdf()实现此功能。错误也就出现在此方法中,错误提示根据写入文件时编码方式的不同有所改变。

部分代码如下所示:

public static Dictionary ComputeIDF(List stopWordsList)
{
DirectoryInfo di = new DirectoryInfo(@"d:/users/v-lingao/from_lei/wordsegmentation/testdata");
FileInfo[] ff = di.GetFiles("*.txt");
Dictionary featureDoc = new Dictionary();

        Parallel.For(0, ff.Length, (part) =>
        {
            FileInfo file = ff[part];
            Dictionary<string, int> featureFile = new Dictionary<string,int>();
            string name = file.Name.Substring(file.Name.LastIndexOf("\") + 1);
            string path = Path.Combine(@"d:/users/v-lingao/from_lei/wordsegmentation/testdata1", name);
            FileStream aFile = new FileStream(path, FileMode.Create);
            StreamWriter sw = new StreamWriter(aFile, Encoding.UTF8);
            int lineCount = 0;
            char[] charArray = new char[] { ' ' };
            StreamReader sr = new StreamReader(file.OpenRead(),Encoding.UTF8);
            string line = sr.ReadLine();
            while (line != null)
            {
?    ?    ?    ?    ?    ?//部分代码省略
?    ?    ?    ?    ??lineCount++;
                sw.Write(lineCount);
                foreach (KeyValuePair<string, int> keyvalue in featureLine)
                {
                   sw.Write(' ' + keyvalue.Key + ':' + (0.5 + 0.5 * ((float)keyvalue.Value / maxCount)));
                 }
                 sw.WriteLine();
                 line = sr.ReadLine();
            }
                //combine the featureFiles into featureDoc without repeating
                featureDoc.Add(featurename, featureFile[featurename]);
                sr.Close();
                sw.Close();
        });
        Dictionary<string, float> idf = new Dictionary<string, float>();
        foreach (KeyValuePair<string, int> keyvalue in featureDoc)
        {
            idf.Add(keyvalue.Key, (float)Math.Log10((float)sumLine / (float)keyvalue.Value));
        }
        return idf;
    }

这个方法没有问题。接下来是ComputingTfIdf(idf),问题出在这个方法中。
public static void ComputingTfIdf(Dictionary idf)
{
DirectoryInfo dir = new DirectoryInfo(@"d:/users/v-lingao/from_lei/wordsegmentation/testdata1");
FileInfo[] ff = dir.GetFiles("*.txt");
StreamReader sr;

        Parallel.For(0, ff.Length, (part) =>
        {
            FileInfo file = ff[part];
            List<string> idfList = new List<string>();
            idfList.AddRange(idf.Keys);
            int linenum = 0;
            sr = new StreamReader(file.OpenRead(),Encoding.UTF8);
            char[] charArray = new char[] { ' ' };
            char[] charArray1 = new char[] { ':' };

            string name = file.Name.Substring(file.Name.LastIndexOf("\") + 1);
            string path = Path.Combine(@"d:/users/v-lingao/from_lei/wordsegmentation/idfdata", name);
            FileStream aFile = new FileStream(path, FileMode.Create);
            StreamWriter sw = new StreamWriter(aFile, Encoding.UTF8);
             ** *string line = sr.ReadLine();* **    //这行有时也会出错
            while (line != null)
            {
                linenum++;
                string[] words = line.Split(charArray);
                int i = 1;
                foreach (string word in words)
                {
                    if (i == 1)
                    {
                        sw.Write(word + ' ');
                        i++;
                    }
                    else
                    {
                        string[] wds = word.Split(charArray1);
                        if (wds.Length == 2)
                        {
                            string key = wds[0];
                            if (idf.Keys.Contains(key))
                            {
                                double tfidf = (double)idf[key] * (Convert.ToDouble(wds[1]));
                                sw.Write(idfList.IndexOf(key)+ ':'+tfidf +' ');
                            }
                        }
                    }
                }
                sw.WriteLine();
                 ** *line = sr.ReadLine();* **   //问题常常出现在这行
                }
            }
            sw.Close();
        });
    }

错误提示根据写入文件时编码方式的不同有所改变。当读取、写入文件用UTF8或者Unicode时,写入和读取的都是乱码,并且line = sr.ReadLine()出错,错误提示为: ** The output char buffer is too small to contain the decoded characters, encoding 'Unicode (UTF-8)' fallback 'System.Text.DecoderReplacementFallback' **
很是无语,功能相同的代码,为什么ComputeIDF()方法中line = sr.ReadLine()就不出错。我将编码换成Encoding.GetEncoding("GBK")读写文件不会出现乱码,但line = sr.ReadLine()还是出错,相当无语!
还有就是当不用并行处理Parallel.For,而是用for循环时也不出错。
求大侠帮忙,不胜感激!

解决方案

问题在朋友的帮助下已经解决,很感谢我的朋友!
现在把结果和大家分享下,希望遇到类似问题的同仁能从中有所启发。
用并行处理Parallel.For,要特别注意局部变量的位置。在我的代码中sr是在Parallel.For结构外面定义的,这样在执行的过程中几个线程会共享一个sr,最终导致异常的产生。

时间: 2024-09-19 09:47:33

c#编程-C#中Parallel.For并行处理中读取文件时出现的错误的相关文章

qt txt文件 中文 乱码-Qt5中用QTextStream向txt文件中写入中文字符串,打开文件时出现乱码

问题描述 Qt5中用QTextStream向txt文件中写入中文字符串,打开文件时出现乱码 在网上查了一些关于Qt中文乱码的问题,主要是因为机器的编码问题QTextCodec::setCodecForLocale(QTextCodec::codecForName(""GBK""));QTextCodec::setCodecForCStrings(QTextCodec::codecForName(""GBK"")); QText

mediaplayer-android中MediaPlayer播放M3U8格式本地文件时,网络权限被禁止,仅在小米3,4上有

问题描述 android中MediaPlayer播放M3U8格式本地文件时,网络权限被禁止,仅在小米3,4上有 最近用Vitamio的Mediaplayer开发一款视频播放软件,在小米3和小米4上出现本地视频无法播放的问题:具体为: 当关闭小米3.4的移动网络和wifi之后,使用mediaplayer播放器播放已下载的视频会出现VitamioPlayer: error (1, -5),并且出现网络权限被拒的提示(注:联网权限都已经在manifest中注册)如下图错误提示: 当wifi和移动网络打

实例-跪求大神啊,VB中dwgthumb控件打开DWG文件时需要设置什么参数

问题描述 跪求大神啊,VB中dwgthumb控件打开DWG文件时需要设置什么参数 VB中dwgthumb控件打开DWG文件时需要设置什么参数,用没用实例呢,谢谢啊,大神 解决方案 http://www.newxing.com/Code/VB/TXCL/dwg_462.htmlhttp://download.csdn.net/detail/dirk2212/4197363http://download.csdn.net/download/dirk2212/4198022http://www.edu

在键盘钩子中对lParam进行Marshal.PtrToStructure类型转换时发生“内存保护”错误。

问题描述 键盘信息类:[StructLayout(LayoutKind.Sequential)]publicstructKeyBoardHookStruct{publicintvkCode;publicintscanCode;publicintflags;publicinttime;publicintdwExtraInfo;}在键盘钩子函数privateintKeyboardHookProc(intnCode,Int32wParam,IntPtrlParam)中进行KeyBoardHookStr

解决-从linux服务器中读取文件数据

问题描述 从linux服务器中读取文件数据 现有一个需求: 在一台服务器上写日志文件,每当日志文件写到一定大小时,比如是1G,会将这个日志文件改名成另一个名字,并新建一个与原文件名相同的日志文件,再往这个新建的日志文件里写数据:要求写一个程序能实时地读取日志文件中的内容,并且不能写日志操作.重命名操作.不能修改日志文件的任何数据,保持日志文件的完整性. 首先,这个问题在windows下几乎无解,因为一个程序打开了一个文件,再要对文件重命名是不可能的:而在Linux下,可以得到完美解决.因为Lin

linux下shell中for循环实现读取文件换行

一.问题与需求: 比如有一个aa.list文件内容是: 1    2    3    4    a    b    c    d for脚本读取文件时,我想是一行一行的读入,每次循环读取一行,像第一次是1 2 3 4,第二次是a b c d 但是我这样写 for i in "$(< ./aa.list)" do     echo $i     echo 1111 done 得到结果是:  1 11111 2 11111 3 11111 4 11111 a 11111 b 1111

控件-asp.net中fileupload上传&amp;amp;gt;2G的文件时程序如何不蹦

问题描述 asp.net中fileupload上传>2G的文件时程序如何不蹦 在asp.net中,用fileupload控件上传大于2G文件时,程序自动就崩了,我已经在webconfig中设置了最大上传容量为2G,后台代码程序也提示了<2G,可是根本没提示文件过大,各位大神是什么原如何提示出文件过大因,求帮忙! 解决方案 超过服务器进程的内存上限了,另外文件上传后才知道有多大. 这么大的文件,建议部署activex分块上传. 解决方案二: 试试这个acx:http://www.cnblogs.

从linux服务器中读取文件数据

问题描述 现有一个需求:在一台服务器上写日志文件,每当日志文件写到一定大小时,比如是1G,会将这个日志文件改名成另一个名字,并新建一个与原文件名相同的日志文件,再往这个新建的日志文件里写数据:要求写一个程序能实时地读取日志文件中的内容,并且不能写日志操作.重命名操作.不能修改日志文件的任何数据,保持日志文件的完整性.首先,这个问题在windows下几乎无解,因为一个程序打开了一个文件,再要对文件重命名是不可能的:而在Linux下,可以得到完美解决.因为Linux的文件系统有别于windows,L

一起谈.NET技术,.Net4.0 Parallel编程(二)Data Parallelism 中

在上篇文章中看过了使用Parrallel.For.Parael.Foreach在效率上给我们带来的提高.本文就来如何终止循环.线程局部变量 进行说明. Thread-Local Variables 首先我们来看下线程局部变量,是的我们也许一直在想我们如何去定义一个线程局部变量呢.先看段顺序执行的代码: [TestMethod()]public void NormalSequenceTest(){int[] nums = Enumerable.Range(0, 1000000).ToArray()