首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >从多个线程写入文件

从多个线程写入文件
EN

Stack Overflow用户
提问于 2012-02-16 22:11:26
回答 3查看 3.7K关注 0票数 7

我正在用Objective-C编写一个下载管理器,它可以同时从多个段下载文件,以提高速度。文件的每个段都是以线程的形式下载的。

一开始,我想将每个片段写在不同的文件中,并在下载结束时将所有文件放在一起。但由于许多原因,这不是一个好的解决方案。

因此,我正在寻找一种在特定位置写入文件的方法,这种方法能够处理多线程,因为在我的应用程序中,每个段都是在线程中下载的。在Java语言中,我知道FileChannel完美地完成了这项工作,但在Objective-C中我却一无所知。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-02-17 01:04:00

永远不要忘记,Obj-C基于普通的C,因此我只需要编写一个自己的类,它使用标准C API处理文件I/O,它允许您将当前写入位置放在新文件中的任何位置,甚至远远超出当前文件的大小(缺少的字节由零字节填充),还可以随意向前和向后跳转。实现线程安全的最简单方法是使用锁,这不是最快的方法,但在您的特定情况下,我打赌瓶颈肯定不是线程同步。这个类可以有一个像这样的头:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@interface MultiThreadFileWriter : NSObject
{
    @private
        FILE * i_outputFile;
        NSLock * i_fileLock;
}
- (id)initWithOutputPath:(NSString *)aFilePath;
- (BOOL)writeBytes:(const void *)bytes ofLength:(size_t)length
    toFileOffset:(off_t)offset;
- (BOOL)writeData:(NSData *)data toFileOffset:(off_t)offset;
- (void)close;
@end

和一个类似于下面的实现:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#import "MultiThreadFileWriter.h"

@implementation MultiThreadFileWriter

- (id)initWithOutputPath:(NSString *)aFilePath
{
    self = [super init];
    if (self) {
        i_fileLock = [[NSLock alloc] init];
        i_outputFile = fopen([aFilePath UTF8String], "w");
        if (!i_outputFile || !i_fileLock) {
            [self release];
            self = nil;
        }
    }
    return self;
}

- (void)dealloc
{
    [self close];
    [i_fileLock release];
    [super dealloc];
}

- (BOOL)writeBytes:(const void *)bytes ofLength:(size_t)length
    toFileOffset:(off_t)offset
{
    BOOL success;

    [i_fileLock lock];
    success = i_outputFile != NULL
        && fseeko(i_outputFile, offset, SEEK_SET) == 0
        && fwrite(bytes, length, 1, i_outputFile) == 1;
    [i_fileLock unlock];
    return success;
}

- (BOOL)writeData:(NSData *)data toFileOffset:(off_t)offset
{
    return [self writeBytes:[data bytes] ofLength:[data length]
        toFileOffset:offset
    ];
}

- (void)close
{
    [i_fileLock lock];
    if (i_outputFile) {
        fclose(i_outputFile);
        i_outputFile = NULL;
    }
    [i_fileLock unlock];
}
@end

锁可以通过各种方式避免。使用中央分派和数据块来调度串行队列上的查找+写入操作将会起作用。另一种方法是使用UNIX ( POSIX )文件处理程序,而不是标准的C处理程序(open()int,而不是FILE *fopen()),多次复制处理程序(dup()函数),然后将每个处理程序放在不同的文件偏移量上,这避免了在每次写入和锁定时进一步寻找操作,因为POSIX I/O是线程安全的。然而,这两种实现都会稍微复杂一些,可移植性较差,并且没有可测量的速度改进。

票数 3
EN

Stack Overflow用户

发布于 2012-02-17 01:49:26

到目前为止,给出的答案有一些明显的缺点:

使用系统调用的

  • 文件i/o肯定有一些缺点,因为内存中的locking.
  • Caching部件会在内存受限的环境中导致严重的问题。(即任何计算机)

一种线程安全、高效、无锁的方法是使用内存映射,其工作原理如下:

为read/write

  • mmap()
  • 创建(至少)文件总长度的结果文件到内存中的某个位置。文件现在“存在”在内存中的接收部分中,在文件中的右偏移处跟踪所有的部分是否已经接收到(例如,通过在主线程上张贴一些选择器来获取接收到的每个部分,并对内存进行stored)
  • munmap()
  • close()

实际的编写是由内核处理的--您的程序永远不会发出任何形式的write系统调用。内存映射通常没有什么缺点,被广泛用于共享库之类的东西。

