2011年7月15日金曜日

DVD-RAMを適当に消去

昔バックアップに使っていたDVD-RAMディスク、内容がいらなくなったので消去しました。 でも、エクスプローラでファイルを消しても目録が消されただけでデータ部分は残っているんですよね? 完全消去をする必要はないデータなんですが、興味があったので完全消去の方法を調べてみました。 wikipediaに載ってました。

cipherコマンド? WindowsXP homeには無いようですね。 Windows7 homeにはありました。 でも、他のサイトで調べたら3回も書き込みするらしいです。 そこまでは必要ないなぁ。

他にフリーソフトがないかも探したんですが、途中で面倒になって自分で乱数で埋めたファイルを作ってディスクを埋めることにしました。 殴り書きで作ったjavaのコードはこんな感じです。

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package createrandomfile;
import java.io.*;
import java.util.Random;

/**
 *
 * @author user
 */
public class CreateRandomFile {
    public static String FILE_NAME = "o:\\randdata";
    //public static int LOOP_TIMES = 620000;
    //public static int CHUNK_SIZE = 8192;
    public static int LOOP_TIMES = 20000;
    public static int CHUNK_SIZE = 262144;

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        CreateRandomFile thisApp = new CreateRandomFile();
        thisApp.run();
    }
    
    public void run()
    {
        long start = System.currentTimeMillis();
        Random rand = new Random(start);
        
        byte[] data = new byte[CHUNK_SIZE];
        
        FileOutputStream out = null;
        try
        {
            out = new FileOutputStream(FILE_NAME);
            for(int i = 0; i < LOOP_TIMES; i++)
            {
                rand.nextBytes(data);
                out.write(data);
                out.flush();
                
                long now = System.currentTimeMillis();
                String elapseStr = elapseTimeToString(start, now);
                System.out.print("\rwrite " + i + "/" + LOOP_TIMES + " " + elapseStr + "             ");
            }
        }
        catch(Exception exc)
        {
            exc.printStackTrace();
        }
        finally
        {
            if(out != null)
            {
                try
                {
                    out.close();
                }
                catch (Exception exc_close)
                {
                    exc_close.printStackTrace();
                }
            }
        }
    }
    
    public String elapseTimeToString(long start, long now)
    {
        String res = "";
        long elapse = (now - start) / 1000;
        
        res = elapse % 60 + "秒";
        elapse /= 60;
        res = elapse % 60 + "分" + res;
        elapse /= 60;
        res = elapse + "時間" + res;
        
        return res;
    }
}

データの塊1つを書き込むごとにflushしてます。 書き込めなくなったら例外が発生して終了。 手抜きで正常系の終了コードすら書いてません。

最初はCHUNK_SIZE=8192にして試してみました。 実際に使ってみると、光学ドライブの出す音がぎこちないです。 CHUNK_SIZEが小さすぎたかな? ドライブの耐久テストみたいになったら嫌だなぁ、ってことで、途中で止めて次の2つで比べてみました。

  1. CHUNK_SIZEを大きく(262144byteに)してもう1度
  2. コードを流用して800MBくらいのファイルをつくり、エクスプローラで容量いっぱいになるまでコピー

音が同じだったらサンプルコードの方で続けて、エクスプローラの方が落ち着いた音なら800MBのファイルを使いまわすことにしましょう。 そう、音で判断です。 DVD-RAMの書き込み音になんて精通してないので判断基準が曖昧すぎるけど、まぁそんな感じで。 どちらが良くても、メディアが埋まりきらなかったら手動で適当にファイルをコピーして埋めて、さらにもう1度フォーマットして削除完了とする予定。

まずはCHUNK_SIZEを大きくしたプログラムを実行。 最初は順調でした。 光学ドライブの書き込み音も落ち着き気味。 しかし、しばらく放っておくとコマンドプロンプト上の表示が3~4秒に1度しか更新されなくなりました。 CHUNK_SIZE=8192のときよりは落ち着いた音だけど、最初とは明らかに違います。 ガベージコレクションのせい? それとも、光学ドライブのキャッシュのせいでしょうか? かかった時間は1時間38分29秒、空き容量230kbです。

次にエクスプローラでファイルコピーしてみました。 音はCHUNK_SIZE=262144byteのコードと大して変わりませんでした。 音が変わらないんなら、自分で書いたコードの方が書き込みしきれない部分が小さくていいかな?

上のコードは乱数で埋めたバッファを1つ書き込むごとにflushしています。 「flushと次のflushの間が少しあくから書き込み音がちょっと大きくなるのか?」と思い、BufferedOutputStreamを使った版も作ってみました。 CHUNK_SIZE=8192です。 上のコードのファイル出力部分を次のように書き換えます。

BufferedOutputStream out = null;
try
{
    out = new BufferedOutputStream(new FileOutputStream(FILE_NAME) );
    for(int i = 0; i < LOOP_TIMES; i++)
    {
        rand.nextBytes(data);
        out.write(data);
        
        long now = System.currentTimeMillis();
        String elapseStr = elapseTimeToString(start, now);
        System.out.print("\rwrite " + i + "/" + LOOP_TIMES + " " + elapseStr + "             ");
    }
    out.flush();
}

結果は失敗です。 光学ドライブのモーター音が加速減速を繰り返してしまいます。 かえってうるさく、ドライブにも悪そうになってしまいました。

最初のコードのCHUNK_SIZE=262144byte版が1番良いみたいですね。 その後、CHUNK_SIZE以下の領域がちょっとあくので、それをBufferedOutputStream版で埋めると残りが少なくなります。

で、この順番で実行するとBufferedOutputStream版でもモーター音がしません。 やはり、光学ドライブのバッファが影響してそうです。

最後に2KBほど書き残しがありました。 これはDVD-RAMディスクのエラー具合によって変わるのかもしれません。 一応、「完全消去のやり方を試す」という趣旨なのでテキストエディタで適当なファイルを作って書き込んでおきました。

サクラエディタで少し書いてセーブを繰り返しました。 正常に書き込めたようですが、ファイルサイズを見ると途中から変化がありません。 どうやら、ディスクに空き領域がないとき、サクラエディターは書き込めなくてもエラーメッセージを出さないようです。 そういうところはしっかりしてそうなイメージだったので意外でした。

まぁ、テキストエディタを使ったのはオマケみたいなものなので、今回は気にしなくてOK。 書き込むメディアによってはサクラエディターを使うとき残り容量を気にしておいた方がよさそうですね。

DVD-RAMをクイックフォーマットして完全?消去終了です。