0

4バイト長のByteArrayにファイルを読み込む方法を知りたいのですが。これらの配列は操作されてから、ファイルに書き込む準備ができている単一の配列に変換し直す必要があります。

編集: コードスニペット。

    var arrays = new List<byte[]>();
    using (var f = new FileStream("file.cfg.dec", FileMode.Open))
    {
        for (int i = 0; i < f.Length; i += 4)
        {
            var b = new byte[4];
            var bytesRead = f.Read(b, i, 4);
            if (bytesRead < 4)
            {
                var b2 = new byte[bytesRead];
                Array.Copy(b, b2, bytesRead);
                arrays.Add(b2);
            }
            else if (bytesRead > 0)
                arrays.Add(b);
        }
    }

    foreach (var b in arrays)
    {
        BitArray source = new BitArray(b);
        BitArray target = new BitArray(source.Length);

        target[26] = source[0];
        target[31] = source[1];
        target[17] = source[2];
        target[10] = source[3];
        target[30] = source[4];
        target[16] = source[5];
        target[24] = source[6];
        target[2] = source[7];
        target[29] = source[8];
        target[8] = source[9];
        target[20] = source[10];
        target[15] = source[11];
        target[28] = source[12];
        target[11] = source[13];
        target[13] = source[14];
        target[4] = source[15];
        target[19] = source[16];
        target[23] = source[17];
        target[0] = source[18];
        target[12] = source[19];
        target[14] = source[20];
        target[27] = source[21];
        target[6] = source[22];
        target[18] = source[23];
        target[21] = source[24];
        target[3] = source[25];
        target[9] = source[26];
        target[7] = source[27];
        target[22] = source[28];
        target[1] = source[29];
        target[25] = source[30];
        target[5] = source[31];

        var back2byte = BitArrayToByteArray(target);

        arrays.Clear();
        arrays.Add(back2byte);
    }

    using (var f = new FileStream("file.cfg.enc", FileMode.Open))
    {
        foreach (var b in arrays)
            f.Write(b, 0, b.Length);
    }

編集2: これは私が望んでいたことを達成する醜いベティに見えるコードです。今、私はパフォーマンスのためにそれを洗練する必要があります...

var arrays_ = new List<byte[]>();
var arrays_save = new List<byte[]>();
var arrays = new List<byte[]>();
using (var f = new FileStream("file.cfg.dec", FileMode.Open))
{
    for (int i = 0; i < f.Length; i += 4)
    {
        var b = new byte[4];
        var bytesRead = f.Read(b, 0, b.Length);
        if (bytesRead < 4)
        {
            var b2 = new byte[bytesRead];
            Array.Copy(b, b2, bytesRead);
            arrays.Add(b2);
        }
        else if (bytesRead > 0)
            arrays.Add(b);
    }
}

foreach (var b in arrays)
{
    arrays_.Add(b);
}
foreach (var b in arrays_)
{
    BitArray source = new BitArray(b);
    BitArray target = new BitArray(source.Length);

    target[26] = source[0];
    target[31] = source[1];
    target[17] = source[2];
    target[10] = source[3];
    target[30] = source[4];
    target[16] = source[5];
    target[24] = source[6];
    target[2] = source[7];
    target[29] = source[8];
    target[8] = source[9];
    target[20] = source[10];
    target[15] = source[11];
    target[28] = source[12];
    target[11] = source[13];
    target[13] = source[14];
    target[4] = source[15];
    target[19] = source[16];
    target[23] = source[17];
    target[0] = source[18];
    target[12] = source[19];
    target[14] = source[20];
    target[27] = source[21];
    target[6] = source[22];
    target[18] = source[23];
    target[21] = source[24];
    target[3] = source[25];
    target[9] = source[26];
    target[7] = source[27];
    target[22] = source[28];
    target[1] = source[29];
    target[25] = source[30];
    target[5] = source[31];

    var back2byte = BitArrayToByteArray(target);

    arrays_save.Add(back2byte);
}

using (var f = new FileStream("file.cfg.enc", FileMode.Open))
{
    foreach (var b in arrays_save)
        f.Write(b, 0, b.Length);
}

編集3: 大きなファイルを4バイトのバイト配列にロードするのは賢明なアイデアではありませんでした...6800万を超える配列が処理および操作されています。それを単一の配列にロードし、それでもビット操作を機能させることが可能かどうか本当に疑問に思います。:/