更新:一段代码可以说超过1000个单词...这是基于锁的多线程文件写入器的mmap版本。注意,写入被简化为一个简单的memcpy,它不会失败(!!),因此没有要检查的BOOL success。性能相当于基于锁的版本。(通过并行写入100个1mb块进行测试)

关于基于mmap的方法的"overkill“的评论:这种方法使用更少的代码行,不需要锁定,在编写时不太可能阻塞,在编写时不需要检查返回值。唯一的“过度杀伤力”是,它要求开发人员理解另一个概念,而不是好的旧的读/写文件I/O。

直接读入mmapped内存区域的可能性被省略了,但实现起来相当简单。您可以直接在文件中使用read(fd,i_filedata+offset,length);recv(socket,i_filedata+offset,length,flags);

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@interface MultiThreadFileWriterMMap : NSObject
{
@private
    FILE * i_outputFile;
    NSUInteger i_length;
    unsigned char *i_filedata;
}

- (id)initWithOutputPath:(NSString *)aFilePath length:(NSUInteger)length;
- (void)writeBytes:(const void *)bytes ofLength:(size_t)length
      toFileOffset:(off_t)offset;
- (void)writeData:(NSData *)data toFileOffset:(off_t)offset;
- (void)close;
@end

#import "MultiThreadFileWriterMMap.h"
#import <sys/mman.h>
#import <sys/types.h>

@implementation MultiThreadFileWriterMMap

- (id)initWithOutputPath:(NSString *)aFilePath length:(NSUInteger)length
{
    self = [super init];
    if (self) {
        i_outputFile = fopen([aFilePath UTF8String], "w+");
        i_length = length;
        if ( i_outputFile ) {
            ftruncate(fileno(i_outputFile), i_length);
            i_filedata = mmap(NULL,i_length,PROT_WRITE,MAP_SHARED,fileno(i_outputFile),0);
            if ( i_filedata == MAP_FAILED ) perror("mmap");
        }
        if ( !i_outputFile || i_filedata==MAP_FAILED ) {
            [self release];
            self = nil;
        }
    }
    return self;
}

- (void)dealloc
{
    [self close];
    [super dealloc];
}

- (void)writeBytes:(const void *)bytes ofLength:(size_t)length
      toFileOffset:(off_t)offset
{
    memcpy(i_filedata+offset,bytes,length);
}

- (void)writeData:(NSData *)data toFileOffset:(off_t)offset
{
    memcpy(i_filedata+offset,[data bytes],[data length]);
}

- (void)close
{
    munmap(i_filedata,i_length);
    i_filedata = NULL;
    fclose(i_outputFile);
    i_outputFile = NULL;
}

@end
票数 10
EN

Stack Overflow用户

发布于 2012-02-16 22:47:27

将段对象排入队列,因为它们被接收到写线程。写线程应该保留一个无序对象的列表,以便实际的磁盘写入是顺序的。如果一个片段下载失败,它可以被推回到下载线程池中进行另一次尝试(也许应该保留一个内部重试计数)。我建议使用段对象池来防止一个段的一个或多个下载失败,从而在下载后段并将其添加到列表中时导致失控的内存使用。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9319874

