2

とりわけ、ゼロで埋められたファイルを保存する必要があるコードに取り組んでいます。10MB から 1GB の空のファイルを作成することも期待できます。

これは、次の Unix コマンドに似ている必要があります。

dd if=/dev/zero of=my_image.dsk count=20480

小さなサイズでこの1つの作業を行うことができます:

int totalSize = 1024*1024;
char buf[totalSize];
strcpy(buf,"");

NSData *theData = [NSData dataWithBytes:buf length:sizeof(buf)];

//NSLog(@"%@", theData);
NSLog(@"%lu", sizeof(buf));

[theData writeToFile:@"/Users/foo/Desktop/my_image.dsk" atomically:YES];

しかし、より大きな値 (たとえば、1024*1024*10) を試すと、クラッシュします。だから私は試しました:

NSFileManager *ddd = [[NSFileManager alloc ] init];
[ddd createFileAtPath:@"/Users/foo/Desktop/my_image.dsk" contents:[NSData data] attributes:nil];

空のファイルが作成されますが、ファイル サイズがゼロなので良くありません。ゼロであってはなりません。

答えを見つけるのに何時間も費やしましたが、成功しませんでした。私は Obj-C でこれを行いたいのですが、気が狂う前に C もオプションです。

誰か光をください!

前もって感謝します!

- 編集 -

みんなありがとう、でももう1つ、メモリにすべてを割り当てずに書き込むことは可能ですか?

4

4 に答える 4

4

これは、POSIX API では比較的単純です。

int f = open("filename", O_CREAT|O_EXCL, S_IRUSR|S_IWUSR);
if (f < 0) {
    perror("open filename");
    exit(1);
}

char empty = 0;

pwrite(f, &empty, sizeof(char), <offset into the file>);

オフセットは type の整数を使用して指定さoff_tれますが、特定のニーズに対して十分な大きさではない場合があります。十分な大きさでない場合は、システム API ドキュメントを調べて、64 ビット ファイル インターフェイスを見つけてください。

このアプローチの最も優れた点は、数バイトのプログラム メモリしか必要としないことです。つまり、ファイルを書き込むために 10 ギガバイトを何も割り当てていないということです。

もう 1 つの簡単な方法は、truncate(2)システム コールを使用することです。すべてのプラットフォームが を使用したファイルの拡張をサポートしているわけではありませんが、サポートしているプラ​​ットフォームtruncate(2)では1 回の呼び出しで済みます。

于 2012-01-16T01:00:59.573 に答える
3

使用できますdd。これにより、メモリやアドレス空間を気にせずに、たとえば 10 GB を書き込むことができます。

NSTask *task = [NSTask new];
long size = ...; // Note! dd multiplies this by 512 by default
NSString *path = ...;
[task setLaunchPath:@"/bin/dd"];
[task setArguments:[NSArray arrayWithObjects:@"dd", @"if=/dev/zero",
    [NSString stringWithFormat:@"of=%s", [path fileSystemRepresentation]],
    [NSString stringWithFormat:@"count=%ld", size],
    nil]];
[task launch];
[task waitUntilExit];
if ([task terminationStatus] != 0) {
    // an error occurred...
}
[task release];

利点は、洗練されたユーザーがdd何か問題が発生した場合に殺すことができることです。

サンドボックスについて:これはサンドボックスでも問題なく機能すると思いますが、確実に知りたいと思っています。ドキュメント (リンク) によると、サブプロセスは「それを作成したプロセスのサンドボックスを単純に継承します」。これはまさに、Unix での動作に期待する方法です。

ddApple は OS X が SUSv3 に準拠していると主張しているので、それが定着することは間違いありません。

于 2012-01-16T01:04:00.287 に答える
1

みんな、ありがとう。解決に至りました。これは基本的に、ココア アプリに入れようとしているコードのスケッチです。

正常に動作し、サイズ変数でいくつかの注意が必要なだけで十分だと思います。

long size = 2000*500;

NSString *path = [[NSString alloc] initWithFormat: @"/Users/foo/Desktop/testeFile.dsk"];

NSTask *task = [[NSTask alloc] init];
[task setLaunchPath:@"/bin/dd"];
[task setArguments:[NSArray arrayWithObjects:
                    @"if=/dev/zero",
                    [NSString stringWithFormat:@"of=%s", [path fileSystemRepresentation]],
                    [NSString stringWithFormat:@"count=%ld", size],
                    nil]];
NSLog(@"%@",[task arguments]);
[task launch];

//[task waitUntilExit]; //The app would stuck here.. better use the loop

int cont = 0;
while ([task isRunning]) {
    cont++;
    if(cont%100==0) NSLog(@". %d", cont);
}

if ([task terminationStatus] != 0) {
    NSLog(@"an error occurred...");
}
[task release];
[path release];

NSLog(@"Done!");
于 2012-01-16T19:46:20.247 に答える
1

このコードを試してください:

int totalSize = 1024*1024;
// don't allocate on the stack
char *buf = calloc(totalSize, sizeof(char));

NSData *theData = [NSData dataWithBytesNoCopy:buf length:totalSize];

//NSLog(@"%@", theData);
NSLog(@"%lu", totalSize);

[theData writeToFile:@"/Users/foo/Desktop/my_image.dsk" atomically:YES];

これを試すこともできますが、メモリの浪費は少なく、1 GB のファイルで動作します。

void writeBlankBytes(FILE *file, size_t numKB)
{
    static char *oneKBZero = NULL;

    if (oneKBZero == NULL)
    {
        oneKBZero = calloc(1024, sizeof(char));
    }

    for (int i = 0; i < numKB; i++) {
        fwrite(oneKBZero, 1, 1024, file);
    }
}
于 2012-01-16T00:55:26.880 に答える