4

4 に答える 4

3

@igofedのソリューションに似た別の方法は次のとおりです。

var arrays = new List<byte[]>();
using (var f = new FileStream("test.txt", FileMode.Open))
{
    for (int i = 0; i < f.Length; i += 4)
    {
        var b = new byte[4];
        var bytesRead = f.Read(b, i, 4);
        if (bytesRead < 4)
        {
            var b2 = new byte[bytesRead];
            Array.Copy(b, b2, bytesRead);
            arrays.Add(b2);
        }
        else if (bytesRead > 0)
            arrays.Add(b);
    }
}
//make changes to arrays
using (var f = new FileStream("test-out.txt", FileMode.Create))
{
    foreach (var b in arrays)
        f.Write(b, 0, b.Length);
}
于 2012-05-04T16:55:48.377 に答える
2

これがあなたが望むものです:

using (var reader = new StreamReader("inputFileName"))
{
    using (var writer = new StreamWriter("outputFileName"))
    {
        char[] buff = new char[4];
        int readCount = 0;
        while((readCount = reader.Read(buff, 0, 4)) > 0)
        {
            //manipulations with buff

            writer.Write(buff);
        }
    }
}
于 2012-05-04T16:29:35.447 に答える
2
IEnumerable<byte[]> arraysOf4Bytes = File
    .ReadAllBytes(path)
    .Select((b,i) => new{b, i})
    .GroupBy(x => x.i / 4)
    .Select(g => g.Select(x => x.b).ToArray())
于 2012-05-04T16:31:28.513 に答える
2

あなたの「編集3」について...それは実際には元の質問からの逸脱ですが、私は噛みます。

配列のリストが必要な理由はありません。ファイルを4バイトのシーケンスの連続リストに分割し、各シーケンスをループして処理してから、ループして各シーケンスを書き込むだけだからです。あなたははるかに良くすることができます。 注:以下の実装では、長さが4の倍数ではない入力ファイルをチェックまたは処理しません。重要な場合は、演習として残しておきます。

コメントに直接対処するために、ここに単一アレイのソリューションがあります。Listオブジェクトを破棄し、ファイル全体を1つのbyte []配列に読み取り、その配列の4バイトのセクションをコピーしてビット変換を実行し、結果を元に戻します。最後に、すべてを出力ファイルにスラムします。

byte[] data;
using (Stream fs = File.OpenRead("E:\\temp\\test.bmp")) {
    data = new byte[fs.Length];
    fs.Read(data, 0, data.Length);
}

byte[] element = new byte[4];
for (int i = 0; i < data.Length; i += 4) {
    Array.Copy(data, i, element, 0, element.Length);

    BitArray source = new BitArray(element);
    BitArray target = new BitArray(source.Length);

    target[26] = source[0];
    target[31] = source[1];
    // ...
    target[5] = source[31];

    target.CopyTo(data, i);
}

using (Stream fs = File.OpenWrite("E:\\temp\\test_out.bmp")) {
    fs.Write(data, 0, data.Length);
}

1バイト配列を使用しているだけなので、醜い初期読み取りコードはすべてなくなります。処理ループの前に単一の4バイト配列を予約して再利用していることに注意してください。これにより、ガベージコレクターの作業を節約できます。次に、巨大なデータ配列を一度に4バイトループして作業配列にコピーし、それを使用して変換用のBitArrayを初期化します。次に、ブロックの最後のステートメントがBitArrayをバイト配列に変換してコピーします。巨大なデータ配列内の元の場所に直接戻ります。BitArrayToByteArrayあなたがそれを提供しなかったので、これはメソッドを置き換えます。最後に、変換された巨大なデータ配列を叩き出すだけなので、書き込みも簡単です。

元のソリューションを実行したときに、元のテストファイルである100MBでOutOfMemory例外が発生したため、44MBのファイルを使用しました。メモリで650MBを消費し、30秒で実行されました。シングルアレイソリューションは54MBのメモリを使用し、10秒で実行されました。悪い改善ではありません。これは、何百万もの小さな配列オブジェクトを保持することがいかに悪いかを示しています。

于 2012-05-06T03:08:51.930 に答える