复制
相关文章
scanf从文件中读入,printf写入到文件
重定向方式读写文件 #include <stdio.h> #define LOCAL int main() { #ifdef LOCAL freopen("input.txt","r",stdin); //使得scanf从文件input.txt读入 //r只读,如果文件不存在,出错 freopen("output.txt","w",stdout); //使得printf写入文件output.txt //w只写,如果文件不存在,建立新文件 #en
谙忆
2021/01/19
7280
Redo 日志从产生到写入日志文件
对于这样的剧情,想必大家不会陌生:美国大片中拯救世界的英雄,平时看起来跟普通人没啥区别,甚至还可能会有点让人看不上。
csch
2022/09/05
4720
Redo 日志从产生到写入日志文件
使用SparkSQL实现多线程分页查询并写入文件
一、由于具有多张宽表且字段较多,每个宽表数据大概为4000万条,根据业务逻辑拼接别名,并每张宽表的固定字段进行left join 拼接SQL。这样就能根据每个宽表的主列,根据每个宽表的不同字段关联出一张新的集合。由于下来要进行分页查询,如果要使用SparkSQL进行分页查询,需要增加序号列,那么就在刚才的Sql之前增加一句 create table tableName as SELECT  ROW_NUMBER() OVER() as id,* from (拼接的SQL) 就可创建一张带自增序列的,业务需要字段的几张宽表的关联集合,方便下来分页。
用户3003813
2018/09/06
1.4K0
java写入文件
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/106359.html原文链接:https://javaforall.cn
全栈程序员站长
2022/06/30
2K0
lua文件写入
mode 作用 r 读,文件不存在则报错 w 写,若文件存在则覆盖重写,若文件不存在则新建 a 写,若文件不存在,则新建;如果文件存在,则在文件尾追加要写的内容 r+ 读写,文件不存在则报错 w+ 读写,若文件存在则覆盖重写,若文件不存在则新建 a+ 读写,若文件不存在,则新建;如果文件存在,则在文件尾追加要写的内容 b 以二进制模式打开文件 file=io.open("/test.txt","r") io.input(file)-- 设置默认输入文件 print(io.read()) io.close(
司夜
2023/03/31
2.1K0
文件操作——写入
前面我们说到了文件的读取,读取的文件是我们手动创建的txt文本文档,VBA也是可以对文件进行写操作的。
xyj
2020/07/28
2.9K0
文件操作——写入
Jmeter写入文件
一. 场景 之前我们推文讨论过如何使用jmeter读取文件, 比如csv, txt文件读取, 只要配置csv数据文件, 即可非常容易的从文件中读取想要的数据, 但是如果数据已经从API或者DB中获取
louiezhou001
2019/07/25
2.3K0
Jmeter写入文件
19.JAVA-从文件中解析json、并写入Json文件(详解)
json与xml相比, 对数据的描述性比XML较差,但是数据体积小,传递速度更快.
诺谦
2019/12/19
12.2K0
python文件操作读取文件写入文件
要使用文本文件中的信息,首先需要将信息读取到内存中。为此,你可以一次性读取文件的全部内容,也可以以每次一行的方式逐步读取。
章鱼喵
2018/09/26
11.3K0
vim打开多个文件、同时显示多个文件、在文件之间切换 打开多个文件:
1.vim还没有启动的时候: 在终端里输入 vim file1 file2 ... filen便可以打开所有想要打开的文件 2.vim已经启动 输入 :open file 可以再打开一个文件,并且此时vim里会显示出file文件的内容。
sunsky
2020/08/19
15.4K0
文件的读取写入
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
bering
2019/12/03
2.7K0
Python读取文件和写入文件
函数open(filename,mode)用于读取文件,返回一个file object。 所以现在我们的f是一个文件对象
TeeyoHuang
2019/05/25
3.6K0
文件读取和写入
从文件a.txt中读取三个整数,然后把这三个整数保存到b.txt中,两整数之间一个空格。
小Bob来啦
2020/12/15
2.2K0
文件读取和写入
MySQL读取写入文件
MySQL读取和写入文件在ctf或者awd中,常用于读取flag或者写入一个一句话木马,通过特定函数将其写入
vFREE
2022/08/08
5.4K0
【Java多线程】写入同一文件,自定义线程池与线程回收利用 顶
一个文件好几百兆,1个文件大概200万行左右的数据,现在我要解决的问题是,将 csv的数据读出来,组合数据,生成sql文件。
linapex
2019/03/26
2.7K0
如何同时从多个文本文件读取数据
在很多时候,需要对多个文件进行同样的或者相似的处理。例如,你可能会从多个文件中选择数据子集,根据多个文件计算像总计和平均值这样的统计量。当文件数量增加时,手动处理文件的可能性会减小,出错的概率会增加。
TalkPython
2019/05/24
3.9K0
从对象写入XML输出
InterSystems IRIS提供了用于为InterSystems IRIS对象生成XML输出的工具。可以指定XML投影的详细信息,如将对象投影到XML中所述。然后创建一个Writer方法,该方法指定XML输出的整体结构:字符编码、对象的显示顺序、是否包括处理指令等。
用户7741497
2022/07/04
9510
Python将数据写入txt文件_python将内容写入txt文件
readlines() 会把每一行的数据作为一个元素放在列表中返回,读取所有行的数据
全栈程序员站长
2022/11/11
12.5K0
HDFS如何读取文件以及写入文件
成都加米谷大数据科技有限公司是一家专注于大数据人才培养的机构。由来自阿里、华为、京东、星环等国内知名企业的多位技术大牛联合创办,技术底蕴丰厚,勤奋创新,精通主流前沿大数据及人工智能相关技术。
加米谷大数据
2018/07/25
1.9K0
点击加载更多

相似问题

从多个线程写入文件。

26

从多个线程写入文件

11

从多个线程写入文件

60

如何从多个线程写入文件

11

如何同步从多个线程写入文件

15
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文