java中啥情况下会发生io异常

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java中啥情况下会发生io异常相关的知识,希望对你有一定的参考价值。

比如文件不存在、读取的文件流、网络流字符有问题都会导致 参考技术A 查看API IOException 发现IOException的直接子类
ChangedCharSetException,
CharacterCodingException,
CharConversionException,
ClosedChannelException,
EOFException,
FileLockInterruptionException,
FileNotFoundException, FilerException,
HttpRetryException, IIOException, InterruptedIOException, InvalidPropertiesFormatException,
JMXProviderException,
JMXServerErrorException,
MalformedURLException, ObjectStreamException, ProtocolException, RemoteException, SaslException, SocketException, SSLException, SyncFailedException, UnknownHostException, UnknownServiceException,
UnsupportedDataTypeException,
UnsupportedEncodingException,
UTFDataFormatException, ZipException
每一种异常都对应着相应的情况,对照API好好学习一下
参考技术B 一般对文件进行处理应该说与io流发生联系的都会

处理后台线程时出现“集合发生变异...”的异常情况

【中文标题】处理后台线程时出现“集合发生变异...”的异常情况【英文标题】:Unusual case of "collection was mutated..." while processing background thread 【发布时间】:2014-03-26 17:50:56 【问题描述】:

我正在尝试使用完成处理程序从后台线程上的文本文件加载数据,该完成处理程序将在我使用正则表达式处理数据后写出一个 plist。我收到“枚举时集合发生突变”错误,但我不确定为什么在这种情况下会抛出它。我正在使用块和后台线程。所以我假设我犯了一个逻辑错误,但我不明白为什么:

    可变数组的计数在断点处不一致(发生错误的地方) 在某一时刻,该过程确实正确完成(填充了 data.plist 文件) 当我在归档之前尝试使用可变数组的副本时,我 收到“尝试插入 nil 对象”错误,但此时原始 nsmutablearray 计数似乎有效(请参阅更新)

有趣的是,由于计数不一致和(在某一时刻)成功完成,我认为我的后台处理可能是罪魁祸首。

下面是 DataManager 类的 init 方法的一部分:

if ( !abcMutableArray )
        abcMutableArray = [[NSMutableArray alloc] init];

    NSFileManager *fileManager = [NSFileManager defaultManager];

    // If the plist file doesn't exist in the Documents Folder, create it from the text file
    if ( ![fileManager fileExistsAtPath:[self filePath]] ) 

        [self createDataFile];

     

这里是辅助方法

- (void) createDataFile

    __weak DataManager* weakSelf = self;

    [weakSelf loadData:^(BOOL completed)
        if(completed)
        

            //Next line produces **Collection <__NSArrayM: 0x8fa28c0> was mutated while being enumerated**
            NSData* data = [NSKeyedArchiver archivedDataWithRootObject:[weakSelf abcMutableArray]];
            [data writeToFile:[weakSelf filePath] atomically:YES];
        
    ];


此方法执行加载,完成后将完成调用传回给调用者

- (void) loadData:(void (^)(BOOL))completed


    __weak DataManager* weakSelf = self;

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^

        NSError *localError = NULL;
        NSStringEncoding fileEncoding = NSUTF8StringEncoding;
        NSURL* fileURL = [[NSBundle mainBundle] URLForResource:@"data" withExtension:@"txt"];
        NSString* fh= [NSString stringWithContentsOfURL:fileURL usedEncoding:&fileEncoding error:&localError];

        for (NSString *line in [fh componentsSeparatedByString:@"\n"]) 

            if ( ![line hasPrefix:@"#"] )
            
            //      [self parseLine:line];

                //parsing routine
                NSError *error = NULL;

                Thing* t = [[Thing alloc]init];

                NSString* pattern = @"(^.*)\\s(.*)\\s\\[(.*)\\]\\s\\/(.*)\\;\\s(.*)";

                NSRegularExpression *regEx = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionCaseInsensitive error:&error];

                NSArray *matches = [regEx matchesInString:line
                                                  options:0
                                                    range:NSMakeRange(0, [line length])];

                for (NSTextCheckingResult *match in matches) 

                    if ([match numberOfRanges] == 6) 

                        //The range at index 0 contains the entire string.
                        thing.a = (NSString*)[line substringWithRange:[match rangeAtIndex:1]];

                        thing.b = (NSString*)[line substringWithRange:[match rangeAtIndex:2]];

                        thing.c = (NSString*)[line substringWithRange:[match rangeAtIndex:3]];

                        thing.d = (NSString*)[line substringWithRange:[match rangeAtIndex:4]];

                        thing.e = (NSString*)[[[line substringWithRange:[match rangeAtIndex:5]]stringByReplacingOccurrencesOfString:@"/" withString:@". "] stringByReplacingOccurrencesOfString:@".." withString:@"."];

                        [[weakSelf abcMutableArray] addObject:thing];

                     //end-if match

                 //end-for matches

             //end-if line

         //end-for lines

        //file load data process is completed
        completed(YES);
    );


更新

尝试按照建议将复制方法添加到代码中时:

NSData* data = [NSKeyedArchiver archivedDataWithRootObject:[[weakSelf abcMutableArray]copy]];

我在同一断点处收到以下错误。

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSPlaceholderArray initWithObjects:count:]: attempt to insert nil object from objects[12]'

请注意,当我在上面的 NSData 行中断时,我可以看到 abcMutableArray 包含可变数量的对象(每个周期中的对象数量不同,这使我相信我的后台线程尚未完成处理)。

【问题讨论】:

【参考方案1】:

变化:

NSData* data = [NSKeyedArchiver archivedDataWithRootObject:[weakSelf abcMutableArray]];

收件人:

NSData* data = [NSKeyedArchiver archivedDataWithRootObject:[[weakSelf abcMutableArray] copy]];

这将传入数组的副本,因此不可能对其进行变异。

【讨论】:

好建议,但是,当反复测试时,有时会抛出 *** Terminating app due to unaught exception 'NSInvalidArgumentException', reason: '*** -[__NSPlaceholderArray initWithObjects:count:]: 尝试插入来自对象[2443]'的零对象' |我的测试步骤是执行,见data.plist,删除data.plist,执行|想知道我的后台任务有时是否未完成? 我最终使用了这种方法,我确定我的其他问题与线程有关。

以上是关于java中啥情况下会发生io异常的主要内容,如果未能解决你的问题,请参考以下文章

java.sql.SQLException: Io 异常: Broken pipe 如何在不重启的情况下恢复?

java.io 上的 FileNotFound(访问被拒绝)异常

java的异常和java web容器的异常

JavaSE-异常机制File类IO流

怎么处理Java中的异常

java.sql.SQLException:Io 异常:套接字读取超时与关闭连接